From cd998aaadd946d023567381a59512c639932e468 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 16 Sep 2007 16:23:21 +0000 Subject: [PATCH 001/101] Initial checkin of cloth files + changes --- extern/bullet2/src/Bullet-C-Api.h | 15 + .../bullet2/src/BulletDynamics/CMakeLists.txt | 1 + .../BulletDynamics/Dynamics/Bullet-C-Api.cpp | 92 + extern/bullet2/src/SConscript | 1 + source/blender/blenkernel/BKE_cloth.h | 243 +++ source/blender/blenkernel/SConscript | 1 + source/blender/blenkernel/intern/cloth.c | 1344 +++++++++++++++ source/blender/blenkernel/intern/collision.c | 638 +++++++ source/blender/blenkernel/intern/implicit.c | 1511 +++++++++++++++++ source/blender/blenkernel/intern/kdop.c | 861 ++++++++++ source/blender/blenkernel/intern/modifier.c | 105 ++ source/blender/blenloader/intern/readfile.c | 15 +- source/blender/blenloader/intern/writefile.c | 16 + source/blender/include/butspace.h | 7 + source/blender/makesdna/DNA_cloth_types.h | 150 ++ source/blender/makesdna/DNA_modifier_types.h | 11 + source/blender/makesdna/intern/makesdna.c | 2 + source/blender/src/buttons_object.c | 291 +++- 18 files changed, 5299 insertions(+), 5 deletions(-) create mode 100644 extern/bullet2/src/Bullet-C-Api.h create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp create mode 100644 source/blender/blenkernel/BKE_cloth.h create mode 100644 source/blender/blenkernel/intern/cloth.c create mode 100644 source/blender/blenkernel/intern/collision.c create mode 100644 source/blender/blenkernel/intern/implicit.c create mode 100644 source/blender/blenkernel/intern/kdop.c create mode 100644 source/blender/makesdna/DNA_cloth_types.h diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h new file mode 100644 index 00000000000..2d35383e902 --- /dev/null +++ b/extern/bullet2/src/Bullet-C-Api.h @@ -0,0 +1,15 @@ +#ifndef Bullet_C_API_H +#define Bullet_C_API_H + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +double plNearestPoints(float p[3][3], float q[3][3], float *pa, float *pb, float normal[3]); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif + diff --git a/extern/bullet2/src/BulletDynamics/CMakeLists.txt b/extern/bullet2/src/BulletDynamics/CMakeLists.txt index 79e07b7f77b..4cda87a146a 100644 --- a/extern/bullet2/src/BulletDynamics/CMakeLists.txt +++ b/extern/bullet2/src/BulletDynamics/CMakeLists.txt @@ -14,6 +14,7 @@ ADD_LIBRARY(LibBulletDynamics Dynamics/btDiscreteDynamicsWorld.cpp Dynamics/btSimpleDynamicsWorld.cpp Dynamics/btRigidBody.cpp + Dynamics/Bullet-C-Api.cpp Vehicle/btRaycastVehicle.cpp Vehicle/btWheelInfo.cpp ) diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp new file mode 100644 index 00000000000..2ae30e851dc --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp @@ -0,0 +1,92 @@ +#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 p[3][3], float q[3][3], float *pa, float *pb, float normal[3]) +{ + btTriangleShape trishapeA(btVector3(p[0][0], p[0][1], p[0][2]), btVector3(p[1][0], p[1][1], p[1][2]), btVector3(p[2][0], p[2][1], p[2][2])); + trishapeA.setMargin(0.001f); + + btTriangleShape trishapeB(btVector3(q[0][0], q[0][1], q[0][2]), btVector3(q[1][0], q[1][1], q[1][2]), btVector3(q[2][0], q[2][1], q[2][2])); + trishapeB.setMargin(0.001f); + + // 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; +} + + diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index 6280c49066d..127752777c8 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -33,6 +33,7 @@ bulletdyn_src = ["BulletDynamics/ConstraintSolver/btContactConstraint.cpp", "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp", "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp", "BulletDynamics/Dynamics/btRigidBody.cpp", + "BulletDynamics/Dynamics/Bullet-C-Api.cpp", "BulletDynamics/Vehicle/btRaycastVehicle.cpp", "BulletDynamics/Vehicle/btWheelInfo.cpp"] collision_src = ["BulletCollision/BroadphaseCollision/btAxisSweep3.cpp", diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h new file mode 100644 index 00000000000..e843079f412 --- /dev/null +++ b/source/blender/blenkernel/BKE_cloth.h @@ -0,0 +1,243 @@ +/** +* BKE_cloth.h +* +* $Id: BKE_cloth.h,v 1.1 2007/08/01 02:07:27 daniel Exp $ +* +* ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. The Blender +* Foundation also sells licenses for use in proprietary software under +* the Blender License. See http://www.blender.org/BL/ for information +* about this. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* The Original Code is Copyright (C) Blender Foundation. +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): none yet. +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ +#ifndef BKE_CLOTH_H +#define BKE_CLOTH_H + +#include "BKE_DerivedMesh.h" +#include "DNA_customdata_types.h" +#include "BKE_customdata.h" +#include "DNA_meshdata_types.h" + +struct Object; +struct Cloth; +struct MFace; +struct DerivedMesh; + +// this is needed for inlining behaviour +#ifndef _WIN32 + #define LINUX + #define DO_INLINE inline +#else + #define DO_INLINE +#endif + + +/* goal defines */ +#define SOFTGOALSNAP 0.999f + +/* This is approximately the smallest number that can be +* represented by a float, given its precision. */ +#define ALMOST_ZERO 0.0000001 + +/* Bits to or into the ClothVertex.flags. */ +#define CVERT_FLAG_PINNED 1 +#define CVERT_FLAG_COLLISION 2 + + +// 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 +{ + CSIMSETT_FLAG_RESET = (1 << 1), // The CM object requires a reinitializaiton. + CSIMSETT_FLAG_COLLOBJ = (1 << 2), // object is only collision object, no cloth simulation is done + CSIMSETT_FLAG_GOAL = (1 << 3), // we have goals enabled + CSIMSETT_FLAG_CCACHE_FREE_ALL = (1 << 4), // delete all from cache + CSIMSETT_FLAG_CCACHE_FREE_PART = (1 << 5), // delete some part of cache + CSIMSETT_FLAG_TEARING_ENABLED = (1 << 6), // true if tearing is enabled +} CSIMSETT_FLAGS; + +/* Spring types as defined in the paper.*/ +typedef enum +{ + STRUCTURAL = 0, + SHEAR, + BENDING, +} springType; + +/* SPRING FLAGS */ +typedef enum +{ + CSPRING_FLAG_DEACTIVATE = (1 << 1), +} CSPRINGS_FLAGS; + +// needed for buttons_object.c +void cloth_cache_free(ClothModifierData *clmd, float time); + +// needed for cloth.c +void implicit_set_positions (ClothModifierData *clmd); + +// from cloth.c, needed for modifier.c +void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numverts); + +// used in collision.c +typedef struct Tree { + struct Tree *nodes[4]; // 4 children --> quad-tree + struct Tree *parent; + struct Tree *nextLeaf; + struct Tree *prevLeaf; + float bv[26]; // Bounding volume of all nodes / we have 7 axes on a 14-DOP + unsigned int tri_index; // this saves the index of the face + int count_nodes; // how many nodes are used + int traversed; // how many nodes already traversed until this level? + int isleaf; +} Tree; + +typedef struct Tree TreeNode; + +typedef struct BVH{ + unsigned int numfaces; + unsigned int numverts; + ClothVertex *verts; // just a pointer to the original datastructure + MFace *mfaces; // just a pointer to the original datastructure + struct LinkNode *tree; + TreeNode *root; // TODO: saving the root --> is this really needed? YES! + TreeNode *leaf_tree; /* Tail of the leaf linked list. */ + TreeNode *leaf_root; /* Head of the leaf linked list. */ + float epsilon; /* epslion is used for inflation of the k-dop */ + int flags; /* bvhFlags */ +} BVH; + +typedef void (*CM_COLLISION_RESPONSE) (ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2); + + +///////////////////////////////////////////////// +// collision.c +//////////////////////////////////////////////// + +// needed for implicit.c +void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2); +int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RESPONSE collision_response, float dt); + +//////////////////////////////////////////////// + + +///////////////////////////////////////////////// +// kdop.c +//////////////////////////////////////////////// + +// needed for implicit.c +void bvh_update_static(ClothModifierData * clmd, BVH * bvh); +void bvh_update_moving(ClothModifierData * clmd, BVH * bvh); + +// needed for cloth.c +void bvh_free(BVH * bvh); +BVH *bvh_build (ClothModifierData *clmd, float epsilon); + +// needed for collision.c +int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response); + +//////////////////////////////////////////////// + + + +///////////////////////////////////////////////// +// cloth.c +//////////////////////////////////////////////// +void cloth_free_modifier (ClothModifierData *clmd); +void cloth_init (ClothModifierData *clmd); +void cloth_deform_verts(struct Object *ob, float framenr, float (*vertexCos)[3], int numVerts, void *derivedData, ClothModifierData *clmd); +void cloth_update_normals (ClothVertex *verts, int nVerts, MFace *face, int totface); + +//////////////////////////////////////////////// + + +/* Typedefs for function pointers we need for solvers and collision detection. */ +typedef void (*CM_COLLISION_SELF) (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, + CM_COLLISION_SELF self_collision, CM_COLLISION_OBJ obj_collision); + int (*free) (ClothModifierData *clmd); +} CM_SOLVER_DEF; + + +/* new C implicit simulator */ +int implicit_init (Object *ob, ClothModifierData *clmd); +int implicit_free (ClothModifierData *clmd); +int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors, + CM_COLLISION_SELF self_collision, CM_COLLISION_OBJ obj_collision); + +/* used for caching in implicit.c */ +typedef struct Frame +{ + ClothVertex *verts; + ClothSpring *springs; + float time; /* we need float since we want to support sub-frames */ +} Frame; + +/* used for collisions in collision.c */ +typedef struct CollPair +{ + unsigned int face1; // cloth face + unsigned int face2; // object face + double distance; // magnitude of vector + float normal[3]; + float vector[3]; // unnormalized collision vector: p2-p1 + float p1[3], p2[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 + int quadA, quadB; // indicates the used triangle of the quad: 0 means verts 1,2,3; 1 means verts 4,1,3 +} CollPair; + + +#endif + diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 5316c50694a..3403490b778 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -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 += ' ' + env['BF_OPENGL_INC'] incs += ' ' + env['BF_ZLIB_INC'] diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c new file mode 100644 index 00000000000..4b4aa2d0d1d --- /dev/null +++ b/source/blender/blenkernel/intern/cloth.c @@ -0,0 +1,1344 @@ +/* cloth.c +* +* +* ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. The Blender +* Foundation also sells licenses for use in proprietary software under +* the Blender License. See http://www.blender.org/BL/ for information +* about this. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* The Original Code is Copyright (C) Blender Foundation +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): none yet. +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + + +#include +#include +#include + +#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" + +#ifdef _WIN32 +void tstart(void) +{ +} +void tend(void) +{ + +} +double tval() +{ + return 0; +} +#else +#include +static struct timeval _tstart, _tend; +static struct timezone tz; +void tstart(void) +{ + gettimeofday(&_tstart, &tz); +} +void tend(void) +{ + gettimeofday(&_tend,&tz); +} +double tval() +{ + double t1, t2; + t1 = (double)_tstart.tv_sec + (double)_tstart.tv_usec/(1000*1000); + t2 = (double)_tend.tv_sec + (double)_tend.tv_usec/(1000*1000); + return t2-t1; +} +#endif + +/* Our available solvers. */ +// 255 is the magic reserved number, so NEVER try to put 255 solvers in here! +// 254 = MAX! +static CM_SOLVER_DEF solvers [] = { + { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free }, + // { "Implicit C++", CM_IMPLICITCPP, implicitcpp_init, implicitcpp_solver, implicitcpp_free }, +}; + +#define DEBUG_CLOTH_VERBOSE 1000 +static int DEBUG_CLOTH = 0; +/* ********** cloth engine ******* */ +/* Prototypes for internal functions. +*/ +static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3], unsigned int numverts); +static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm); +static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float (*vertexCos)[3], unsigned int numverts); +static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float (*vertexCos)[3], unsigned int numverts); +int cloth_build_springs(Cloth *cloth, DerivedMesh *dm); +static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup); +/****************************************************************************** +* +* External interface called by modifier.c clothModifier functions. +* +******************************************************************************/ +/** +* cloth_init - creates a new cloth simulation. +* +* 1. create object +* 2. fill object with standard values or with the GUI settings if given +*/ +void cloth_init (ClothModifierData *clmd) +{ + /* Initialize our new data structure to reasonable values. */ + clmd->sim_parms.gravity [0] = 0.0; + clmd->sim_parms.gravity [1] = 0.0; + clmd->sim_parms.gravity [2] = -9.81; + clmd->sim_parms.structural = 100.0; + clmd->sim_parms.shear = 100.0; + clmd->sim_parms.bending = 1.0; + clmd->sim_parms.Cdis = 5.0; + clmd->sim_parms.Cvi = 1.0; + clmd->sim_parms.mass = 1.0f; + clmd->sim_parms.stepsPerFrame = 5; + clmd->sim_parms.sim_time = 1.0; + clmd->sim_parms.flags = CSIMSETT_FLAG_RESET; + clmd->sim_parms.solver_type = 0; + clmd->sim_parms.preroll = 0; + clmd->sim_parms.maxspringlen = 10; + clmd->coll_parms.self_friction = 5.0; + clmd->coll_parms.friction = 10.0; + clmd->coll_parms.loop_count = 1; + clmd->coll_parms.epsilon = 0.01f; + + /* These defaults are copied from softbody.c's + * softbody_calc_forces() function. + */ + clmd->sim_parms.eff_force_scale = 1000.0; + clmd->sim_parms.eff_wind_scale = 250.0; + + // also from softbodies + clmd->sim_parms.maxgoal = 1.0f; + clmd->sim_parms.mingoal = 0.0f; + clmd->sim_parms.defgoal = 0.7f; + clmd->sim_parms.goalspring = 100.0f; + clmd->sim_parms.goalfrict = 0.0f; + + clmd->sim_parms.cache = NULL; +} + +// unused in the moment, cloth needs quads from mesh +DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) +{ + DerivedMesh *result = NULL; + int i; + int numverts = dm->getNumVerts(dm); + int numedges = dm->getNumEdges(dm); + int numfaces = dm->getNumFaces(dm); + + MVert *mvert = CDDM_get_verts(dm); + MEdge *medge = CDDM_get_edges(dm); + MFace *mface = CDDM_get_faces(dm); + + MVert *mvert2; + MFace *mface2; + unsigned int numtris=0; + unsigned int numquads=0; + int a = 0; + int random = 0; + int firsttime = 0; + float vec1[3], vec2[3], vec3[3], vec4[3], vec5[3]; + float mag1=0, mag2=0; + + for(i = 0; i < numfaces; i++) + { + if(mface[i].v4) + numquads++; + else + numtris++; + } + + result = CDDM_from_template(dm, numverts, 0, numtris + 2*numquads); + + if(!result) + return NULL; + + // do verts + mvert2 = CDDM_get_verts(result); + for(a=0; av1 = mface[a].v2; + mf->v2 = mface[a].v3; + mf->v3 = mface[a].v4; + } + else + { + mf->v1 = mface[a].v1; + mf->v2 = mface[a].v2; + mf->v3 = mface[a].v3; + } + + mf->v4 = 0; + mf->flag |= ME_SMOOTH; + + test_index_face(mf, NULL, 0, 3); + + if(mface[a].v4) + { + MFace *mf2; + + i++; + + mf2 = &mface2[i]; + /* + DM_copy_face_data(dm, result, a, i, 1); + + *mf2 = *inMF; + */ + + if(random==1) + { + mf2->v1 = mface[a].v1; + mf2->v2 = mface[a].v2; + mf2->v3 = mface[a].v4; + } + else + { + mf2->v1 = mface[a].v4; + mf2->v2 = mface[a].v1; + mf2->v3 = mface[a].v3; + } + mf2->v4 = 0; + mf2->flag |= ME_SMOOTH; + + test_index_face(mf2, NULL, 0, 3); + } + + i++; + } + + CDDM_calc_edges(result); + CDDM_calc_normals(result); + + return result; + +} + + +DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) +{ + DerivedMesh *result = NULL; + unsigned int i = 0, a = 0, j=0; + int numverts = dm->getNumVerts(dm); + int numedges = dm->getNumEdges(dm); + int numfaces = dm->getNumFaces(dm); + + MVert *mvert = CDDM_get_verts(dm); + MEdge *medge = CDDM_get_edges(dm); + MFace *mface = CDDM_get_faces(dm); + + MVert *mvert2; + MFace *mface2; + unsigned int numtris=0; + unsigned int numquads=0; + EdgeHash *edgehash = NULL; + Cloth *cloth = clmd->clothObject; + ClothSpring *springs = cloth->springs; + unsigned int numsprings = cloth->numsprings; + + // create spring tearing hash + edgehash = BLI_edgehash_new(); + + for(i = 0; i < numsprings; i++) + { + if((springs[i].flags & CSPRING_FLAG_DEACTIVATE) + &&(!BLI_edgehash_haskey(edgehash, springs[i].ij, springs[i].kl))) + { + BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL); + BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL); + j++; + } + } + + // printf("found %d tears\n", j); + + result = CDDM_from_template(dm, numverts, 0, numfaces); + + if(!result) + return NULL; + + // do verts + mvert2 = CDDM_get_verts(result); + for(a=0; av1 = mface[a].v1; + mf->v2 = mface[a].v2; + mf->v3 = mface[a].v3; + mf->v4 = mface[a].v4; + + test_index_face(mf, NULL, 0, 4); + + i++; + } + } + + CDDM_lower_num_faces(result, i); + CDDM_calc_edges(result); + CDDM_calc_normals(result); + + BLI_edgehash_free(edgehash, NULL); + + return result; +} + + +int cloth_cache_search_frame(ClothModifierData *clmd, float time) +{ + Frame *frame = NULL; + LinkNode *search = NULL; + int newtime = time + clmd->sim_parms.preroll; + + Cloth *cloth = NULL; + + if(!clmd) + return 0; + + cloth = clmd->clothObject; + + if(!cloth) + return 0; + + if(clmd->sim_parms.cache) + { + search = clmd->sim_parms.cache; + + // check if frame exists + while(search) + { + frame = search->link; + + if(frame->time == newtime) + break; + + frame = NULL; + + search = search->next; + } + } + + if(!frame) + return 0; + + return 1; +} + +void cloth_cache_get_frame(ClothModifierData *clmd, float time) +{ + Frame *frame = NULL; + LinkNode *search = NULL; + unsigned int i = 0; + Cloth *cloth = NULL; + int newtime = time + clmd->sim_parms.preroll; + + if(clmd) + { + cloth = clmd->clothObject; + + if(!cloth) + return; + + // get cache + if(clmd->sim_parms.cache) + { + search = clmd->sim_parms.cache; + frame = NULL; + // check if frame exists + while(search) + { + frame = search->link; + if(frame->time == newtime) + break; + + frame = NULL; + + search = search->next; + } + + if(frame) + { + if(frame->verts) + { + + // copy ClothVertex struct + memcpy(cloth->verts, frame->verts, cloth->numverts*sizeof(ClothVertex)); + implicit_set_positions(clmd); + } + + if(frame->springs) + { + // copy ClothSpring struct + memcpy(cloth->springs, frame->springs, cloth->numsprings*sizeof(ClothSpring)); + } + } + } + } + +} + +void cloth_cache_set_frame(ClothModifierData *clmd, float time) +{ + Frame *frame = NULL; + unsigned int i = 0; + Cloth *cloth = NULL; + int newtime = time + clmd->sim_parms.preroll; + + if(clmd) + { + cloth = clmd->clothObject; + + if(cloth) + { + // creat new frame cache + frame = (Frame *)MEM_callocN(sizeof(Frame), "cloth frame cache"); + frame->verts = (ClothVertex *)MEM_callocN(sizeof(ClothVertex)*cloth->numverts, "cloth frame vertex cache"); + frame->springs = (ClothSpring *)MEM_callocN(sizeof(ClothSpring)*cloth->numsprings, "cloth frame spring cache"); + frame->time = newtime; + + // copy ClothVertex struct + for(i = 0; i < cloth->numverts; i++) + { + memcpy(&frame->verts[i], &cloth->verts[i], sizeof(ClothVertex)); + } + + // copy ClothSpring struct + for(i = 0; i < cloth->numsprings; i++) + { + memcpy(&frame->springs[i], &cloth->springs[i], sizeof(ClothSpring)); + } + + } + if(frame) + { + if(!clmd->sim_parms.cache) + BLI_linklist_prepend(&clmd->sim_parms.cache, frame); + else + BLI_linklist_append(&clmd->sim_parms.cache, frame); + } + } +} + +void cloth_cache_free(ClothModifierData *clmd, float time) +{ + Frame *frame = NULL; + LinkNode *search, *last_search; + int newtime = time + clmd->sim_parms.preroll; + + // do never free first cached frame + if((newtime<1.0f) && !(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_FREE_ALL)) + return; + + /* Calls the solver and collision frees first as they + * might depend on data in clmd->clothObject. */ + + if (clmd) + { + if(clmd->sim_parms.cache) + { + last_search = search = clmd->sim_parms.cache; + while(search) + { + LinkNode *next= search->next; + frame = search->link; + + // free part of cache, but not preroll cache and first framer + if((clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_FREE_PART) + && (frame->time > newtime)) // do not delete the first frame + { + MEM_freeN(frame->verts); + MEM_freeN(frame->springs); + MEM_freeN(frame); + MEM_freeN(search); + last_search->next = next; + } + else if(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_FREE_ALL) // free COMPLETE cache + { + MEM_freeN(frame->verts); + MEM_freeN(frame->springs); + MEM_freeN(frame); + } + else + last_search = search; + search = next; + } + + if(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_FREE_ALL) + { + BLI_linklist_free(clmd->sim_parms.cache,NULL); + clmd->sim_parms.cache = NULL; + } + } + } + + /* clear flags */ + clmd->sim_parms.flags &= ~CSIMSETT_FLAG_CCACHE_FREE_ALL; + clmd->sim_parms.flags &= ~CSIMSETT_FLAG_CCACHE_FREE_PART; + +} + + +/** +* cloth_deform_verts - simulates one step, framenr is in frames. +* +**/ +void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, + float (*vertexCos)[3], int numverts) +{ + unsigned int i; + unsigned int numedges = -1; + unsigned int numfaces = -1; + MVert *mvert = NULL; + MEdge *medge = NULL; + MFace *mface = NULL; + DerivedMesh *result = NULL, *result2 = NULL; + Cloth *cloth = clmd->clothObject; + unsigned int framenr = (float)G.scene->r.cfra; + float current_time = bsystem_time(ob, (float)G.scene->r.cfra, 0.0); + ListBase *effectors = NULL; + ClothVertex *newframe= NULL, *verts; + Frame *frame = NULL; + LinkNode *search = NULL; + float deltaTime = current_time - clmd->sim_parms.sim_time; + + clmd->sim_parms.dt = 1.0f / (clmd->sim_parms.stepsPerFrame * G.scene->r.frs_sec); + + clmd->sim_parms.sim_time = current_time; + + // check if cloth object was some collision object before and needs freeing now + if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) && (clmd->clothObject != NULL) && (clmd->clothObject->old_solver_type == 255)) + { + // temporary set CSIMSETT_FLAG_COLLOBJ flag for proper freeing + clmd->sim_parms.flags |= CSIMSETT_FLAG_COLLOBJ; + cloth_free_modifier(clmd); + clmd->sim_parms.flags &= ~CSIMSETT_FLAG_COLLOBJ; + } + + // This is for collisions objects: check special case CSIMSETT_FLAG_COLLOBJ + if (clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + { + + // save next position + time + if ((clmd->clothObject == NULL) || (numverts != clmd->clothObject->numverts) ) + { + if(!collobj_from_object (ob, clmd, dm, vertexCos, framenr)) + return; + + if(clmd->clothObject == NULL) + return; + + cloth = clmd->clothObject; + } + + // Save old position + clmd->sim_parms.sim_time_old = clmd->sim_parms.sim_time; + clmd->sim_parms.sim_time = current_time; + + verts = cloth->verts; + + for (i = 0; i < clmd->clothObject->numverts; i++, verts++) + { + // Save the previous position. + VECCOPY (verts->xold, verts->x); + VECCOPY (verts->txold, verts->x); + + // Get the current position. + VECCOPY (verts->x, mvert[i].co); + Mat4MulVecfl(ob->obmat, verts->x); + + // Compute the vertices velocity. + VECSUB (verts->v, verts->x, verts->xold); + } + + return; + } + + if(deltaTime == 1.0f) + { + if ((clmd->clothObject == NULL) || (numverts != clmd->clothObject->numverts) ) + { + if(!cloth_from_object (ob, clmd, dm, vertexCos, numverts)) + return; + + if(clmd->clothObject == NULL) + return; + + cloth = clmd->clothObject; + } + + clmd->clothObject->old_solver_type = clmd->sim_parms.solver_type; + + // Insure we have a clmd->clothObject, in case allocation failed. + if (clmd->clothObject != NULL) + { + if(!cloth_cache_search_frame(clmd, framenr)) + { + verts = cloth->verts; + + /* Force any pinned verts to their constrained location. */ + for (i = 0; i < clmd->clothObject->numverts; i++, verts++) + { + /* Save the previous position. */ + VECCOPY (verts->xold, verts->xconst); + VECCOPY (verts->txold, verts->x); + + /* Get the current position. */ + VECCOPY (verts->xconst, vertexCos[i]); + Mat4MulVecfl(ob->obmat, verts->xconst); + + /* Compute the vertices velocity. */ + VECSUB (verts->v, verts->x, verts->xold); + } + + tstart(); + + /* Call the solver. */ + + if (solvers [clmd->sim_parms.solver_type].solver) + solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors,0,0); + + tend(); + printf("Cloth simulation time: %f\n", (float)tval()); + + cloth_cache_set_frame(clmd, framenr); + + } + else // just retrieve the cached frame + { + cloth_cache_get_frame(clmd, framenr); + } + + // Copy the result back to the object. + cloth_to_object (ob, clmd, vertexCos, numverts); + + // bvh_free(clmd->clothObject->tree); + // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); + } + + } + else if((deltaTime <= 0.0f)||(deltaTime > 1.0f)) + { + if(cloth_cache_search_frame(clmd, framenr)) + { + cloth_cache_get_frame(clmd, framenr); + cloth_to_object (ob, clmd, vertexCos, numverts); + } + } +} + +/* frees all */ +void cloth_free_modifier (ClothModifierData *clmd) +{ + Cloth *cloth = NULL; + + if(!clmd) + return; + + cloth = clmd->clothObject; + + // free our frame cache + clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_ALL; + cloth_cache_free(clmd, 0); + + /* Calls the solver and collision frees first as they + * might depend on data in clmd->clothObject. */ + + if (cloth) + { + // If our solver provides a free function, call it + if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free) + { + solvers [cloth->old_solver_type].free (clmd); + } + + // Free the verts. + if (cloth->verts != NULL) + MEM_freeN (cloth->verts); + + cloth->verts = NULL; + cloth->numverts = -1; + + // Free the springs. + if (cloth->springs != NULL) + MEM_freeN (cloth->springs); + + cloth->springs = NULL; + cloth->numsprings = -1; + + // free BVH collision tree + if(cloth->tree) + bvh_free((BVH *)cloth->tree); + + // we save our faces for collision objects + if(cloth->mfaces) + MEM_freeN(cloth->mfaces); + + if(clmd->clothObject->facemarks) + MEM_freeN(clmd->clothObject->facemarks); + + MEM_freeN (cloth); + clmd->clothObject = NULL; + } + +} + + + +/****************************************************************************** +* +* Internal functions. +* +******************************************************************************/ + +/** +* cloth_to_object - copies the deformed vertices to the object. +* +* This function is a modified version of the softbody.c:softbody_to_object() function. +**/ +static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3], unsigned int numverts) +{ + ClothVertex *verts = NULL; + unsigned int i = 0; + + if (clmd->clothObject) { + verts = clmd->clothObject->verts; + + /* inverse matrix is not uptodate... */ + Mat4Invert (ob->imat, ob->obmat); + + for (i = 0; i < numverts; i++, verts++) + { + VECCOPY (vertexCos[i], verts->x); + Mat4MulVecfl (ob->imat, vertexCos[i]); /* softbody is in global coords */ + } + } + else if (DEBUG_CLOTH) + printf ("cloth_to_object: clmd->clothObject was NULL.\n"); +} + + +/** +* cloth_apply_vgroup - applies a vertex group as specified by type +* +**/ +static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup) +{ + unsigned int i; + int j; + MDeformVert *dvert = NULL; + Cloth *clothObj; + unsigned int numverts = dm->getNumVerts(dm); + float goalfac = 0; + ClothVertex *verts = NULL; + + clothObj = clmd->clothObject; + + /* vgroup is 1 based, decrement so we can match the right group. */ + --vgroup; + + verts = clothObj->verts; + + for (i = 0; i < numverts; i++, verts++) + { + /* so this will definily be below SOFTGOALSNAP */ + verts->goal= 0.0f; + + // LATER ON, support also mass painting here + if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) + { + dvert = dm->getVertData(dm, i, CD_MDEFORMVERT); + if(dvert) + { + for(j = 0; j < dvert->totweight; j++) + { + if(dvert->dw[j].def_nr == vgroup) + { + verts->goal = dvert->dw [j].weight; + + goalfac= ABS(clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal); + verts->goal = (float)pow(verts->goal , 4.0f); + + if(dvert->dw [j].weight >=SOFTGOALSNAP) + { + verts->flags |= CVERT_FLAG_PINNED; + } + + // TODO enable mass painting here, for the moment i let "goals" go first + + break; + } + } + } + } + } +} + +// only meshes supported at the moment +/* collision objects */ +static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float (*vertexCos)[3], unsigned int numverts) +{ + unsigned int i; + MVert *mvert = NULL; + ClothVertex *verts = NULL; + + switch (ob->type) + { + case OB_MESH: + + // mesh input objects need DerivedMesh + if(!dm) + return 0; + + cloth_from_mesh (ob, clmd, dm); + + if (clmd->clothObject != NULL) + { + mvert = CDDM_get_verts(dm); + verts = clmd->clothObject->verts; + + for (i = 0; i < numverts; i++, verts++) + { + VECCOPY (verts->x, mvert[i].co); + Mat4MulVecfl(ob->obmat, verts->x); + verts->flags = 0; + VECCOPY(verts->xold, verts->x); + VECCOPY(verts->txold, verts->x); + VECCOPY(verts->tx, verts->x); + VecMulf(verts->v, 0.0f); + } + clmd->clothObject->tree = bvh_build(clmd,clmd->coll_parms.epsilon); + + } + + return 1; + default: return 0; // TODO - we do not support changing meshes + } +} + +/* +helper function to get proper spring length +when object is rescaled +*/ +float cloth_globallen(float *v1,float *v2,Object *ob) +{ + float p1[3],p2[3]; + VECCOPY(p1,v1); + Mat4MulVecfl(ob->obmat, p1); + VECCOPY(p2,v2); + Mat4MulVecfl(ob->obmat, p2); + return VecLenf(p1,p2); +} + +static void curve_surf_to_cloth(Object *ob, ClothModifierData *clmd, float (*vertexCos)[3]) +{ + Curve *cu= ob->data; + Nurb *nu; + BezTriple *bezt; + float goalfac; + unsigned int a, curindex=0, i=0; + unsigned int numverts, numsprings = 0, setgoal=0; + Cloth *clothObj; + ClothVertex *verts = NULL; + + clmd->clothObject->numverts = numverts= count_curveverts(&cu->nurb); + clothObj = clmd->clothObject; + + if(ob->type==OB_CURVE) + { + numsprings = numverts - BLI_countlist(&cu->nurb); + } + + /* Allocate our vertices. + */ + clmd->clothObject->numverts = numverts; + clmd->clothObject->verts = MEM_callocN (sizeof (ClothVertex) * clmd->clothObject->numverts, "clothVertex"); + if (clmd->clothObject->verts == NULL) + { + cloth_free_modifier (clmd); + modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts."); + return; + } + + verts = clmd->clothObject->verts; + + // copy vertex positions + for (i = 0; i < numverts; i++) + { + VECCOPY (verts->x, vertexCos[i]); + Mat4MulVecfl(ob->obmat, verts->x); + + verts->mass = clmd->sim_parms.mass; + // verts->goal= clmd->sim_parms.defgoal; + verts->flags = 0; + VECCOPY(verts->xold, verts->x); + VECCOPY(verts->xconst, verts->x); + VECCOPY(verts->txold, verts->x); + VecMulf(verts->v, 0.0f); + } + + clmd->clothObject->mfaces = NULL; // update face pointer + clmd->clothObject->numfaces = 0; + + clmd->clothObject->springs = MEM_callocN (sizeof (ClothSpring) * (numsprings), "cloth_springs_alloc"); + + // set vars now + goalfac= ABS(clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal); + // clothObj->verts [i].goal = clmd->sim_parms.mingoal + bezt->weight*goalfac; + + /* apply / set vertex groups */ + if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) + { + if (clmd->sim_parms.vgroup_mass > 0) + { + setgoal = 1; + } + } + +/* + for(nu= cu->nurb.first; nu; nu= nu->next) + { + if(nu->bezt) + { + for(bezt=nu->bezt, a=0; apntsu; a++, bezt++, bp+=3, curindex+=3) + { + if(setgoal) + { + bp->goal= sb->mingoal + bezt->weight*goalfac; + // a little ad hoc changing the goal control to be less *sharp* + bp->goal = (float)pow(bp->goal, 4.0f); + + // all three triples + (bp+1)->goal= bp->goal; + (bp+2)->goal= bp->goal; + } + + if(totspring) + { + if(a>0) + { + bs->v1= curindex-1; + bs->v2= curindex; + bs->strength= 1.0; + bs->order=1; + bs->len= globallen( (bezt-1)->vec[2], bezt->vec[0], ob ); + bs++; + } + bs->v1= curindex; + bs->v2= curindex+1; + bs->strength= 1.0; + bs->order=1; + bs->len= globallen( bezt->vec[0], bezt->vec[1], ob ); + bs++; + + bs->v1= curindex+1; + bs->v2= curindex+2; + bs->strength= 1.0; + bs->order=1; + bs->len= globallen( bezt->vec[1], bezt->vec[2], ob ); + bs++; + } + } + } + else { + for(bpnt=nu->bp, a=0; apntsu*nu->pntsv; a++, bpnt++, bp++, curindex++) + { + if(setgoal) + { + bp->goal= sb->mingoal + bpnt->weight*goalfac; + // a little ad hoc changing the goal control to be less *sharp* + bp->goal = (float)pow(bp->goal, 4.0f); + } + if(totspring && a>0) + { + bs->v1= curindex-1; + bs->v2= curindex; + bs->strength= 1.0; + bs->order=1; + bs->len= globallen( (bpnt-1)->vec, bpnt->vec , ob ); + bs++; + } + } + } + } + */ +} + +// only meshes supported at the moment +static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float (*vertexCos)[3], unsigned int numverts) +{ + unsigned int i = 0; + // dm->getNumVerts(dm); + MVert *mvert = NULL; // CDDM_get_verts(dm); + ClothVertex *verts = NULL; + + /* If we have a clothObject, free it. */ + if (clmd->clothObject != NULL) + cloth_free_modifier (clmd); + + /* Allocate a new cloth object. */ + clmd->clothObject = MEM_callocN (sizeof(Cloth), "cloth"); + if (clmd->clothObject) + { + clmd->clothObject->old_solver_type = -1; + clmd->clothObject->old_collision_type = -1; + } + else if (clmd->clothObject == NULL) + { + modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject."); + return 0; + } + + switch (ob->type) + { + case OB_MESH: + + // mesh input objects need DerivedMesh + if(!dm) + return 0; + + cloth_from_mesh (ob, clmd, dm); + + if (clmd->clothObject != NULL) + { + /* create springs */ + clmd->clothObject->springs = NULL; + clmd->clothObject->numsprings = -1; + + if (!cloth_build_springs (clmd->clothObject, dm) ) + { + modifier_setError (&(clmd->modifier), "Can't build springs."); + return 0; + } + + mvert = CDDM_get_verts(dm); + verts = clmd->clothObject->verts; + + /* set initial values */ + for (i = 0; i < numverts; i++, verts++) + { + VECCOPY (verts->x, mvert[i].co); + Mat4MulVecfl(ob->obmat, verts->x); + + verts->mass = clmd->sim_parms.mass; + verts->goal= clmd->sim_parms.defgoal; + verts->flags = 0; + VECCOPY(verts->xold, verts->x); + VECCOPY(verts->xconst, verts->x); + VECCOPY(verts->txold, verts->x); + VecMulf(verts->v, 0.0f); + } + + /* apply / set vertex groups */ + if (clmd->sim_parms.vgroup_mass > 0) + cloth_apply_vgroup (clmd, dm, clmd->sim_parms.vgroup_mass); + + /* init our solver */ + if (solvers [clmd->sim_parms.solver_type].init) + solvers [clmd->sim_parms.solver_type].init (ob, clmd); + + clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); + + cloth_cache_set_frame(clmd, 1); + } + + return 1; + case OB_LATTICE: + printf("OB_LATTICE\n"); + // lattice_to_softbody(ob); + return 1; + case OB_CURVE: + case OB_SURF: + printf("OB_SURF| OB_CURVE\n"); + curve_surf_to_cloth(ob, clmd, vertexCos); + return 1; + default: return 0; // TODO - we do not support changing meshes + } + + return 0; +} + +static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm) +{ + unsigned int numverts = dm->getNumVerts(dm); + unsigned int numfaces = dm->getNumFaces(dm); + MFace *mface = CDDM_get_faces(dm); + unsigned int i = 0; + + /* Allocate our vertices. + */ + clmd->clothObject->numverts = numverts; + clmd->clothObject->verts = MEM_callocN (sizeof (ClothVertex) * clmd->clothObject->numverts, "clothVertex"); + if (clmd->clothObject->verts == NULL) + { + cloth_free_modifier (clmd); + modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts."); + return; + } + + // save face information + clmd->clothObject->numfaces = numfaces; + clmd->clothObject->mfaces = MEM_callocN (sizeof (MFace) * clmd->clothObject->numfaces, "clothMFaces"); + if (clmd->clothObject->mfaces == NULL) + { + cloth_free_modifier (clmd); + modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->mfaces."); + return; + } + for(i = 0; i < numfaces; i++) + memcpy(&clmd->clothObject->mfaces[i], &mface[i], sizeof(MFace)); + + + // for SIP code + // clmd->clothObject->facemarks = MEM_callocN (sizeof (unsigned char) * clmd->clothObject->numfaces, "clothFaceMarks"); + + /* Free the springs since they can't be correct if the vertices + * changed. + */ + if (clmd->clothObject->springs != NULL) + MEM_freeN (clmd->clothObject->springs); + +} + +/*************************************************************************************** +* SPRING NETWORK BUILDING IMPLEMENTATION BEGIN +***************************************************************************************/ + +int cloth_build_springs(Cloth *cloth, DerivedMesh *dm) +{ + ClothSpring *springs = NULL; + unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0; + unsigned int i = 0; + unsigned int numverts = dm->getNumVerts(dm); + unsigned int numedges = dm->getNumEdges(dm); + unsigned int numfaces = dm->getNumFaces(dm); + MVert *mvert = CDDM_get_verts(dm); + MEdge *medge = CDDM_get_edges(dm); + MFace *mface = CDDM_get_faces(dm); + unsigned int index2 = 0; // our second vertex index + LinkNode **edgelist = NULL; + EdgeHash *edgehash = NULL; + LinkNode *search = NULL; + float temp[3]; + unsigned int temp_index = 0; + ClothSpring *tspring = NULL; + + // error handling + if(numedges==0) + return 0; + + edgelist = MEM_callocN (sizeof (LinkNode *) * numverts, "cloth_edgelist_alloc"); + for(i = 0; i < numverts; i++) + { + edgelist[i] = NULL; + } + + if(cloth->springs) + MEM_freeN(cloth->springs); + + // create spring network hash + edgehash = BLI_edgehash_new(); + + // should be 4 for maximal bending springs, using 5 to be sure ;) + springs = cloth->springs = MEM_callocN (sizeof (ClothSpring) * (numedges + numfaces * 2 + 6 * numverts), "cloth_springs_alloc"); + + // structural springs + for(i = 0; i < numedges; i++) + { + springs[i].ij = medge[i].v1; + springs[i].kl = medge[i].v2; + VECSUB(temp, mvert[springs[i].kl].co, mvert[springs[i].ij].co); + springs[i].restlen = sqrt(INPR(temp, temp)); + springs[i].type = STRUCTURAL; + springs[i].flags = 0; + struct_springs++; + } + + // shear springs + for(i = 0; i < numfaces; i++) + { + temp_index = struct_springs + shear_springs; + + springs[temp_index].ij = mface[i].v1; + springs[temp_index].kl = mface[i].v3; + VECSUB(temp, mvert[springs[temp_index].kl].co, mvert[springs[temp_index].ij].co); + springs[temp_index].restlen = sqrt(INPR(temp, temp)); + springs[temp_index].type = SHEAR; + + BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index])); + BLI_linklist_append(&edgelist[springs[temp_index].kl], &(springs[temp_index])); + + shear_springs++; + temp_index++; + + springs[temp_index].ij = mface[i].v2; + springs[temp_index].kl = mface[i].v4; + VECSUB(temp, mvert[springs[temp_index].kl].co, mvert[springs[temp_index].ij].co); + springs[temp_index].restlen = sqrt(INPR(temp, temp)); + springs[temp_index].type = SHEAR; + + BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index])); + BLI_linklist_append(&edgelist[springs[temp_index].kl], &(springs[temp_index])); + + shear_springs++; + } + + // bending springs + for(i = struct_springs; i < struct_springs+shear_springs; i++) + { + search = edgelist[springs[i].kl]; + while(search) + { + tspring = search->link; + index2 = ((tspring->ij==springs[i].kl) ? (tspring->kl) : (tspring->ij)); + + if(!BLI_edgehash_haskey(edgehash, index2, springs[i].ij) // check for existing spring + && !BLI_edgehash_haskey(edgehash, springs[i].ij, index2) // same + && (index2!=springs[i].ij)) // check if startpoint is equal to endpoint + { + temp_index = struct_springs + shear_springs + bend_springs; + + springs[temp_index].ij = springs[i].ij; + springs[temp_index].kl = index2; + VECSUB(temp, mvert[index2].co, mvert[springs[i].ij].co); + springs[temp_index].restlen = sqrt(INPR(temp, temp)); + springs[temp_index].type = BENDING; + BLI_edgehash_insert(edgehash, springs[temp_index].ij, index2, NULL); + bend_springs++; + + } + search = search->next; + } + } + + cloth->numsprings = struct_springs + shear_springs + bend_springs; + + for(i = 0; i < numverts; i++) + { + BLI_linklist_free(edgelist[i],NULL); + } + if(edgelist) + MEM_freeN(edgelist); + + BLI_edgehash_free(edgehash, NULL); + + return 1; + +} /* cloth_build_springs */ +/*************************************************************************************** +* SPRING NETWORK BUILDING IMPLEMENTATION END +***************************************************************************************/ + diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c new file mode 100644 index 00000000000..cdbac692b35 --- /dev/null +++ b/source/blender/blenkernel/intern/collision.c @@ -0,0 +1,638 @@ +/* collision.c +* +* +* ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. The Blender +* Foundation also sells licenses for use in proprietary software under +* the Blender License. See http://www.blender.org/BL/ for information +* about this. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* The Original Code is Copyright (C) Blender Foundation +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): none yet. +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#include +#include +#include +#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_mesh.h" +#include "BKE_object.h" +#include "BKE_cloth.h" +#include "BKE_modifier.h" +#include "BKE_utildefines.h" +#include "BKE_DerivedMesh.h" +#include "DNA_screen_types.h" +#include "BSE_headerbuttons.h" +#include "BIF_screen.h" +#include "BIF_space.h" +#include "mydevice.h" + +#include "Bullet-C-Api.h" + + +#define DERANDOMIZE 1 + + +enum TRIANGLE_MARK +{ + TM_MV = 1, + TM_ME = 2, + TM_V1 = 4, + TM_V2 = 8, + TM_V3 = 16, + TM_E1 = 32, + TM_E2 = 64, + TM_E3 = 128 +}; + +DO_INLINE int hasTriangleMark(unsigned char mark, unsigned char bit) { return mark & bit; } +DO_INLINE void setTriangleMark(unsigned char *mark, unsigned char bit) { mark[0] |= bit; } +DO_INLINE void clearTriangleMark(unsigned char *mark, unsigned char bit) { mark[0] &= ~bit; } + + +void generateTriangleMarks() +{ + /* + unsigned int firstEdge = 0; + + // 1. Initialization + memset(m_triangleMarks, 0, sizeof(unsigned char) * m_triangleCount); + + // 2. The Marking Process + + // 2.1 Randomly mark triangles for covering vertices. + for (unsigned int v = 0; v < m_vertexCount; ++v) + { + if (vertexCover(v) == 0) + { + + // Randomly select an edge whose first triangle we're going to flag. + +#ifndef DERANDOMIZE + firstEdge = (unsigned int)((float)(random() & 0x7FFFFFFF) / + (float)(0x80000000) * + (float)(m_vertices[v].getEdgeCount())); +#endif + for (unsigned int ofs = 0; ofs < m_vertices[v].getEdgeCount(); ++ofs) + { + unsigned int edgeIdx = (firstEdge + ofs) % m_vertices[v].getEdgeCount(); + if (m_edges[m_vertices[v].getEdge(edgeIdx)].getTriangleCount()) + setTriangleMark(m_triangleMarks[m_edges[m_vertices[v].getEdge(edgeIdx)].getTriangle(0)], TM_MV); + } + } + } + */ + /* If the Cloth is malformed (vertices without adjacent triangles) there might still be uncovered vertices. (Bad luck.) */ + /* + // 2.2 Randomly mark triangles for covering edges. + for (unsigned int e = 0; e < m_edgeCount; ++e) + { + if (m_edges[e].getTriangleCount() && (edgeCover(e) == 0)) + { +#ifndef DERANDOMIZE + setTriangleMark(m_triangleMarks[m_edges[e].getTriangle(static_cast((float)(random() & 0x7FFFFFFF) / + (float)(0x80000000) * + (float)(m_edges[e].getTriangleCount())))], TM_ME); +#else + setTriangleMark(m_triangleMarks[m_edges[e].getTriangle(0)], TM_ME); +#endif + } + } + + + // 3. The Unmarking Process + for (unsigned int t = 0; (t < m_triangleCount); ++t) + { + bool overCoveredVertices = true; + bool overCoveredEdges = true; + for (unsigned char i = 0; (i < 3) && (overCoveredVertices || overCoveredEdges); ++i) + { + + if (vertexCover(m_triangles[t].getVertex(i)) == 1) + overCoveredVertices = false; + if (edgeCover(m_triangles[t].getEdge(i)) == 1) + overCoveredEdges = false; + + assert(vertexCover(m_triangles[t].getVertex(i)) > 0); + assert(edgeCover(m_triangles[t].getEdge(i)) > 0); + } + if (overCoveredVertices) + clearTriangleMark(m_triangleMarks[t], TM_MV); + if (overCoveredEdges) + clearTriangleMark(m_triangleMarks[t], TM_ME); + } + + + // 4. The Bit Masking Process + vector vertexAssigned(m_vertexCount, false); + vector edgeAssigned(m_edgeCount, false); + for (unsigned int t = 0; (t < m_triangleCount); ++t) + { + for (unsigned char i = 0; i < 3; ++i) + { + if (!vertexAssigned[m_triangles[t].getVertex(i)]) + { + vertexAssigned[m_triangles[t].getVertex(i)] = true; + setTriangleMark(m_triangleMarks[t], 1 << (2 + i)); + } + if (!edgeAssigned[m_triangles[t].getEdge(i)]) + { + edgeAssigned[m_triangles[t].getEdge(i)] = true; + setTriangleMark(m_triangleMarks[t], 1 << (5 + i)); + } + } + } + */ +} + + +void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], double *w1, double *w2, double *w3) +{ + float tempV1[3], tempV2[3], tempV4[3]; + double a,b,c,e,f; + + VECSUB (tempV1, p1, p3); /* x1 - x3 */ + VECSUB (tempV2, p2, p3); /* x2 - x3 */ + VECSUB (tempV4, pv, p3); /* pv - x3 */ + + a = INPR (tempV1, tempV1); + b = INPR (tempV1, tempV2); + c = INPR (tempV2, tempV2); + e = INPR (tempV1, tempV4); + f = INPR (tempV2, tempV4); + + + w1[0] = (e * c - b * f) / (a * c - b * b); + w2[0] = (f - b * w1[0]) / c; + w3[0] = 1.0 - w1[0] - w2[0]; +} + +DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3) +{ + to[0] = to[1] = to[2] = 0; + VECADDMUL(to, v1, w1); + VECADDMUL(to, v2, w2); + VECADDMUL(to, v3, w3); +} + +DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal[3], double normalVelocity, + double frictionConstant, double delta_V_n) +{ + float vrel_t_pre[3]; + float vrel_t[3]; + VECSUBS(vrel_t_pre, vrel, normal, normalVelocity); + VECCOPY(vrel_t, vrel_t_pre); + VecMulf(vrel_t, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); + VECSUB(to, vrel_t_pre, vrel_t); + VecMulf(to, 1.0f / 2.0f); +} + +int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, LinkNode **collision_list) +{ + unsigned int i = 0, numverts=0; + int result = 0; + LinkNode *search = NULL; + CollPair *collpair = NULL; + Cloth *cloth1, *cloth2; + MFace *face1, *face2; + double w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + numverts = clmd->clothObject->numverts; + + /* + for(i = 0; i < LIST_LENGTH; i++) + { + // calc SIP-code + // TODO for later: calculateSipCode() + + // calc distance (?) + + // calc impulse + + // apply impulse + } + */ + + for(i = 0; i < numverts; i++) + { + search = collision_list[i]; + + while(search) + { + collpair = search->link; + + face1 = &(cloth1->mfaces[collpair->face1]); + face2 = &(cloth2->mfaces[collpair->face2]); + + // compute barycentric coordinates for both collision points + if(!collpair->quadA) + bvh_compute_barycentric(collpair->p1, + cloth1->verts[face1->v1].txold, + cloth1->verts[face1->v2].txold, + cloth1->verts[face1->v3].txold, + &w1, &w2, &w3); + else + bvh_compute_barycentric(collpair->p1, + cloth1->verts[face1->v4].txold, + cloth1->verts[face1->v1].txold, + cloth1->verts[face1->v3].txold, + &w1, &w2, &w3); + + if(!collpair->quadB) + bvh_compute_barycentric(collpair->p2, + cloth2->verts[face2->v1].txold, + cloth2->verts[face2->v2].txold, + cloth2->verts[face2->v3].txold, + &u1, &u2, &u3); + else + bvh_compute_barycentric(collpair->p2, + cloth2->verts[face2->v4].txold, + cloth2->verts[face2->v1].txold, + cloth2->verts[face2->v3].txold, + &u1, &u2, &u3); + + // Calculate relative velocity. + if(!collpair->quadA) + interpolateOnTriangle(v1, cloth1->verts[face1->v1].v, cloth1->verts[face1->v2].v, cloth1->verts[face1->v3].v, w1, w2, w3); + else + interpolateOnTriangle(v1, cloth1->verts[face1->v4].v, cloth1->verts[face1->v1].v, cloth1->verts[face1->v3].v, w1, w2, w3); + + if(!collpair->quadB) + interpolateOnTriangle(v2, cloth2->verts[face2->v1].v, cloth2->verts[face2->v2].v, cloth2->verts[face2->v3].v, u1, u2, u3); + else + interpolateOnTriangle(v2, cloth2->verts[face2->v4].v, cloth2->verts[face2->v1].v, cloth2->verts[face2->v3].v, u1, u2, u3); + + VECSUB(relativeVelocity, v1, v2); + + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). + magrelVel = INPR(relativeVelocity, collpair->normal); + + // Calculate masses of points. + + // printf("relativeVelocity -> x: %f, y: %f, z: %f\n", relativeVelocity[0], relativeVelocity[1],relativeVelocity[2]); + + // If v_n_mag > 0 the edges are approaching each other. + if(magrelVel > ALMOST_ZERO) + { + // Calculate Impulse magnitude to stop all motion in normal direction. + // const double I_mag = v_n_mag / (1/m1 + 1/m2); + float magnitude_i = magrelVel / 2.0f; // TODO implement masses + float tangential[3], magtangent; + + calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); + + magtangent = INPR(tangential, tangential); + + // Apply friction impulse. + if (magtangent > ALMOST_ZERO) + { + /* + printf("friction applied: %f\n", magtangent); + // TODO check original code + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential); + */ + } + + // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case + + // Apply the impulse and increase impulse counters. + /* + VECADDMUL(cloth1->verts[face1->v1].tv,collpair->normal, -magnitude_i); + VECADDMUL(cloth1->verts[face1->v2].tv,collpair->normal, -magnitude_i); + VECADDMUL(cloth1->verts[face1->v3].tv,collpair->normal, -magnitude_i); + VECADDMUL(cloth1->verts[face1->v4].tv,collpair->normal, -magnitude_i); + */ + + // my try + magtangent = INPR(cloth1->verts[face1->v1].tv, collpair->normal); + VECADDMUL(cloth1->verts[face1->v1].tv, collpair->normal, -magtangent); + + magtangent = INPR(cloth1->verts[face1->v2].tv, collpair->normal); + VECADDMUL(cloth1->verts[face1->v2].tv, collpair->normal, -magtangent); + + magtangent = INPR(cloth1->verts[face1->v3].tv, collpair->normal); + VECADDMUL(cloth1->verts[face1->v3].tv, collpair->normal, -magtangent); + + magtangent = INPR(cloth1->verts[face1->v4].tv, collpair->normal); + VECADDMUL(cloth1->verts[face1->v4].tv, collpair->normal, -magtangent); + + result = 1; + + } + + search = search->next; + } + } + + return result; +} + +// return distance between two triangles using bullet engine +double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData *coll_clmd, unsigned int tri_index1, unsigned int tri_index2, float pa[3], float pb[3], float normal[3], int quadA, int quadB) +{ + MFace *face1=NULL, *face2=NULL; + float a[3][3]; + float b[3][3]; + double distance=0, tempdistance=0; + Cloth *cloth1=NULL, *cloth2=NULL; + float tpa[3], tpb[3], tnormal[3]; + unsigned int indexA=0, indexB=0, indexC=0, indexD=0, indexE=0, indexF=0; + int i = 0; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + face1 = &(cloth1->mfaces[tri_index1]); + face2 = &(cloth2->mfaces[tri_index2]); + + // face a1 + face b1 + VECCOPY(a[0], cloth1->verts[face1->v1].txold); + VECCOPY(a[1], cloth1->verts[face1->v2].txold); + VECCOPY(a[2], cloth1->verts[face1->v3].txold); + + + VECCOPY(b[0], cloth2->verts[face2->v1].txold); + VECCOPY(b[1], cloth2->verts[face2->v2].txold); + VECCOPY(b[2], cloth2->verts[face2->v3].txold); + + distance = plNearestPoints(a,b,pa,pb,normal); + + quadA = quadB = 0; + + for(i = 0; i < 3; i++) + { + if(i == 0) + { + indexA = face1->v4; + indexB = face1->v1; + indexC = face1->v3; + + indexD = face2->v1; + indexE = face2->v2; + indexF = face2->v3; + } + else if(i == 1) + { + indexA = face1->v4; + indexB = face1->v1; + indexC = face1->v3; + + indexD = face2->v4; + indexE = face2->v1; + indexF = face2->v3; + } + else if(i == 2) + { + indexA = face1->v1; + indexB = face1->v2; + indexC = face1->v3; + + indexD = face2->v4; + indexE = face2->v1; + indexF = face2->v3; + } + + // face a2 + face b1 + VECCOPY(a[0], cloth1->verts[indexA].txold); + VECCOPY(a[1], cloth1->verts[indexB].txold); + VECCOPY(a[2], cloth1->verts[indexC].txold); + + + VECCOPY(b[0], cloth2->verts[indexD].txold); + VECCOPY(b[1], cloth2->verts[indexE].txold); + VECCOPY(b[2], cloth2->verts[indexF].txold); + + tempdistance = plNearestPoints(a,b,tpa,tpb,tnormal); + + if(tempdistance < distance) + { + VECCOPY(pa, tpa); + VECCOPY(pb, tpb); + VECCOPY(normal, tnormal); + distance = tempdistance; + + if(i == 0) + { + quadA = 1; quadB = 0; + } + else if(i == 1) + { + quadA = quadB = 1; + } + else if(i == 2) + { + quadA = 0; quadB = 1; + } + } + } + return distance; +} + +void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2) +{ + CollPair *collpair = NULL; + LinkNode **linknode; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + + collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); + linknode = clmd->coll_parms.temp; + + // calc SIPcode (?) + + // calc distance + normal + distance = implicit_tri_check_coherence(clmd, coll_clmd, tree1->tri_index, tree2->tri_index, collpair->p1, collpair->p2, collpair->vector, collpair->quadA, collpair->quadB); + + if (ABS(distance) <= (epsilon + ALMOST_ZERO)) + { + // printf("distance: %f, epsilon: %f\n", (float)distance, epsilon + ALMOST_ZERO); + + collpair->face1 = tree1->tri_index; + collpair->face2 = tree2->tri_index; + + VECCOPY(collpair->normal, collpair->vector); + Normalize(collpair->normal); + + // printf("normal x: %f, y: %f, z: %f\n", collpair->normal[0], collpair->normal[1], collpair->normal[2]); + + collpair->distance = distance; + + BLI_linklist_append(&linknode[tree1->tri_index], collpair); + } + else + { + MEM_freeN(collpair); + } +} + + +int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RESPONSE collision_response, float dt) +{ + Base *base=NULL; + ClothModifierData *coll_clmd=NULL; + Cloth *cloth=NULL; + Object *coll_ob=NULL; + BVH *cloth_bvh=NULL; + unsigned int i=0, numverts=0; + int result = 0; + + if ((clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) + { + return 0; + } + cloth = clmd->clothObject; + cloth_bvh = (BVH *) cloth->tree; + numverts = clmd->clothObject->numverts; + + //////////////////////////////////////////////////////////// + // static collisions + //////////////////////////////////////////////////////////// + + // update cloth bvh + bvh_update_static(clmd, cloth_bvh); + + // search all objects for collision object + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + unsigned int coll_numverts = coll_clmd->clothObject->numverts; + Cloth *coll_cloth = coll_clmd->clothObject; + + LinkNode **collision_list = MEM_callocN (sizeof(LinkNode *)*numverts, "collision_list"); + BVH *coll_bvh = coll_clmd->clothObject->tree; + + if(collision_list) + { + // memset(collision_list, 0, sizeof(LinkNode *)*numverts); + + for(i = 0; i < numverts; i++) + { + collision_list[i] = NULL; + } + + clmd->coll_parms.temp = collision_list; + + // update position of collision object + for(i = 0; i < coll_numverts; i++) + { + VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx); + + VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step); + + VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold); + } + + // update BVH of collision object + bvh_update_static(coll_clmd, coll_bvh); + + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response); + + result += collision_static(clmd, coll_clmd, collision_list); + + // calculate velocities + + // free temporary list + for(i = 0; i < numverts; i++) + { + LinkNode *search = collision_list[i]; + while(search) + { + LinkNode *next= search->next; + CollPair *collpair = search->link; + + if(collpair) + MEM_freeN(collpair); + + search = next; + } + + BLI_linklist_free(collision_list[i],NULL); + } + if(collision_list) + MEM_freeN(collision_list); + + clmd->coll_parms.temp = NULL; + } + + + } + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + //////////////////////////////////////////////////////////// + // update positions + velocities + //////////////////////////////////////////////////////////// + + // TODO + + + //////////////////////////////////////////////////////////// + // moving collisions + //////////////////////////////////////////////////////////// + + // TODO + // bvh_update_moving(clmd, clmd->clothObject->tree); + + return MIN2(result, 1); +} diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c new file mode 100644 index 00000000000..5d386036b7b --- /dev/null +++ b/source/blender/blenkernel/intern/implicit.c @@ -0,0 +1,1511 @@ +/* implicit.c +* +* +* ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. The Blender +* Foundation also sells licenses for use in proprietary software under +* the Blender License. See http://www.blender.org/BL/ for information +* about this. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* The Original Code is Copyright (C) Blender Foundation +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): none yet. +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ +#include +#include +#include +#include +#include "MEM_guardedalloc.h" +/* types */ +#include "DNA_curve_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_cloth_types.h" +#include "DNA_key_types.h" +#include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_lattice_types.h" +#include "DNA_scene_types.h" +#include "DNA_modifier_types.h" +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_threads.h" +#include "BKE_curve.h" +#include "BKE_displist.h" +#include "BKE_effect.h" +#include "BKE_global.h" +#include "BKE_key.h" +#include "BKE_object.h" +#include "BKE_cloth.h" +#include "BKE_modifier.h" +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BIF_editdeform.h" + + +#ifdef _WIN32 +#include +static LARGE_INTEGER _itstart, _itend; +static LARGE_INTEGER ifreq; +void itstart(void) +{ + static int first = 1; + if(first) { + QueryPerformanceFrequency(&ifreq); + first = 0; + } + QueryPerformanceCounter(&_itstart); +} +void itend(void) +{ + QueryPerformanceCounter(&_itend); +} +double itval() +{ + return ((double)_itend.QuadPart - + (double)_itstart.QuadPart)/((double)ifreq.QuadPart); +} +#else +#include +// intrinsics need better compile flag checking +// #include +// #include +#include + +static struct timeval _itstart, _itend; +static struct timezone itz; +void itstart(void) +{ + gettimeofday(&_itstart, &itz); +} +void itend(void) +{ + gettimeofday(&_itend,&itz); +} +double itval() +{ + double t1, t2; + t1 = (double)_itstart.tv_sec + (double)_itstart.tv_usec/(1000*1000); + t2 = (double)_itend.tv_sec + (double)_itend.tv_usec/(1000*1000); + return t2-t1; +} +#endif +/* +#define C99 +#ifdef C99 +#defineDO_INLINE inline +#else +#defineDO_INLINE static +#endif +*/ +struct Cloth; + +////////////////////////////////////////// +/* fast vector / matrix library, enhancements are welcome :) -dg */ +///////////////////////////////////////// + +/* DEFINITIONS */ +typedef float lfVector[3]; +typedef struct fmatrix3x3 { + float m[3][3]; /* 4x4 matrix */ + unsigned int c,r; /* column and row number */ + int pinned; /* is this vertex allowed to move? */ + float n1,n2,n3; /* three normal vectors for collision constrains */ + unsigned int vcount; /* vertex count */ + unsigned int scount; /* spring count */ +} fmatrix3x3; + +/////////////////////////// +// float[3] vector +/////////////////////////// +/* simple vector code */ +/* STATUS: verified */ +DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar) +{ + to[0] = from[0] * scalar; + to[1] = from[1] * scalar; + to[2] = from[2] * scalar; +} +/* simple cross product */ +/* STATUS: verified */ +DO_INLINE void cross_fvector(float to[3], float vectorA[3], float vectorB[3]) +{ + to[0] = vectorA[1] * vectorB[2] - vectorA[2] * vectorB[1]; + to[1] = vectorA[2] * vectorB[0] - vectorA[0] * vectorB[2]; + to[2] = vectorA[0] * vectorB[1] - vectorA[1] * vectorB[0]; +} +/* simple v^T * v product ("outer product") */ +/* STATUS: HAS TO BE verified (*should* work) */ +DO_INLINE void mul_fvectorT_fvector(float to[3][3], float vectorA[3], float vectorB[3]) +{ + mul_fvector_S(to[0], vectorB, vectorA[0]); + mul_fvector_S(to[1], vectorB, vectorA[1]); + mul_fvector_S(to[2], vectorB, vectorA[2]); +} +/* simple v^T * v product with scalar ("outer product") */ +/* STATUS: HAS TO BE verified (*should* work) */ +DO_INLINE void mul_fvectorT_fvectorS(float to[3][3], float vectorA[3], float vectorB[3], float aS) +{ + mul_fvector_S(to[0], vectorB, vectorA[0]* aS); + mul_fvector_S(to[1], vectorB, vectorA[1]* aS); + mul_fvector_S(to[2], vectorB, vectorA[2]* aS); +} + +/* printf vector[3] on console: for debug output */ +void print_fvector(float m3[3]) +{ + printf("%f\n%f\n%f\n\n",m3[0],m3[1],m3[2]); +} + +/////////////////////////// +// long float vector float (*)[3] +/////////////////////////// +/* print long vector on console: for debug output */ +DO_INLINE void print_lfvector(float (*fLongVector)[3], unsigned int verts) +{ + unsigned int i = 0; + for(i = 0; i < verts; i++) + { + print_fvector(fLongVector[i]); + } +} +/* create long vector */ +DO_INLINE lfVector *create_lfvector(unsigned int verts) +{ + // TODO: check if memory allocation was successfull */ + return (lfVector *)MEM_callocN (verts * sizeof(lfVector), "cloth_implicit_alloc_vector"); + // return (lfVector *)cloth_aligned_malloc(&MEMORY_BASE, verts * sizeof(lfVector)); +} +/* delete long vector */ +DO_INLINE void del_lfvector(float (*fLongVector)[3]) +{ + if (fLongVector != NULL) + { + MEM_freeN (fLongVector); + // cloth_aligned_free(&MEMORY_BASE, fLongVector); + } +} +/* copy long vector */ +DO_INLINE void cp_lfvector(float (*to)[3], float (*from)[3], unsigned int verts) +{ + memcpy(to, from, verts * sizeof(lfVector)); +} +/* init long vector with float[3] */ +DO_INLINE void init_lfvector(float (*fLongVector)[3], float vector[3], unsigned int verts) +{ + unsigned int i = 0; + for(i = 0; i < verts; i++) + { + VECCOPY(fLongVector[i], vector); + } +} +/* zero long vector with float[3] */ +DO_INLINE void zero_lfvector(float (*to)[3], unsigned int verts) +{ + memset(to, 0.0f, verts * sizeof(lfVector)); +} +/* multiply long vector with scalar*/ +DO_INLINE void mul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts) +{ + unsigned int i = 0; + + for(i = 0; i < verts; i++) + { + mul_fvector_S(to[i], fLongVector[i], scalar); + } +} +/* multiply long vector with scalar*/ +/* A -= B * float */ +DO_INLINE void submul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts) +{ + unsigned int i = 0; + for(i = 0; i < verts; i++) + { + VECSUBMUL(to[i], fLongVector[i], scalar); + } +} +/* dot product for big vector */ +DO_INLINE float dot_lfvector(float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) +{ + unsigned int i = 0; + +#ifndef _WIN32 + float temp __attribute__ ((aligned (16) ) )= 0.0f; // __declspec(align(16)) +#else + float temp = 0.0f; +#endif + +#pragma omp parallel for reduction(+: temp) schedule(guided, 1) + for(i = 0; i < verts; i++) + { + temp += INPR(fLongVectorA[i], fLongVectorB[i]); + } + return temp; +} +/* A = B + C --> for big vector */ +DO_INLINE void add_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) +{ + + unsigned int i = 0; + + for(i = 0; i < verts; i++) + { + VECADD(to[i], fLongVectorA[i], fLongVectorB[i]); + } + +} +/* A = B + C * float --> for big vector */ +DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts) +{ + unsigned int i = 0; + + for(i = 0; i < verts; i++) + { + VECADDS(to[i], fLongVectorA[i], fLongVectorB[i], bS); + + } +} +/* A = B * float + C * float --> for big vector */ +DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float aS, float (*fLongVectorB)[3], float bS, unsigned int verts) +{ + unsigned int i = 0; + + for(i = 0; i < verts; i++) + { + VECADDSS(to[i], fLongVectorA[i], aS, fLongVectorB[i], bS); + } +} +/* A = B - C * float --> for big vector */ +DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts) +{ + unsigned int i = 0; + for(i = 0; i < verts; i++) + { + VECSUBS(to[i], fLongVectorA[i], fLongVectorB[i], bS); + } + +} +/* A = B - C --> for big vector */ +DO_INLINE void sub_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) +{ + unsigned int i = 0; + + for(i = 0; i < verts; i++) + { + VECSUB(to[i], fLongVectorA[i], fLongVectorB[i]); + } + +} +/////////////////////////// +// 4x4 matrix +/////////////////////////// +/* printf 4x4 matrix on console: for debug output */ +void print_fmatrix(float m3[3][3]) +{ + printf("%f\t%f\t%f\n",m3[0][0],m3[0][1],m3[0][2]); + printf("%f\t%f\t%f\n",m3[1][0],m3[1][1],m3[1][2]); + printf("%f\t%f\t%f\n\n",m3[2][0],m3[2][1],m3[2][2]); +} +/* copy 4x4 matrix */ +DO_INLINE void cp_fmatrix(float to[3][3], float from[3][3]) +{ + // memcpy(to, from, sizeof (float) * 9); + VECCOPY(to[0], from[0]); + VECCOPY(to[1], from[1]); + VECCOPY(to[2], from[2]); +} +/* calculate determinant of 4x4 matrix */ +DO_INLINE float det_fmatrix(float m[3][3]) +{ + return m[0][0]*m[1][1]*m[2][2] + m[1][0]*m[2][1]*m[0][2] + m[0][1]*m[1][2]*m[2][0] + -m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2]; +} +DO_INLINE void inverse_fmatrix(float to[3][3], float from[3][3]) +{ + unsigned int i, j; + float d; + + if((d=det_fmatrix(from))==0) + { + printf("can't build inverse"); + exit(0); + } + for(i=0;i<3;i++) + { + for(j=0;j<3;j++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + int j1=(j+1)%3; + int j2=(j+2)%3; + // reverse indexs i&j to take transpose + to[j][i] = (from[i1][j1]*from[i2][j2]-from[i1][j2]*from[i2][j1])/d; + /* + if(i==j) + to[i][j] = 1.0f / from[i][j]; + else + to[i][j] = 0; + */ + } + } + +} + +/* 4x4 matrix multiplied by a scalar */ +/* STATUS: verified */ +DO_INLINE void mul_fmatrix_S(float matrix[3][3], float scalar) +{ + mul_fvector_S(matrix[0], matrix[0],scalar); + mul_fvector_S(matrix[1], matrix[1],scalar); + mul_fvector_S(matrix[2], matrix[2],scalar); +} + +/* a vector multiplied by a 4x4 matrix */ +/* STATUS: verified */ +DO_INLINE void mul_fvector_fmatrix(float *to, float *from, float matrix[3][3]) +{ + to[0] = matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2]; + to[1] = matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2]; + to[2] = matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2]; +} + +/* 4x4 matrix multiplied by a vector */ +/* STATUS: verified */ +DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][3], float *from) +{ + to[0] = INPR(matrix[0],from); + to[1] = INPR(matrix[1],from); + to[2] = INPR(matrix[2],from); +} +/* 4x4 matrix multiplied by a 4x4 matrix */ +/* STATUS: verified */ +DO_INLINE void mul_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +{ + mul_fvector_fmatrix(to[0], matrixA[0],matrixB); + mul_fvector_fmatrix(to[1], matrixA[1],matrixB); + mul_fvector_fmatrix(to[2], matrixA[2],matrixB); +} +/* 4x4 matrix addition with 4x4 matrix */ +DO_INLINE void add_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +{ + VECADD(to[0], matrixA[0], matrixB[0]); + VECADD(to[1], matrixA[1], matrixB[1]); + VECADD(to[2], matrixA[2], matrixB[2]); +} +/* 4x4 matrix add-addition with 4x4 matrix */ +DO_INLINE void addadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +{ + VECADDADD(to[0], matrixA[0], matrixB[0]); + VECADDADD(to[1], matrixA[1], matrixB[1]); + VECADDADD(to[2], matrixA[2], matrixB[2]); +} +/* 4x4 matrix sub-addition with 4x4 matrix */ +DO_INLINE void addsub_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS) +{ + VECADDSUBSS(to[0], matrixA[0], aS, matrixB[0], bS); + VECADDSUBSS(to[1], matrixA[1], aS, matrixB[1], bS); + VECADDSUBSS(to[2], matrixA[2], aS, matrixB[2], bS); +} +/* A -= B + C (4x4 matrix sub-addition with 4x4 matrix) */ +DO_INLINE void subadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +{ + VECSUBADD(to[0], matrixA[0], matrixB[0]); + VECSUBADD(to[1], matrixA[1], matrixB[1]); + VECSUBADD(to[2], matrixA[2], matrixB[2]); +} +/* A -= B*x + C*y (4x4 matrix sub-addition with 4x4 matrix) */ +DO_INLINE void subadd_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS) +{ + VECSUBADDSS(to[0], matrixA[0], aS, matrixB[0], bS); + VECSUBADDSS(to[1], matrixA[1], aS, matrixB[1], bS); + VECSUBADDSS(to[2], matrixA[2], aS, matrixB[2], bS); +} +/* A = B - C (4x4 matrix subtraction with 4x4 matrix) */ +DO_INLINE void sub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +{ + VECSUB(to[0], matrixA[0], matrixB[0]); + VECSUB(to[1], matrixA[1], matrixB[1]); + VECSUB(to[2], matrixA[2], matrixB[2]); +} +/* A += B - C (4x4 matrix add-subtraction with 4x4 matrix) */ +DO_INLINE void addsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +{ + VECADDSUB(to[0], matrixA[0], matrixB[0]); + VECADDSUB(to[1], matrixA[1], matrixB[1]); + VECADDSUB(to[2], matrixA[2], matrixB[2]); +} +///////////////////////////////////////////////////////////////// +// special functions +///////////////////////////////////////////////////////////////// +/* a vector multiplied and added to/by a 4x4 matrix */ +DO_INLINE void muladd_fvector_fmatrix(float to[3], float from[3], float matrix[3][3]) +{ + to[0] += matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2]; + to[1] += matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2]; + to[2] += matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2]; +} +/* 4x4 matrix multiplied and added to/by a 4x4 matrix and added to another 4x4 matrix */ +DO_INLINE void muladd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +{ + muladd_fvector_fmatrix(to[0], matrixA[0],matrixB); + muladd_fvector_fmatrix(to[1], matrixA[1],matrixB); + muladd_fvector_fmatrix(to[2], matrixA[2],matrixB); +} +/* a vector multiplied and sub'd to/by a 4x4 matrix */ +DO_INLINE void mulsub_fvector_fmatrix(float to[3], float from[3], float matrix[3][3]) +{ + to[0] -= matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2]; + to[1] -= matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2]; + to[2] -= matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2]; +} +/* 4x4 matrix multiplied and sub'd to/by a 4x4 matrix and added to another 4x4 matrix */ +DO_INLINE void mulsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +{ + mulsub_fvector_fmatrix(to[0], matrixA[0],matrixB); + mulsub_fvector_fmatrix(to[1], matrixA[1],matrixB); + mulsub_fvector_fmatrix(to[2], matrixA[2],matrixB); +} +/* 4x4 matrix multiplied+added by a vector */ +/* STATUS: verified */ +DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][3], float from[3]) +{ + to[0] += INPR(matrix[0],from); + to[1] += INPR(matrix[1],from); + to[2] += INPR(matrix[2],from); +} +/* 4x4 matrix multiplied+sub'ed by a vector */ +DO_INLINE void mulsub_fmatrix_fvector(float to[3], float matrix[3][3], float from[3]) +{ + to[0] -= INPR(matrix[0],from); + to[1] -= INPR(matrix[1],from); + to[2] -= INPR(matrix[2],from); +} +///////////////////////////////////////////////////////////////// + +/////////////////////////// +// SPARSE SYMMETRIC big matrix with 4x4 matrix entries +/////////////////////////// +/* printf a big matrix on console: for debug output */ +void print_bfmatrix(fmatrix3x3 *m3) +{ + unsigned int i = 0; + + for(i = 0; i < m3[0].vcount + m3[0].scount; i++) + { + print_fmatrix(m3[i].m); + } +} +/* create big matrix */ +DO_INLINE fmatrix3x3 *create_bfmatrix(unsigned int verts, unsigned int springs) +{ + // TODO: check if memory allocation was successfull */ + fmatrix3x3 *temp = (fmatrix3x3 *)MEM_callocN (sizeof (fmatrix3x3) * (verts + springs), "cloth_implicit_alloc_matrix"); + temp[0].vcount = verts; + temp[0].scount = springs; + return temp; +} +/* delete big matrix */ +DO_INLINE void del_bfmatrix(fmatrix3x3 *matrix) +{ + if (matrix != NULL) + { + MEM_freeN (matrix); + } +} +/* copy big matrix */ +DO_INLINE void cp_bfmatrix(fmatrix3x3 *to, fmatrix3x3 *from) +{ + // TODO bounds checking + memcpy(to, from, sizeof(fmatrix3x3) * (from[0].vcount+from[0].scount) ); +} +/* init the diagonal of big matrix */ +// slow in parallel +DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][3]) +{ + unsigned int i,j; + float tmatrix[3][3] = {{0,0,0},{0,0,0},{0,0,0}}; + + for(i = 0; i < matrix[0].vcount; i++) + { + cp_fmatrix(matrix[i].m, m3); + } + for(j = matrix[0].vcount; j < matrix[0].vcount+matrix[0].scount; j++) + { + cp_fmatrix(matrix[j].m, tmatrix); + } +} +/* init big matrix */ +DO_INLINE void init_bfmatrix(fmatrix3x3 *matrix, float m3[3][3]) +{ + unsigned int i; + + for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++) + { + cp_fmatrix(matrix[i].m, m3); + } +} +/* multiply big matrix with scalar*/ +DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) +{ + unsigned int i = 0; + for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++) + { + mul_fmatrix_S(matrix[i].m, scalar); + } +} +/* SPARSE SYMMETRIC multiply big matrix with long vector*/ +/* STATUS: verified */ +DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (*fLongVector)[3]) +{ + unsigned int i = 0,j=0; + zero_lfvector(to, from[0].vcount); + /* process diagonal elements */ + for(i = 0; i < from[0].vcount; i++) + { + muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); + } + + /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */ + for(j = from[0].vcount; j < from[0].vcount+from[0].scount; j++) + { + muladd_fmatrix_fvector(to[from[j].c], from[j].m, fLongVector[from[j].r]); + muladd_fmatrix_fvector(to[from[j].r], from[j].m, fLongVector[from[j].c]); + } + +} +/* SPARSE SYMMETRIC add big matrix with big matrix: A = B + C*/ +DO_INLINE void add_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) +{ + unsigned int i = 0; + + /* process diagonal elements */ + for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++) + { + add_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); + } + +} +/* SPARSE SYMMETRIC add big matrix with big matrix: A += B + C */ +DO_INLINE void addadd_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) +{ + unsigned int i = 0; + + /* process diagonal elements */ + for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++) + { + addadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); + } + +} +/* SPARSE SYMMETRIC subadd big matrix with big matrix: A -= B + C */ +DO_INLINE void subadd_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) +{ + unsigned int i = 0; + + /* process diagonal elements */ + for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++) + { + subadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); + } + +} +/* A = B - C (SPARSE SYMMETRIC sub big matrix with big matrix) */ +DO_INLINE void sub_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) +{ + unsigned int i = 0; + + /* process diagonal elements */ + for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++) + { + sub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); + } + +} +/* SPARSE SYMMETRIC sub big matrix with big matrix S (special constraint matrix with limited entries) */ +DO_INLINE void sub_bfmatrix_Smatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) +{ + unsigned int i = 0; + + /* process diagonal elements */ + for(i = 0; i < matrix[0].vcount; i++) + { + sub_fmatrix_fmatrix(to[matrix[i].c].m, from[matrix[i].c].m, matrix[i].m); + } + +} +/* A += B - C (SPARSE SYMMETRIC addsub big matrix with big matrix) */ +DO_INLINE void addsub_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) +{ + unsigned int i = 0; + + /* process diagonal elements */ + for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++) + { + addsub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); + } + +} +/* SPARSE SYMMETRIC sub big matrix with big matrix*/ +/* A -= B * float + C * float --> for big matrix */ +/* VERIFIED */ +DO_INLINE void subadd_bfmatrixS_bfmatrixS( fmatrix3x3 *to, fmatrix3x3 *from, float aS, fmatrix3x3 *matrix, float bS) +{ + unsigned int i = 0; + + /* process diagonal elements */ + for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++) + { + subadd_fmatrixS_fmatrixS(to[i].m, from[i].m, aS, matrix[i].m, bS); + } + +} + +/////////////////////////////////////////////////////////////////// +// simulator start +/////////////////////////////////////////////////////////////////// +static float I[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; +static float ZERO[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}; +typedef struct Implicit_Data +{ + lfVector *X, *V, *Xnew, *Vnew, *olddV, *F, *B, *dV, *z; + fmatrix3x3 *A, *dFdV, *dFdX, *S, *P, *Pinv, *bigI; +} Implicit_Data; +int implicit_init (Object *ob, ClothModifierData *clmd) +{ + unsigned int i = 0; + unsigned int pinned = 0; + Cloth *cloth; + ClothVertex *verts; + ClothSpring *springs; + Implicit_Data *id; + + // init memory guard + // MEMORY_BASE.first = MEMORY_BASE.last = NULL; + + cloth = (Cloth *)clmd->clothObject; + verts = cloth->verts; + springs = cloth->springs; + + // create implicit base + id = (Implicit_Data *)MEM_callocN (sizeof(Implicit_Data), "implicit vecmat"); + cloth->implicit = id; + + /* process diagonal elements */ + id->A = create_bfmatrix(cloth->numverts, cloth->numsprings); + id->dFdV = create_bfmatrix(cloth->numverts, cloth->numsprings); + id->dFdX = create_bfmatrix(cloth->numverts, cloth->numsprings); + id->S = create_bfmatrix(cloth->numverts, 0); + id->Pinv = create_bfmatrix(cloth->numverts, cloth->numsprings); + id->P = create_bfmatrix(cloth->numverts, cloth->numsprings); + id->bigI = create_bfmatrix(cloth->numverts, cloth->numsprings); // TODO 0 springs + id->X = create_lfvector(cloth->numverts); + id->Xnew = create_lfvector(cloth->numverts); + id->V = create_lfvector(cloth->numverts); + id->Vnew = create_lfvector(cloth->numverts); + id->olddV = create_lfvector(cloth->numverts); + zero_lfvector(id->olddV, cloth->numverts); + id->F = create_lfvector(cloth->numverts); + id->B = create_lfvector(cloth->numverts); + id->dV = create_lfvector(cloth->numverts); + id->z = create_lfvector(cloth->numverts); + for(i=0;inumverts;i++) + { + id->A[i].r = id->A[i].c = id->dFdV[i].r = id->dFdV[i].c = id->dFdX[i].r = id->dFdX[i].c = id->P[i].c = id->P[i].r = id->Pinv[i].c = id->Pinv[i].r = id->bigI[i].c = id->bigI[i].r = i; + + if(verts [i].flags & CVERT_FLAG_PINNED) + { + id->S[pinned].pinned = 1; + id->S[pinned].c = id->S[pinned].r = i; + pinned++; + } + } + + // S is special and needs specific vcount and scount + id->S[0].vcount = pinned; id->S[0].scount = 0; + + // init springs */ + for(i=0;inumsprings;i++) + { + // dFdV_start[i].r = big_I[i].r = big_zero[i].r = + id->A[i+cloth->numverts].r = id->dFdV[i+cloth->numverts].r = id->dFdX[i+cloth->numverts].r = + id->P[i+cloth->numverts].r = id->Pinv[i+cloth->numverts].r = id->bigI[i+cloth->numverts].r = springs[i].ij; + + // dFdV_start[i].c = big_I[i].c = big_zero[i].c = + id->A[i+cloth->numverts].c = id->dFdV[i+cloth->numverts].c = id->dFdX[i+cloth->numverts].c = + id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = springs[i].kl; + + springs[i].matrix_index = i + cloth->numverts; + } + + for(i = 0; i < cloth->numverts; i++) + { + VECCOPY(id->X[i], verts[i].x); + } + + return 1; +} +int implicit_free (ClothModifierData *clmd) +{ + Implicit_Data *id; + Cloth *cloth; + cloth = (Cloth *)clmd->clothObject; + + if(cloth) + { + id = cloth->implicit; + + if(id) + { + del_bfmatrix(id->A); + del_bfmatrix(id->dFdV); + del_bfmatrix(id->dFdX); + del_bfmatrix(id->S); + del_bfmatrix(id->P); + del_bfmatrix(id->Pinv); + del_bfmatrix(id->bigI); + + del_lfvector(id->X); + del_lfvector(id->Xnew); + del_lfvector(id->V); + del_lfvector(id->Vnew); + del_lfvector(id->olddV); + del_lfvector(id->F); + del_lfvector(id->B); + del_lfvector(id->dV); + del_lfvector(id->z); + + MEM_freeN(id); + } + } + + return 1; +} +DO_INLINE float fb(float length, float L) +{ + float x = length/L; + return (-11.541f*pow(x,4)+34.193f*pow(x,3)-39.083f*pow(x,2)+23.116f*x-9.713f); +} +DO_INLINE float fbderiv(float length, float L) +{ + float x = length/L; + + return (-46.164f*pow(x,3)+102.579f*pow(x,2)-78.166f*x+23.116f); +} + +DO_INLINE float fbstar(float length, float L, float kb, float cb) +{ + float tempfb = kb * fb(length, L); + + float fbstar = cb * (length - L); + + if(tempfb < fbstar) + return fbstar; + else + return tempfb; +} +DO_INLINE float fbstar_jacobi(float length, float L, float kb, float cb) +{ + float tempfb = kb * fb(length, L); + float fbstar = cb * (length - L); + + if(tempfb < fbstar) + { + return cb; + } + else + { + return kb * fbderiv(length, L); + } +} +DO_INLINE void filter(lfVector *V, fmatrix3x3 *S) +{ + unsigned int i=0; + + for(i=0;istarget && conjgrad_loopcount < conjgrad_looplimit)) + { + // Mul(q,A,d); // q = A*d; + mul_bfmatrix_lfvector(q, lA, d); + + filter(q,S); + + a = s/dot_lfvector(d, q, numverts); + + // X = X + d*a; + add_lfvector_lfvectorS(ldV, ldV, d, a, numverts); + + // r = r - q*a; + sub_lfvector_lfvectorS(r, r, q, a, numverts); + + s_prev = s; + s = dot_lfvector(r, r, numverts); + + //d = r+d*(s/s_prev); + add_lfvector_lfvectorS(d, r, d, (s/s_prev), numverts); + + filter(d,S); + + conjgrad_loopcount++; + } + conjgrad_lasterror = s; + + del_lfvector(q); + del_lfvector(d); + del_lfvector(tmp); + del_lfvector(r); + // printf("W/O conjgrad_loopcount: %d\n", conjgrad_loopcount); + + return conjgrad_loopcount(epsilon_sqr*delta0))&& (conjgrad_loopcount++ < conjgrad_looplimit)) +{ +////////////////////////// +// (s) = q = S*A*c +////////////////////////// +// q = A*c; +mul_bfmatrix_lfvector(q, lA, c); +filter(q,S); +////////////////////////// + +////////////////////////// +// alpha = deltanew / (c^T * q) +////////////////////////// +alpha = deltanew/dot_lfvector(c, q, numverts); +////////////////////////// + +//X = X + c*alpha; +add_lfvector_lfvectorS(ldV, ldV, c, alpha, numverts); +//r = r - q*alpha; +sub_lfvector_lfvectorS(r, r, q, alpha, numverts); + +////////////////////////// +// (h) = s = P^-1 * r +////////////////////////// +// s = Pinv * r; +mul_bfmatrix_lfvector(s, Pinv, r); +filter(s,S); +////////////////////////// + +deltaold = deltanew; + +// deltanew = dot(r,s); +deltanew = dot_lfvector(r, s, numverts); + +////////////////////////// +// c = S * (s + (deltanew/deltaold)*c) +////////////////////////// +// c = s + c * (deltanew/deltaold); +add_lfvector_lfvectorS(c, s, c, (deltanew/deltaold), numverts); +filter(c,S); +////////////////////////// + +} +conjgrad_lasterror = deltanew; +del_lfvector(q); +del_lfvector(c); +del_lfvector(tmp); +del_lfvector(r); +del_lfvector(s); +del_lfvector(filterX0); +del_lfvector(p_fb); +del_lfvector(bhat); +printf("Bconjgrad_loopcount: %d\n", conjgrad_loopcount); + +return conjgrad_loopcount 1.0f) ? (1.0f): (L/length))); + sub_fmatrix_fmatrix(to, to, I); + mul_fmatrix_S(to, -k); +} +DO_INLINE void dfdx_damp(float to[3][3], float dir[3],float length,const float vel[3],float rest,float damping) +{ + // inner spring damping vel is the relative velocity of the endpoints. + // return (I-outerprod(dir,dir)) * (-damping * -(dot(dir,vel)/Max(length,rest))); + mul_fvectorT_fvector(to, dir, dir); + sub_fmatrix_fmatrix(to, I, to); + mul_fmatrix_S(to, (-damping * -(INPR(dir,vel)/MAX2(length,rest)))); + +} + +DO_INLINE void calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) +{ + float extent[3]; + float length = 0; + float dir[3] = {0,0,0}; + float vel[3]; + float k = 0.0f; + float L = s->restlen; + float cb = clmd->sim_parms.structural; + + float f[3] = {0,0,0}; + float stretch_force[3] = {0,0,0}; + float bending_force[3] = {0,0,0}; + float damping_force[3] = {0,0,0}; + float dfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; + float dfdv[3][3]; + int needed = 0; + Cloth *cloth = clmd->clothObject; + ClothVertex *verts = cloth->verts; + + // calculate elonglation + VECSUB(extent, X[s->kl], X[s->ij]); + VECSUB(vel, V[s->kl], V[s->ij]); + length = sqrt(INPR(extent, extent)); + + + + if(length > ABS(ALMOST_ZERO)) + { + if(length>L) + { + if((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) + && ((((length-L)*100.0f/L) > clmd->sim_parms.maxspringlen))) // cut spring! + { + s->flags |= CSPRING_FLAG_DEACTIVATE; + return; + } + } + + mul_fvector_S(dir, extent, 1.0f/length); + } + else + { + mul_fvector_S(dir, extent, 0.0f); + } + + + // calculate force of structural springs + if(s->type != BENDING) + { + if(length > L) // only on elonglation + { + needed++; + + k = clmd->sim_parms.structural; + + mul_fvector_S(stretch_force, dir, (k*(length-L))); + + VECADD(f, f, stretch_force); + + // Ascher & Boxman, p.21: Damping only during elonglation + mul_fvector_S(damping_force, extent, clmd->sim_parms.Cdis * ((INPR(vel,extent)/length))); + VECADD(f, f, damping_force); + + dfdx_spring_type1(dfdx, dir,length,L,k); + + dfdv_damp(dfdv, dir,clmd->sim_parms.Cdis); + sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, dfdv); + sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, dfdv); + + add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, dfdv); + + } + } + else // calculate force of bending springs + { + if(length < L) + { + k = clmd->sim_parms.bending; + + needed++; + + mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); + VECADD(f, f, bending_force); + + dfdx_spring_type2(dfdx, dir,length,L,k, cb); + } + } + + if(needed) + { + VECADD(lF[s->ij], lF[s->ij], f); + VECSUB(lF[s->kl], lF[s->kl], f); + + sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, dfdx); + sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, dfdx); + + add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, dfdx); + } +} + +DO_INLINE void calculateTriangleNormal(float to[3], lfVector *X, MFace mface) +{ + float v1[3], v2[3]; + + VECSUB(v1, X[mface.v2], X[mface.v1]); + VECSUB(v2, X[mface.v3], X[mface.v1]); + cross_fvector(to, v1, v2); +} +DO_INLINE void calculatQuadNormal(float to[3], lfVector *X, MFace mface) +{ + float temp = CalcNormFloat4(X[mface.v1],X[mface.v2],X[mface.v3],X[mface.v4],to); + mul_fvector_S(to, to, temp); +} + +void calculateWeightedVertexNormal(ClothModifierData *clmd, MFace *mfaces, float to[3], int index, lfVector *X) +{ + float temp[3]; + int i; + Cloth *cloth = clmd->clothObject; + + for(i = 0; i < cloth->numfaces; i++) + { + // check if this triangle contains the selected vertex + if(mfaces[i].v1 == index || mfaces[i].v2 == index || mfaces[i].v3 == index || mfaces[i].v4 == index) + { + calculatQuadNormal(temp, X, mfaces[i]); + VECADD(to, to, temp); + } + } +} +float calculateVertexWindForce(int index, float wind[3], float vertexnormal[3]) +{ + return fabs(INPR(wind, vertexnormal) * 0.5f); +} + +DO_INLINE void calc_triangle_force(ClothModifierData *clmd, MFace mface, lfVector *F, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors) +{ + +} + +void calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time) +{ + /* Collect forces and derivatives: F,dFdX,dFdV */ + Cloth *cloth = clmd->clothObject; + unsigned int i = 0; + float spring_air = clmd->sim_parms.Cvi * 0.01f; /* viscosity of air scaled in percent */ + float gravity[3]; + float tm2[3][3] = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}}; + ClothVertex *verts = cloth->verts; + ClothSpring *springs = cloth->springs; + MFace *mfaces = cloth->mfaces; + float wind_normalized[3]; + unsigned int numverts = cloth->numverts; + float auxvect[3], velgoal[3], tvect[3]; + float kd, ks; + + + VECCOPY(gravity, clmd->sim_parms.gravity); + mul_fvector_S(gravity, gravity, 0.001f); /* scale gravity force */ + + /* set dFdX jacobi matrix to zero */ + init_bfmatrix(dFdX, ZERO); + /* set dFdX jacobi matrix diagonal entries to -spring_air */ + initdiag_bfmatrix(dFdV, tm2); + + init_lfvector(lF, gravity, numverts); + + submul_lfvectorS(lF, lV, spring_air, numverts); + + /* do goal stuff */ + if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) + { + for(i = 0; i < numverts; i++) + { + if(verts [i].goal < SOFTGOALSNAP) + { + // current_position = xold + t * (newposition - xold) + VECSUB(tvect, verts[i].xconst, verts[i].xold); + mul_fvector_S(tvect, tvect, time); + VECADD(tvect, tvect, verts[i].xold); + + VecSubf(auxvect, tvect, lX[i]); + ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms.goalspring)-1.0f ; + VECADDS(lF[i], lF[i], auxvect, -ks); + + /* calulate damping forces generated by goals*/ + VECSUB(velgoal,verts[i].xold, verts[i].xconst); + kd = clmd->sim_parms.goalfrict * 0.01f; // friction force scale taken from SB + VECSUBADDSS(lF[i], velgoal, kd, lV[i], kd); + + } + } + } + + /* handle external forces like wind */ + if(effectors) + { + float wind[3] = {0,1.0f,0}; + float force[3]= {0.0f, 0.0f, 0.0f}; + + for(i = 0; i < cloth->numverts; i++) + { + float vertexnormal[3]={0,0,0}; + + pdDoEffectors(effectors, lX[i], force, wind, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); + + VECCOPY(wind_normalized, wind); + Normalize(wind_normalized); + + calculateWeightedVertexNormal(clmd, mfaces, vertexnormal, i, lX); + VECADDS(lF[i], lF[i], wind_normalized, -calculateVertexWindForce(i, wind, vertexnormal)); + } + } + + /* calculate and apply spring forces */ + for(i = 0; i < cloth->numsprings; i++) + { + // only handle active springs + if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) + { + calc_spring_force(clmd, &springs[i], lF, lX, lV, dFdV, dFdX); + } + } + +} + +void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV) +{ + unsigned int numverts = dFdV[0].vcount; + + lfVector *dFdXmV = create_lfvector(numverts); + + initdiag_bfmatrix(A, I); + zero_lfvector(dV, numverts); + + subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); + + mul_bfmatrix_lfvector(dFdXmV, dFdX, lV); + + add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts); + cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */ + // cg_filtered_pre(dV, A, B, z, olddV, dt); + cp_lfvector(olddV, dV, numverts); + + // advance velocities + add_lfvector_lfvector(Vnew, lV, dV, numverts); + + del_lfvector(dFdXmV); +} + +int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors, + CM_COLLISION_SELF self_collision, CM_COLLISION_OBJ obj_collision) +{ + unsigned int i=0, j; + float step=0.0f, tf=1.0f; + Cloth *cloth = clmd->clothObject; + ClothVertex *verts = cloth->verts; + unsigned int numverts = cloth->numverts; + float dt = 1.0f / clmd->sim_parms.stepsPerFrame; + Implicit_Data *id = cloth->implicit; + int result = 0; + + if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) /* do goal stuff */ + { + for(i = 0; i < numverts; i++) + { + // update velocities with constrained velocities from pinned verts + if(verts [i].goal >= SOFTGOALSNAP) + { + VECSUB(id->V[i], verts[i].xconst, verts[i].xold); + } + } + } + + while(step < tf) + { + effectors= pdInitEffectors(ob,NULL); + + // calculate + calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV); + add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); + + // collisions + itstart(); + // update verts to current positions + for(i = 0; i < numverts; i++) + { + VECCOPY(verts[i].tx, id->Xnew[i]); + + VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + } + + // call collision function + // result = cloth_bvh_objcollision(clmd, step + dt, bvh_collision_response, dt); + + // copy corrected positions back to simulation + for(i = 0; i < numverts; i++) + { + // TODO: calculate v_n+1 from v_n+1/2 + if(result) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + + VECCOPY(verts[i].txold, verts[i].tx); + + VECCOPY(id->Xnew[i], verts[i].tx); + + VECCOPY(id->Vnew[i], verts[i].tv); + VecMulf(id->Vnew[i], 1.0f / dt); + } + else + { + VECCOPY(verts[i].txold, id->Xnew[i]); + } + } + + // X = Xnew; + cp_lfvector(id->X, id->Xnew, numverts); + + // if there were collisions, advance the velocity from v_n+1/2 to v_n+1 + if(result) + { + // V = Vnew; + cp_lfvector(id->V, id->Vnew, numverts); + + // calculate + calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV); + } + + itend(); + // printf("collision time: %f\n", (float)itval()); + + // V = Vnew; + cp_lfvector(id->V, id->Vnew, numverts); + + step += dt; + + if(effectors) pdEndEffectors(effectors); + } + + for(i = 0; i < numverts; i++) + { + if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) + { + if(verts [i].goal < SOFTGOALSNAP) + { + VECCOPY(verts[i].txold, id->X[i]); + VECCOPY(verts[i].x, id->X[i]); + VECCOPY(verts[i].v, id->V[i]); + } + else + { + VECCOPY(verts[i].txold, verts[i].xconst); + VECCOPY(verts[i].x, verts[i].xconst); + VECCOPY(verts[i].v, id->V[i]); + } + } + else + { + VECCOPY(verts[i].txold, id->X[i]); + VECCOPY(verts[i].x, id->X[i]); + VECCOPY(verts[i].v, id->V[i]); + } + } + return 1; +} + +void implicit_set_positions (ClothModifierData *clmd) +{ + Cloth *cloth = clmd->clothObject; + ClothVertex *verts = cloth->verts; + unsigned int numverts = cloth->numverts, i; + Implicit_Data *id = cloth->implicit; + for(i = 0; i < numverts; i++) + { + VECCOPY(id->X[i], verts[i].x); + VECCOPY(id->V[i], verts[i].v); + } +} diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c new file mode 100644 index 00000000000..cdcb16c67f6 --- /dev/null +++ b/source/blender/blenkernel/intern/kdop.c @@ -0,0 +1,861 @@ +/* collision.c +* +* +* ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. The Blender +* Foundation also sells licenses for use in proprietary software under +* the Blender License. See http://www.blender.org/BL/ for information +* about this. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* The Original Code is Copyright (C) Blender Foundation +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): none yet. +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#include +#include +#include +#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_14 + + + +#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 exchange(Tree **a, int i, int j) +{ + Tree *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 insertionsort(Tree **a, int lo, int hi, int axis) +{ + int i,j; + Tree *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 partition(Tree **a, int lo, int hi, Tree * 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; + exchange(a, i,j); + i++; + } +} + +/* +* Heapsort algorithm +*/ +static void downheap(Tree **a, int i, int n, int lo, int axis) +{ + Tree * 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 heapsort(Tree **a, int lo, int hi, int axis) +{ + int n = hi-lo, i; + for (i=n/2; i>=1; i=i-1) + { + downheap(a, i,n,lo, axis); + } + for (i=n; i>1; i=i-1) + { + exchange(a, lo,lo+i-1); + downheap(a, 1,i-1,lo, axis); + } +} + +static Tree *medianof3(Tree **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 introsort_loop (Tree **a, int lo, int hi, int depth_limit, int axis) +{ + int p; + + while (hi-lo > size_threshold) + { + if (depth_limit == 0) + { + heapsort(a, lo, hi, axis); + return; + } + depth_limit=depth_limit-1; + p=partition(a, lo, hi, medianof3(a, lo, lo+((hi-lo)/2)+1, hi-1, axis), axis); + introsort_loop(a, p, hi, depth_limit, axis); + hi=p; + } +} + +DO_INLINE void sort(Tree **a0, int begin, int end, int axis) +{ + if (begin < end) + { + Tree **a=a0; + introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis); + insertionsort(a, begin, end, axis); + } +} +DO_INLINE void bvh_sort_along_axis(Tree **face_list, int start, int end, int axis) +{ + sort(face_list, start, end, axis); +} +//////////////////////////////////////////////////////////////////////////////////////////////// +void bvh_free(BVH * bvh) +{ + LinkNode *search = NULL; + Tree *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; + + 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, Tree **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, Tree **tri, int numfaces, float *bv) +{ + ClothVertex *tempMVert = bvh->verts; + 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(tempMVert[temp].txold, 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, Tree **tri, int numfaces, float *bv) +{ +ClothVertex *tempMVert = bvh->verts; +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(tempMVert[temp].tx, KDOP_AXES[i]); +if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0)) +tempBV[(2 * i)] = newminmax; +// the same like some "else if" but with that condition I +// don't need to insert the first entry manually +if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0)) +tempBV[(2 * i) + 1] = newminmax; + +newminmax = INPR(tempMVert[temp].txold, KDOP_AXES[i]); +if (newminmax < tempBV[(2 * i)]) +tempBV[(2 * i)] = newminmax; +if (newminmax > tempBV[(2 * i) + 1]) +tempBV[(2 * i) + 1] = newminmax; +} +} +} +} +*/ +static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink) +{ + int i = 0; + Tree *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 = (Tree *)MEM_callocN(sizeof(Tree), "Tree"); + 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 + { + Tree *tnode = face_list[tstart]; + tree->nodes[i] = tnode; + tree->nodes[i]->parent = tree; + } + } + return; +} + +BVH *bvh_build (ClothModifierData *clmd, float epsilon) +{ + unsigned int i = 0, j = 0, k = 0; + Tree **face_list=NULL; + BVH *bvh=NULL; + Cloth *cloth = NULL; + Tree *tree=NULL; + LinkNode *nlink = NULL; + EdgeHash *edgehash = NULL; + ClothSpring *springs = NULL; + unsigned int numsprings = 0; + MFace *mface = NULL; + + if(!clmd) + return NULL; + + cloth = clmd->clothObject; + + if(!cloth) + return NULL; + + bvh = MEM_callocN(sizeof(BVH), "BVH"); + if (bvh == NULL) + { + printf("bvh: Out of memory.\n"); + return NULL; + } + + springs = cloth->springs; + numsprings = cloth->numsprings; + + bvh->flags = 0; + bvh->leaf_tree = NULL; + bvh->leaf_root = NULL; + + bvh->epsilon = epsilon; + bvh->numfaces = cloth->numfaces; + mface = bvh->mfaces = cloth->mfaces; + + bvh->numverts = cloth->numverts; + bvh->verts = cloth->verts; + tree = (Tree *)MEM_callocN(sizeof(Tree), "Tree"); + // TODO: check succesfull alloc + BLI_linklist_prepend(&bvh->tree, tree); + + nlink = bvh->tree; + + if (tree == NULL) + { + printf("bvh_build: Out of memory for nodes.\n"); + bvh_free(bvh); + return NULL; + } + 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 spring tearing hash + /* + edgehash = BLI_edgehash_new(); + if(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) + for(i = 0; i < numsprings; i++) + { + if((springs[i].flags & CSPRING_FLAG_DEACTIVATE) + &&(!BLI_edgehash_haskey(edgehash, springs[i].ij, springs[i].kl))) + { + BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL); + BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL); + } + } + */ + + // create face boxes + face_list = MEM_callocN (bvh->numfaces * sizeof (Tree *), "Tree"); + if (face_list == NULL) + { + printf("bvh_build: Out of memory for face_list.\n"); + bvh_free(bvh); + return NULL; + } + + // create face boxes + for(i = 0, k = 0; i < bvh->numfaces; i++) + { + LinkNode *tnlink; + /* + if((!BLI_edgehash_haskey(edgehash, mface[i].v1, mface[i].v2)) + &&(!BLI_edgehash_haskey(edgehash, mface[i].v2, mface[i].v3)) + &&(!BLI_edgehash_haskey(edgehash, mface[i].v3, mface[i].v4)) + &&(!BLI_edgehash_haskey(edgehash, mface[i].v4, mface[i].v1))) + */ + { + tree = (Tree *)MEM_callocN(sizeof(Tree), "Tree"); + // 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); + + // BLI_edgehash_free(edgehash, NULL); + } + + + return bvh; +} + +// 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, ClothModifierData * coll_clmd, Tree * tree1, Tree * 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, coll_clmd, 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, coll_clmd, 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, coll_clmd, 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(Tree * 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 +void bvh_update_static(ClothModifierData * clmd, BVH * bvh) +{ + TreeNode *leaf, *parent; + int traversecheck = 1; // if this is zero we don't go further + unsigned int j = 0; + + for (leaf = bvh->leaf_root; leaf; leaf = leaf->nextLeaf) + { + traversecheck = 1; + if ((leaf->parent) && (leaf->parent->traversed == leaf->parent->count_nodes)) + { + leaf->parent->traversed = 0; + } + bvh_calc_DOP_hull_static(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); + } + } + + } + } +} diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index bb5d4039336..0d7668e0ccc 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -51,6 +51,7 @@ #include "MEM_guardedalloc.h" #include "DNA_armature_types.h" +#include "DNA_cloth_types.h" #include "DNA_effect_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" @@ -84,6 +85,7 @@ #include "BKE_object.h" #include "BKE_mesh.h" #include "BKE_softbody.h" +#include "BKE_cloth.h" #include "BKE_material.h" #include "depsgraph_private.h" @@ -4855,6 +4857,94 @@ static void softbodyModifier_deformVerts( sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts); } + +/* Cloth */ + +static void clothModifier_initData(ModifierData *md) +{ + ClothModifierData *clmd = (ClothModifierData*) md; + cloth_init (clmd); +} + +static void clothModifier_deformVerts( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) +{ + DerivedMesh *dm = NULL; + + // if possible use/create DerivedMesh + if(derivedData) dm = CDDM_copy(derivedData); + else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); + + if(dm) + { + CDDM_apply_vert_coords(dm, vertexCos); + CDDM_calc_normals(dm); + } + + clothModifier_do((ClothModifierData *)md, ob, dm, vertexCos, numVerts); + + if(dm) + dm->release(dm); +} + +static void clothModifier_updateDepgraph( + ModifierData *md, DagForest *forest, Object *ob, + DagNode *obNode) +{ + ClothModifierData *clmd = (ClothModifierData*) md; + + Base *base; + + if(clmd) + { + for(base = G.scene->base.first; base; base= base->next) + { + Object *ob1= base->object; + if(ob1 != ob) + { + ClothModifierData *coll_clmd = (ClothModifierData *)modifiers_findByType(ob1, eModifierType_Cloth); + if(coll_clmd) + { + if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + { + DagNode *curNode = dag_get_node(forest, ob1); + dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA); + } + } + } + } + } + +} + +CustomDataMask clothModifier_requiredDataMask(ModifierData *md) +{ + ClothModifierData *clmd = (HookModifierData *)md; + CustomDataMask dataMask = 0; + + /* ask for vertexgroups if we need them */ + if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) + if (clmd->sim_parms.vgroup_mass > 0) + dataMask |= (1 << CD_MDEFORMVERT); + + return dataMask; +} + + +static int clothModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + +static void clothModifier_freeData(ModifierData *md) +{ + ClothModifierData *clmd = (ClothModifierData*) md; + + if (clmd) + cloth_free_modifier (clmd); +} + /* Boolean */ static void booleanModifier_copyData(ModifierData *md, ModifierData *target) @@ -5139,6 +5229,21 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_RequiresOriginalData; mti->deformVerts = softbodyModifier_deformVerts; + + mti = INIT_TYPE(Cloth); + mti->type = eModifierTypeType_OnlyDeform; + mti->initData = clothModifier_initData; + mti->flags = eModifierTypeFlag_AcceptsCVs; + // | eModifierTypeFlag_RequiresOriginalData; + // | eModifierTypeFlag_SupportsMapping + // | eModifierTypeFlag_SupportsEditmode + // | eModifierTypeFlag_EnableInEditmode; + mti->dependsOnTime = clothModifier_dependsOnTime; + mti->freeData = clothModifier_freeData; + mti->requiredDataMask = clothModifier_requiredDataMask; + // mti->copyData = clothModifier_copyData; + mti->deformVerts = clothModifier_deformVerts; + mti->updateDepgraph = clothModifier_updateDepgraph; mti = INIT_TYPE(Boolean); mti->type = eModifierTypeType_Nonconstructive; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 624bfedf6cd..19f74096e54 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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" @@ -112,6 +113,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" @@ -2871,7 +2873,18 @@ 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; + /* + if (clmd->sim_parms.flags & CSIMSETT_FLAG_BAKED) { + clmd->baked_data = newdataadr (fd, clmd->baked_data); + printf ("direct_link_modifiers: read cloth baked_data.\n"); + }*/ + } + else if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; hmd->indexar= newdataadr(fd, hmd->indexar); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 4f09f51bc87..4203824ae65 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -107,6 +107,7 @@ Important to know is that 'streaming' has been added to files, for Blender Publi #include "DNA_actuator_types.h" #include "DNA_brush_types.h" #include "DNA_camera_types.h" +#include "DNA_cloth_types.h" #include "DNA_color_types.h" #include "DNA_constraint_types.h" #include "DNA_controller_types.h" @@ -154,6 +155,7 @@ Important to know is that 'streaming' has been added to files, for Blender Publi #include "BKE_action.h" #include "BKE_bad_level_calls.h" // build_seqar (from WHILE_SEQ) free_oops error #include "BKE_blender.h" +#include "BKE_cloth.h" #include "BKE_curve.h" #include "BKE_customdata.h" #include "BKE_constraint.h" @@ -826,6 +828,20 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) HookModifierData *hmd = (HookModifierData*) md; writedata(wd, DATA, sizeof(int)*hmd->totindex, hmd->indexar); + } + else if (md->type==eModifierType_Cloth) { + int n; + ClothModifierData *clmd = (ClothModifierData *) md; + /* + if ((clmd->sim_parms.flags & CSIMSETT_FLAG_BAKED) && clmd->baked_data) { + // Compute the number of vertices we're saving. + + n = (clmd->sim_parms.bake_end_frame - clmd->sim_parms.bake_start_frame + 1) * + clmd->sim_parms.bake_num_verts; + writedata (wd, DATA, n * sizeof (clmd->baked_data [0]), clmd->baked_data); + printf ("write_modifiers: wrote %d elements of size %d for cloth baked data.\n", + n, sizeof (clmd->baked_data [0])); + }*/ } } } diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 4f09ad716d7..cb17f81b87d 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -283,6 +283,13 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_GROUP_RELINK 1460 #define B_OBJECT_IPOFLAG 1461 + +/* Cloth sim button defines */ +#define B_CLOTH_CLEARCACHEALL 1470 +#define B_CLOTH_CLEARCACHEFRAME 1471 +#define B_CLOTH_CHANGEPREROLL 1472 +#define B_CLOTH_DEL_VG 1473 + /* *********************** */ #define B_WORLDBUTS 1600 diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h new file mode 100644 index 00000000000..bed04c2fa71 --- /dev/null +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -0,0 +1,150 @@ +/** +* $Id: DNA_cloth_types.h,v 1.1 2007/08/01 02:28:34 daniel Exp $ +* +* ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. The Blender +* Foundation also sells licenses for use in proprietary software under +* the Blender License. See http://www.blender.org/BL/ for information +* about this. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* The Original Code is Copyright (C) 2006 by NaN Holding BV. +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): Daniel (Genscher), Todd Koeckeritz (zaz) +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ +#ifndef DNA_CLOTH_TYPES_H +#define DNA_CLOTH_TYPES_H + +#include "DNA_listBase.h" + + +/** +* Pin and unpin frames are the frames on which the vertices stop moving. +* They will assume the position they had prior to pinFrame until unpinFrame +* is reached. +*/ +typedef struct ClothVertex { + int flags; /* General flags per vertex. */ + float v [3]; /* The velocity of the point. */ + float xconst [3]; /* constrained position */ + float x [3]; /* The current position of this vertice. */ + float xold [3]; /* The previous position of this vertice. */ + float tx [3]; + float txold [3]; + float tv[3]; + float mass; /* mass / weight of the vertex */ + float goal; /* goal, from SB */ +} 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 */ + int type; + int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ +} ClothSpring; + + + +/** +* This struct contains all the global data required to run a simulation. +* At the time of this writing, this structure contains data appropriate +* to run a simulation as described in Deformation Constraints in a +* Mass-Spring Model to Describe Rigid Cloth Behavior by Xavier Provot. +* +* I've tried to keep similar, if not exact names for the variables as +* are presented in the paper. Where I've changed the concept slightly, +* as in stepsPerFrame comapred to the time step in the paper, I've used +* variables with different names to minimize confusion. +**/ +typedef struct SimulationSettings { + short vgroup_mass; /* optional vertexgroup name for assigning weight. */ + short pad; + float mingoal; /* see SB */ + int preroll; /* How many frames of simulation to do before we start. */ + float Cdis; /* Mechanical damping of springs. */ + float Cvi; /* Viscous/fluid damping. */ + int stepsPerFrame; /* Number of time steps per frame. */ + float gravity [3]; /* Gravity/external force vector. */ + float ufluid [3]; /* Velocity vector of the fluid. */ + float dt; /* This is the duration of our time step, computed. */ + float mass; /* The mass of the entire cloth. */ + float structural; /* Structural spring stiffness. */ + float shear; /* Shear spring stiffness. */ + float bending; /* Flexion spring stiffness. */ + float sim_time; + int flags; /* flags, see CSIMSETT_FLAGS enum above. */ + short solver_type; /* which solver should be used? */ + short pad2; + float maxgoal; /* see SB */ + float eff_force_scale;/* Scaling of effector forces (see softbody_calc_forces).*/ + float eff_wind_scale; /* Scaling of effector wind (see softbody_calc_forces). */ + float sim_time_old; + struct LinkNode *cache; + float defgoal; + int goalfrict; + float goalspring; + int maxspringlen; /* in percent!; if tearing enabled, a spring will get cut */ +} 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. */ + void *temp; /* e.g. pointer to temp memory for collisions */ +} 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 ClothSpring *springs; /* The springs connecting the mesh. */ + unsigned int numverts; /* The number of verts == m * n. */ + unsigned int numsprings; /* The count of springs. */ + unsigned char *facemarks; + char old_solver_type; /* Needed to allow call to free if solver changes. */ + char old_collision_type; /* Needed to allow call to free if collision changes.*/ + short pad7; + unsigned int numfaces; + int pad2; + int pad4; + void *tree; /* collision tree for this cloth object */ + struct MFace *mfaces; + void *implicit; +} Cloth; + +#endif diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 71e850e4368..4c9fbdcc7b7 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -9,6 +9,8 @@ /* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE! */ +#include "DNA_cloth_types.h" + typedef enum ModifierType { eModifierType_None = 0, eModifierType_Subsurf, @@ -28,6 +30,7 @@ typedef enum ModifierType { eModifierType_UVProject, eModifierType_Smooth, eModifierType_Cast, + eModifierType_Cloth, NUM_MODIFIER_TYPES } ModifierType; @@ -335,6 +338,14 @@ typedef struct SoftbodyModifierData { ModifierData modifier; } SoftbodyModifierData; +typedef struct ClothModifierData { + ModifierData modifier; + + Cloth *clothObject; /* The internal data structure for cloth. */ + SimulationSettings sim_parms; /* definition is in DNA_cloth_types.h */ + CollisionSettings coll_parms; /* definition is in DNA_cloth_types.h */ +} ClothModifierData; + typedef enum { eBooleanModifierOp_Intersect, eBooleanModifierOp_Union, diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 4d437861751..d13b964622d 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -127,6 +127,7 @@ char *includefiles[] = { "DNA_color_types.h", "DNA_brush_types.h", "DNA_customdata_types.h", + "DNA_cloth_types.h", // if you add files here, please add them at the end // of makesdna.c (this file) as well @@ -1144,4 +1145,5 @@ int main(int argc, char ** argv) #include "DNA_color_types.h" #include "DNA_brush_types.h" #include "DNA_customdata_types.h" +#include "DNA_cloth_types.h" /* end of list */ diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index a998c568619..de1d8f8c0ac 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -86,6 +86,7 @@ #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" +#include "DNA_cloth_types.h" #include "DNA_constraint_types.h" #include "DNA_curve_types.h" #include "DNA_effect_types.h" @@ -113,6 +114,7 @@ #include "BKE_anim.h" #include "BKE_armature.h" +#include "BKE_cloth.h" #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_deform.h" @@ -844,7 +846,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s /* Draw target parameters */ uiBlockBeginAlign(block); uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); - + if (is_armature_target) { but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone"); uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar); @@ -900,7 +902,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s } uiBlockEndAlign(block); - + /* Draw XYZ toggles */ uiBlockBeginAlign(block); but=uiDefButBitI(block, TOG, SIZELIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component"); @@ -920,7 +922,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); - + /* Draw target parameters */ uiDefButBitS(block, TOG, CONSTRAINT_IK_ROT, B_CONSTRAINT_TEST, "Rot", *xco, *yco-24,60,19, &data->flag, 0, 0, 0, 0, "Chain follows rotation of target"); @@ -2144,8 +2146,61 @@ void do_object_panels(unsigned short event) case B_OBJECT_IPOFLAG: if(ob->ipo) ob->ipo->showkey= (ob->ipoflag & OB_DRAWKEY)?1:0; allqueue(REDRAWVIEW3D, 0); + case B_CLOTH_CLEARCACHEALL: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + CFRA= 1; + update_for_newframe_muted(); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_PART; + cloth_cache_free(clmd, 1); + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); + } + } + break; + case B_CLOTH_CLEARCACHEFRAME: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_PART; + cloth_cache_free(clmd, G.scene->r.cfra); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); + } + } + break; + case B_CLOTH_CHANGEPREROLL: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + if(clmd->sim_parms.cache) + { + CFRA= 1; + update_for_newframe_muted(); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); + } + } + } break; - + case B_CLOTH_DEL_VG: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + clmd->sim_parms.vgroup_mass = 0; + } + + allqueue(REDRAWBUTSOBJECT, 0); + } + break; default: if(event>=B_SELEFFECT && eventmodifiers, md); + } + else { + BLI_remlink(&ob->modifiers, md); + modifier_free(md); + } + + allqueue(REDRAWBUTSEDIT, 0); +} + +static void object_panel_cloth(Object *ob) +{ + uiBlock *block; + static int val, val2; + uiBut *but; + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Cloth", "Physics", 640, 0, 318, 204)==0) return; + + if(ob->id.lib) uiSetButLock(1, "Can't edit library data"); + val = ((clmd)?(1):(0)); + + but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Cloth Object", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become cloth"); + uiButSetFunc(but, object_cloth__enabletoggle, ob, NULL); + uiDefBut(block, LABEL, 0, "",10,10,300,0, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ + + if(clmd) + { + but = uiDefButBitI(block, TOG, CSIMSETT_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object", 170,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); + // uiButSetFunc(but, object_cloth__enabletoggle, ob, NULL); + + if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) + { + Cloth *cloth = clmd->clothObject; + int defCount; + char *clvg1, *clvg2; + char clmvg [] = "Mass Vertex Group%t|None%x0|"; + + val2=0; + + // uiDefButBitI(block, TOG, CSIMSETT_FLAG_ADVANCED, REDRAWBUTSOBJECT, "Advanced", 180,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Enable advanced mode"); + + /* GENERAL STUFF */ + uiClearButLock(); + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_DIFF, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 5000.0, 100, 0, "Overall stiffness of structure"); + uiDefButF(block, NUM, B_DIFF, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 1000.0, 1000, 0, "Wrinkle possibility"); + uiDefButI(block, NUM, B_DIFF, "Steps per Frame:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); + uiBlockEndAlign(block); + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_DIFF, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms.Cvi, 0.0, 10.0, 10, 0, "Apply gravitation to point movement"); + uiBlockEndAlign(block); + + uiClearButLock(); + + uiBlockBeginAlign(block); + uiDefBut(block, LABEL, 0, "Gravity:", 10,100,60,20, NULL, 0.0, 0, 0, 0, ""); + // uiClearButLock(); + + uiDefButF(block, NUM, B_DIFF, "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_DIFF, "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_DIFF, "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, CSIMSETT_FLAG_GOAL, REDRAWVIEW3D, "Use Goal", 10,70,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); + if (clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) + { + if(ob->type==OB_MESH) + { + + defCount = sizeof (clmvg); + clvg1 = get_vertexgroup_menustr (ob); + clvg2 = MEM_callocN (strlen (clvg1) + 1 + defCount, "clothVgMS"); + if (! clvg2) { + printf ("draw_modifier: error allocating memory for cloth vertex group menu string.\n"); + return; + } + defCount = BLI_countlist (&ob->defbase); + if (defCount == 0) + { + clmd->sim_parms.vgroup_mass = 0; + } + sprintf (clvg2, "%s%s", clmvg, clvg1); + + uiDefButS(block, MENU, REDRAWVIEW3D, clvg2, 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups"); + MEM_freeN (clvg1); + MEM_freeN (clvg2); + + if(clmd->sim_parms.vgroup_mass) + { + bDeformGroup *defGroup = BLI_findlink(&ob->defbase, clmd->sim_parms.vgroup_mass-1); + if(defGroup) + uiDefBut(block, BUT, B_DIFF, defGroup->name, 160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group"); + else + uiDefBut(block, BUT, B_DIFF, "(no group)", 160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Vertex Group doesn't exist anymore"); + + uiDefIconBut(block, BUT, B_CLOTH_DEL_VG, ICON_X, 290,70,20,20, 0, 0, 0, 0, 0, "Disable use of vertex group"); + + } + else + uiDefButF(block, NUM, REDRAWVIEW3D, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + + } + else + { + uiDefButS(block, TOG, REDRAWVIEW3D, "W", 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); + uiDefButF(block, NUM, REDRAWVIEW3D, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + } + + uiDefButF(block, NUM, B_DIFF, "G Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness"); + uiDefButF(block, NUM, B_DIFF, "G Damp:", 160,50,150,20, &clmd->sim_parms.goalfrict , 0.0, 50.0, 10, 0, "Goal (vertex target position) friction"); + uiDefButF(block, NUM, REDRAWVIEW3D, "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, REDRAWVIEW3D, "G Max:", 160,30,150,20, &clmd->sim_parms.maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); + } + uiBlockEndAlign(block); + + /* + // no tearing supported anymore since modifier stack restrictions + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, CSIMSETT_FLAG_TEARING_ENABLED, B_EFFECT_DEP, "Tearing", 10,0,150,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); + + if (clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) + { + uiDefButI(block, NUM, B_DIFF, "Max extent:", 160,0,150,20, &clmd->sim_parms.maxspringlen, 1.0, 1000.0, 10, 0, "Maximum extension before spring gets cut"); + } + + uiBlockEndAlign(block); + */ + } + } +} + + +static void object_panel_cloth_II(Object *ob) +{ + uiBlock *block; + static int val; + uiBut *but; + ClothModifierData *clmd = NULL; + + clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) + { + Cloth *cloth = clmd->clothObject; + char str[128]; + + block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_II", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Cloth", "Physics"); + if(uiNewPanel(curarea, block, "Cloth Cache", "Physics", 651, 0, 318, 204)==0) return; + + uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + + if(clmd->sim_parms.cache) + { + int length = BLI_linklist_length(clmd->sim_parms.cache); + + /* correct spelling if only 1 frame cacheed --> only gimmick */ + if(length-clmd->sim_parms.preroll>1) + sprintf (str, "Frame 1 - %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms.preroll, clmd->sim_parms.preroll, length); + else + sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms.preroll, clmd->sim_parms.preroll, length); + + uiDefBut(block, LABEL, 0, str, 10,160,290,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Clear cache:", 10,140,290,20, NULL, 0.0, 0, 0, 0, ""); + uiBlockBeginAlign (block); + uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 10, 120,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache without preroll"); + uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 120,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache"); + if(length>1) // B_CLOTH_CHANGEPREROLL + uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,100,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); + } + else + { + uiDefBut(block, LABEL, 0, "No frames cached.", 10,140,290,20, NULL, 0.0, 0, 0, 0, ""); + } + uiBlockEndAlign(block); + } + } + // uiBlockEndAlign(block); +} + +static void object_panel_cloth_III(Object *ob) +{ + uiBlock *block; + static int val; + uiBut *but; + ClothModifierData *clmd = NULL; + + clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) + { + Cloth *cloth = clmd->clothObject; + char str[128]; + + block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_III", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Cloth", "Physics"); + if(uiNewPanel(curarea, block, "Cloth Collisions", "Physics", 651, 0, 318, 204)==0) return; + + uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + + uiBlockBeginAlign(block); + // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ + uiDefButF(block, NUM, B_DIFF, "Min Distance:", 10,10,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); + uiDefBut(block, LABEL, 0, "",160,10,150,20, NULL, 0.0, 0, 0, 0, ""); + uiBlockEndAlign(block); + } + } + // uiBlockEndAlign(block); +} + + static void object_panel_particles_motion(Object *ob) { uiBlock *block; @@ -3503,6 +3783,9 @@ void physics_panels() object_panel_particles_motion(ob); object_softbodies(ob); object_softbodies_II(ob); + object_panel_cloth(ob); + object_panel_cloth_II(ob); + object_panel_cloth_III(ob); object_panel_fluidsim(ob); } } From 9d0420c1acd983cc0ae6ab2f61d63d31956d081c Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 16 Sep 2007 16:33:42 +0000 Subject: [PATCH 002/101] Little project: Getting fluidsim multithreaded. Can be actuvated by adding "PARALLEL" to compiler flags in elbeem folder. ----- Code already works for MAX_THREADS=1 so there seems to be some bug in openMP code in paraloopstart.h Help appeciated :) --- intern/elbeem/intern/paraloop.h | 51 ++++++++++++++++++++++++++++ intern/elbeem/intern/paraloopend.h | 14 ++++++++ intern/elbeem/intern/paraloopstart.h | 3 ++ 3 files changed, 68 insertions(+) create mode 100644 intern/elbeem/intern/paraloop.h create mode 100644 intern/elbeem/intern/paraloopend.h create mode 100644 intern/elbeem/intern/paraloopstart.h diff --git a/intern/elbeem/intern/paraloop.h b/intern/elbeem/intern/paraloop.h new file mode 100644 index 00000000000..e8bef648a8d --- /dev/null +++ b/intern/elbeem/intern/paraloop.h @@ -0,0 +1,51 @@ + +#define PERFORM_USQRMAXCHECK \ +_Pragma("omp critical") {\ +USQRMAXCHECK(usqr,ux,uy,uz, mMaxVlen, mMxvx,mMxvy,mMxvz); \ +} \ + + +#define LIST_EMPTY(x) \ +_Pragma("omp critical") {\ +mListEmpty.push_back( x ); } + +#define LIST_FULL(x) \ +_Pragma("omp critical") {\ +mListFull.push_back( x ); } + +#define FSGR_ADDPART(x) \ +_Pragma("omp critical") { \ +mpParticles->addFullParticle( x ); } \ + + +#define MAX_THREADS 2 + +#define GRID_REGION_START() \ +{ /* main_region */ \ + int kstart=getForZMinBnd(), kend=getForZMaxBnd(mMaxRefine); \ + if(gridLoopBound>0){ kstart=getForZMin1(), kend=getForZMax1(mMaxRefine); } \ + int kdir = 1; \ + const int id=omp_get_thread_num(); \ + int jstart = (id*((mLevel[mMaxRefine].lSizey-gridLoopBound) / MAX_THREADS))+gridLoopBound; \ + int jend = (id+1)*((mLevel[mMaxRefine].lSizey-gridLoopBound)/ MAX_THREADS); \ + if(id+1 == MAX_THREADS) \ + { \ + jend = mLevel[mMaxRefine].lSizey-gridLoopBound; \ + } \ + if(jstart<1) jstart = 1; \ + LbmFloat *ccel = NULL, *tcel = NULL; \ + CellFlagType *pFlagSrc=NULL, *pFlagDst=NULL; \ + if(mLevel[mMaxRefine].setCurr==1) { \ + kdir = -1; \ + int temp = kend; \ + kend = kstart-1; \ + kstart = temp-1; \ + temp = id; /* dummy remove warning */ \ +} \ + + + +#define unused_GRID_REGION_END() \ +} /* main_region */ \ + // end unusedGRID_REGION_END + diff --git a/intern/elbeem/intern/paraloopend.h b/intern/elbeem/intern/paraloopend.h new file mode 100644 index 00000000000..6ea636e8d23 --- /dev/null +++ b/intern/elbeem/intern/paraloopend.h @@ -0,0 +1,14 @@ +// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +} /* i */ + int i=0; + ADVANCE_POINTERS(2*gridLoopBound); +} /* j */ + /* COMPRESSGRIDS!=1 */ +#pragma omp barrier + + /* int i=0; */ + /* ADVANCE_POINTERS(mLevel[lev].lSizex*2); */ +} /* all cell loop k,j,i */ + if(doReduce) { } /* dummy remove warning */ +} /* main_region */ + diff --git a/intern/elbeem/intern/paraloopstart.h b/intern/elbeem/intern/paraloopstart.h new file mode 100644 index 00000000000..9f13eb3207b --- /dev/null +++ b/intern/elbeem/intern/paraloopstart.h @@ -0,0 +1,3 @@ + +#pragma omp parallel section num_threads(MAX_THREADS) \ +reduction(+: calcCurrentMass, calcCurrentVolume, calcCellsFilled, calcCellsEmptied, calcNumUsedCells) From 1138bd30145c0d961266a150d86d59f9c38418d1 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 16 Sep 2007 23:19:02 +0000 Subject: [PATCH 003/101] New: Min & MaxFrame of simulation; Fixed: Many reset problems gone --- source/blender/blenkernel/BKE_cloth.h | 1 + source/blender/blenkernel/BKE_modifier.h | 1 + source/blender/blenkernel/intern/cloth.c | 36 ++++++++----- source/blender/blenkernel/intern/implicit.c | 24 +++++++-- source/blender/blenkernel/intern/modifier.c | 11 +++- source/blender/include/butspace.h | 1 + source/blender/makesdna/DNA_cloth_types.h | 6 ++- source/blender/src/buttons_editing.c | 12 ++++- source/blender/src/buttons_object.c | 58 +++++++++++++-------- source/blender/src/editmesh.c | 8 ++- source/blender/src/editobject.c | 4 ++ source/blender/src/transform_conversions.c | 9 ++-- source/blender/src/transform_generics.c | 24 +++++++-- source/blender/src/vpaint.c | 6 +++ 14 files changed, 147 insertions(+), 54 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index e843079f412..0a50feeb9b0 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -107,6 +107,7 @@ typedef enum // needed for buttons_object.c void cloth_cache_free(ClothModifierData *clmd, float time); +void cloth_free_modifier (ClothModifierData *clmd); // needed for cloth.c void implicit_set_positions (ClothModifierData *clmd); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 297443b883d..365381f5cdd 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -277,6 +277,7 @@ int modifiers_getCageIndex(struct Object *ob, int *lastPossibleCageIndex_r); int modifiers_isSoftbodyEnabled(struct Object *ob); +struct ModifierData *modifiers_isClothEnabled(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); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 4b4aa2d0d1d..18e1d4a6cde 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -119,6 +119,8 @@ static CM_SOLVER_DEF solvers [] = { #define DEBUG_CLOTH_VERBOSE 1000 static int DEBUG_CLOTH = 0; + + /* ********** cloth engine ******* */ /* Prototypes for internal functions. */ @@ -128,6 +130,8 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float (*vertexCos)[3], unsigned int numverts); int cloth_build_springs(Cloth *cloth, DerivedMesh *dm); static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup); + + /****************************************************************************** * * External interface called by modifier.c clothModifier functions. @@ -157,6 +161,8 @@ void cloth_init (ClothModifierData *clmd) clmd->sim_parms.solver_type = 0; clmd->sim_parms.preroll = 0; clmd->sim_parms.maxspringlen = 10; + clmd->sim_parms.firstframe = 1; + clmd->sim_parms.lastframe = 250; clmd->coll_parms.self_friction = 5.0; clmd->coll_parms.friction = 10.0; clmd->coll_parms.loop_count = 1; @@ -614,8 +620,13 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, Frame *frame = NULL; LinkNode *search = NULL; float deltaTime = current_time - clmd->sim_parms.sim_time; - - clmd->sim_parms.dt = 1.0f / (clmd->sim_parms.stepsPerFrame * G.scene->r.frs_sec); + + // only be active during a specific period + if((current_time < clmd->sim_parms.firstframe)||(current_time > clmd->sim_parms.lastframe)) + return; + + // unused in the moment + clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame; clmd->sim_parms.sim_time = current_time; @@ -707,7 +718,6 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, tstart(); /* Call the solver. */ - if (solvers [clmd->sim_parms.solver_type].solver) solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors,0,0); @@ -754,9 +764,6 @@ void cloth_free_modifier (ClothModifierData *clmd) clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_ALL; cloth_cache_free(clmd, 0); - /* Calls the solver and collision frees first as they - * might depend on data in clmd->clothObject. */ - if (cloth) { // If our solver provides a free function, call it @@ -793,11 +800,9 @@ void cloth_free_modifier (ClothModifierData *clmd) MEM_freeN (cloth); clmd->clothObject = NULL; } - } - /****************************************************************************** * * Internal functions. @@ -826,8 +831,6 @@ static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertex Mat4MulVecfl (ob->imat, vertexCos[i]); /* softbody is in global coords */ } } - else if (DEBUG_CLOTH) - printf ("cloth_to_object: clmd->clothObject was NULL.\n"); } @@ -837,15 +840,20 @@ static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertex **/ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup) { - unsigned int i; - int j; - MDeformVert *dvert = NULL; - Cloth *clothObj; + unsigned int i = 0; + unsigned int j = 0; + MDeformVert *dvert = NULL; + Cloth *clothObj = NULL; unsigned int numverts = dm->getNumVerts(dm); float goalfac = 0; ClothVertex *verts = NULL; clothObj = clmd->clothObject; + + if(!dm) + return; + + numverts = dm->getNumVerts(dm); /* vgroup is 1 based, decrement so we can match the right group. */ --vgroup; diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 5d386036b7b..c756c220fe6 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -689,14 +689,15 @@ typedef struct Implicit_Data lfVector *X, *V, *Xnew, *Vnew, *olddV, *F, *B, *dV, *z; fmatrix3x3 *A, *dFdV, *dFdX, *S, *P, *Pinv, *bigI; } Implicit_Data; + int implicit_init (Object *ob, ClothModifierData *clmd) { unsigned int i = 0; unsigned int pinned = 0; - Cloth *cloth; - ClothVertex *verts; - ClothSpring *springs; - Implicit_Data *id; + Cloth *cloth = NULL; + ClothVertex *verts = NULL; + ClothSpring *springs = NULL; + Implicit_Data *id = NULL; // init memory guard // MEMORY_BASE.first = MEMORY_BASE.last = NULL; @@ -727,6 +728,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) id->B = create_lfvector(cloth->numverts); id->dV = create_lfvector(cloth->numverts); id->z = create_lfvector(cloth->numverts); + for(i=0;inumverts;i++) { id->A[i].r = id->A[i].c = id->dFdV[i].r = id->dFdV[i].c = id->dFdX[i].r = id->dFdX[i].c = id->P[i].c = id->P[i].r = id->Pinv[i].c = id->Pinv[i].r = id->bigI[i].c = id->bigI[i].r = i; @@ -1503,9 +1505,23 @@ void implicit_set_positions (ClothModifierData *clmd) ClothVertex *verts = cloth->verts; unsigned int numverts = cloth->numverts, i; Implicit_Data *id = cloth->implicit; + unsigned int pinned = 0; + + // reset pinned verts in S matrix to zero + // id->S[0].vcount = 0; id->S[0].scount = 0; + for(i = 0; i < numverts; i++) { VECCOPY(id->X[i], verts[i].x); VECCOPY(id->V[i], verts[i].v); + /* + if(verts [i].flags & CVERT_FLAG_PINNED) + { + id->S[pinned].pinned = 1; + id->S[pinned].c = id->S[pinned].r = i; + pinned++; + } + */ } + // id->S[0].vcount = pinned; } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 0d7668e0ccc..d3d41e70d57 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5233,8 +5233,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Cloth); mti->type = eModifierTypeType_OnlyDeform; mti->initData = clothModifier_initData; - mti->flags = eModifierTypeFlag_AcceptsCVs; - // | eModifierTypeFlag_RequiresOriginalData; + mti->flags = eModifierTypeFlag_AcceptsCVs + | eModifierTypeFlag_RequiresOriginalData; // | eModifierTypeFlag_SupportsMapping // | eModifierTypeFlag_SupportsEditmode // | eModifierTypeFlag_EnableInEditmode; @@ -5446,6 +5446,13 @@ int modifiers_isSoftbodyEnabled(Object *ob) return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } +ModifierData * modifiers_isClothEnabled(Object *ob) +{ + ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + + return md; +} + LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask) { LinkNode *dataMasks = NULL; diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index cb17f81b87d..b017dd950e2 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -289,6 +289,7 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_CLOTH_CLEARCACHEFRAME 1471 #define B_CLOTH_CHANGEPREROLL 1472 #define B_CLOTH_DEL_VG 1473 +#define B_CLOTH_RENEW 1474 /* *********************** */ #define B_WORLDBUTS 1600 diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index bed04c2fa71..c756c29f467 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -106,7 +106,9 @@ typedef struct SimulationSettings { float defgoal; int goalfrict; float goalspring; - int maxspringlen; /* in percent!; if tearing enabled, a spring will get cut */ + int maxspringlen; /* in percent!; if tearing enabled, a spring will get cut */ + int lastframe; /* frame on which simulation stops */ + int firstframe; /* frame on which simulation starts */ } SimulationSettings; @@ -144,7 +146,7 @@ typedef struct Cloth { int pad4; void *tree; /* collision tree for this cloth object */ struct MFace *mfaces; - void *implicit; + void *implicit; /* our implicit solver connects to this pointer */ } Cloth; #endif diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index ea90f6fdc16..2ab5397f493 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -949,7 +949,7 @@ static uiBlock *modifiers_add_menu(void *ob_v) ModifierTypeInfo *mti = modifierType_getInfo(i); /* Only allow adding through appropriate other interfaces */ - if(ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue; + if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_Cloth)) continue; if((mti->flags&eModifierTypeFlag_AcceptsCVs) || (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) { @@ -1600,6 +1600,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco height += 20; } else if (md->type==eModifierType_Softbody) { height = 26; + } else if (md->type==eModifierType_Cloth) { + height = 26; } else if (md->type==eModifierType_Boolean) { height = 48; } else if (md->type==eModifierType_Array) { @@ -1615,7 +1617,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiBlockBeginAlign(block); but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack"); uiButSetFunc(but, modifiers_applyModifier, ob, md); - if (md->type!=eModifierType_Softbody) { + if ((md->type!=eModifierType_Softbody) && (md->type!=eModifierType_Cloth)) { but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack"); uiButSetFunc(but, modifiers_copyModifier, ob, md); } @@ -3308,6 +3310,9 @@ void do_latticebuts(unsigned short event) if(ob==G.obedit) resizelattice(editLatt, lt->opntsu, lt->opntsv, lt->opntsw, NULL); else resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, NULL); ob->softflag |= OB_SB_REDO; + if(modifiers_isClothEnabled(ob)) { + cloth_free_modifier(modifiers_isClothEnabled(ob)); + } DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); allqueue(REDRAWVIEW3D, 0); } @@ -3316,6 +3321,9 @@ void do_latticebuts(unsigned short event) lt = ob->data; resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, ob); ob->softflag |= OB_SB_REDO; + if(modifiers_isClothEnabled(ob)) { + cloth_free_modifier(modifiers_isClothEnabled(ob)); + } DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); allqueue(REDRAWVIEW3D, 0); } diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index de1d8f8c0ac..df6d88bddd0 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2196,11 +2196,22 @@ void do_object_panels(unsigned short event) if(clmd) { clmd->sim_parms.vgroup_mass = 0; + do_object_panels(B_CLOTH_RENEW); } allqueue(REDRAWBUTSOBJECT, 0); } break; + case B_CLOTH_RENEW: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + do_object_panels(B_CLOTH_CLEARCACHEALL); + cloth_free_modifier (clmd); + } + } + break; default: if(event>=B_SELEFFECT && eventsim_parms.structural, 1.0, 5000.0, 100, 0, "Overall stiffness of structure"); - uiDefButF(block, NUM, B_DIFF, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 1000.0, 1000, 0, "Wrinkle possibility"); - uiDefButI(block, NUM, B_DIFF, "Steps per Frame:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 5000.0, 100, 0, "Overall stiffness of structure"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 1000.0, 1000, 0, "Wrinkle possibility"); + uiDefButI(block, NUM, B_CLOTH_RENEW, "Steps per Frame:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_DIFF, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Spring damping"); uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms.Cvi, 0.0, 10.0, 10, 0, "Apply gravitation to point movement"); uiBlockEndAlign(block); @@ -3123,9 +3134,9 @@ static void object_panel_cloth(Object *ob) uiDefBut(block, LABEL, 0, "Gravity:", 10,100,60,20, NULL, 0.0, 0, 0, 0, ""); // uiClearButLock(); - uiDefButF(block, NUM, B_DIFF, "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_DIFF, "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_DIFF, "Z:", 230,100,80,20, &clmd->sim_parms.gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,100,80,20, &clmd->sim_parms.gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,100,80,20, &clmd->sim_parms.gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:", 230,100,80,20, &clmd->sim_parms.gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); uiBlockEndAlign(block); /* GOAL STUFF */ @@ -3150,7 +3161,7 @@ static void object_panel_cloth(Object *ob) } sprintf (clvg2, "%s%s", clmvg, clvg1); - uiDefButS(block, MENU, REDRAWVIEW3D, clvg2, 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups"); + uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups"); MEM_freeN (clvg1); MEM_freeN (clvg2); @@ -3166,19 +3177,19 @@ static void object_panel_cloth(Object *ob) } else - uiDefButF(block, NUM, REDRAWVIEW3D, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); } else { - uiDefButS(block, TOG, REDRAWVIEW3D, "W", 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + uiDefButS(block, TOG, B_CLOTH_RENEW, "W", 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); } - uiDefButF(block, NUM, B_DIFF, "G Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness"); - uiDefButF(block, NUM, B_DIFF, "G Damp:", 160,50,150,20, &clmd->sim_parms.goalfrict , 0.0, 50.0, 10, 0, "Goal (vertex target position) friction"); - uiDefButF(block, NUM, REDRAWVIEW3D, "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, REDRAWVIEW3D, "G Max:", 160,30,150,20, &clmd->sim_parms.maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Damp:", 160,50,150,20, &clmd->sim_parms.goalfrict , 0.0, 50.0, 10, 0, "Goal (vertex target position) friction"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Min:", 10,30,150,20, &clmd->sim_parms.mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Max:", 160,30,150,20, &clmd->sim_parms.maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); } uiBlockEndAlign(block); @@ -3219,6 +3230,9 @@ static void object_panel_cloth_II(Object *ob) if(uiNewPanel(curarea, block, "Cloth Cache", "Physics", 651, 0, 318, 204)==0) return; uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + + uiDefButI(block, NUM, B_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, 10, 0, "Frame on which the simulation stops"); if(clmd->sim_parms.cache) { @@ -3230,17 +3244,17 @@ static void object_panel_cloth_II(Object *ob) else sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms.preroll, clmd->sim_parms.preroll, length); - uiDefBut(block, LABEL, 0, str, 10,160,290,20, NULL, 0.0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Clear cache:", 10,140,290,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, str, 10,140,290,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Clear cache:", 10,120,290,20, NULL, 0.0, 0, 0, 0, ""); uiBlockBeginAlign (block); - uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 10, 120,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache without preroll"); - uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 120,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache"); + uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 10, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache without preroll"); + uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache"); if(length>1) // B_CLOTH_CHANGEPREROLL - uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,100,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); + uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); } else { - uiDefBut(block, LABEL, 0, "No frames cached.", 10,140,290,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "No frames cached.", 10,120,290,20, NULL, 0.0, 0, 0, 0, ""); } uiBlockEndAlign(block); } @@ -3271,7 +3285,7 @@ static void object_panel_cloth_III(Object *ob) uiBlockBeginAlign(block); // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ - uiDefButF(block, NUM, B_DIFF, "Min Distance:", 10,10,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,10,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); uiDefBut(block, LABEL, 0, "",160,10,150,20, NULL, 0.0, 0, 0, 0, ""); uiBlockEndAlign(block); } diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index fcfb1a5c40f..0874f4c3342 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -65,6 +65,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_depsgraph.h" +#include "BKE_cloth.h" #include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_key.h" @@ -72,6 +73,7 @@ #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_texture.h" #include "BKE_utildefines.h" @@ -1312,7 +1314,11 @@ void load_editMesh(void) if(me->id.us>1) { Base *base; for(base= G.scene->base.first; base; base= base->next) { - if(base->object->data==me) { + if(base->object->data==me) { + if(modifiers_isClothEnabled(base->object)) { + cloth_free_modifier(modifiers_isClothEnabled(base->object)); + } + base->object->softflag |= OB_SB_REDO; base->object->recalc |= OB_RECALC_DATA; } diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 44b93789690..81a111e62c2 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -1746,6 +1746,10 @@ void exit_editmode(int flag) /* freedata==0 at render, 1= freedata, 2= do undo b sbObjectToSoftbody(ob); } + if(modifiers_isClothEnabled(ob)) { + cloth_free_modifier(modifiers_isClothEnabled(ob)); + } + if(ob->type==OB_MESH && get_mesh(ob)->mr) multires_edge_level_update(ob, get_mesh(ob)); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 2fdf68951b8..12c1265e7ca 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -75,6 +75,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" @@ -2414,7 +2415,7 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) } } -/* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */ +/* inserting keys, refresh ipo-keys, softbody, cloth, redraw events... (ton) */ /* note; transdata has been freed already! */ void special_aftertrans_update(TransInfo *t) { @@ -2476,13 +2477,15 @@ void special_aftertrans_update(TransInfo *t) } else { base= FIRSTBASE; - while(base) { - + while(base) { if(base->flag & BA_DO_IPO) redrawipo= 1; ob= base->object; if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO; + else if(modifiers_isClothEnabled(ob)) { + cloth_free_modifier(modifiers_isClothEnabled(ob)); + } /* Set autokey if necessary */ if ((!cancelled) && (base->flag & SELECT)){ diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index 8e92fdda38a..ae65b1d9fa6 100644 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -67,6 +67,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" @@ -313,8 +314,16 @@ void recalcData(TransInfo *t) /* bah, softbody exception... recalcdata doesnt reset */ for(base= FIRSTBASE; base; base= base->next) { if(base->object->recalc & OB_RECALC_DATA) + { + ClothModifierData *clmd = NULL; + if(modifiers_isSoftbodyEnabled(base->object)) { base->object->softflag |= OB_SB_REDO; + } + else if(modifiers_isClothEnabled(ob)) { + cloth_free_modifier(modifiers_isClothEnabled(ob)); + } + } } } @@ -347,10 +356,17 @@ void recalcData(TransInfo *t) } } - /* softbody exception */ - if(modifiers_isSoftbodyEnabled(ob)) { - if(ob->recalc & OB_RECALC_DATA) - ob->softflag |= OB_SB_REDO; + /* softbody & cloth exception */ + if(ob->recalc & OB_RECALC_DATA) + { + ClothModifierData *clmd = NULL; + + if(modifiers_isSoftbodyEnabled(ob)) { + ob->softflag |= OB_SB_REDO; + } + else if(modifiers_isClothEnabled(ob)) { + cloth_free_modifier(modifiers_isClothEnabled(ob)); + } } /* proxy exception */ diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c index 2f82cd2e2b2..102aa79d47e 100644 --- a/source/blender/src/vpaint.c +++ b/source/blender/src/vpaint.c @@ -64,6 +64,7 @@ #include "BKE_armature.h" #include "BKE_DerivedMesh.h" +#include "BKE_cloth.h" #include "BKE_customdata.h" #include "BKE_depsgraph.h" #include "BKE_deform.h" @@ -1346,6 +1347,11 @@ void weight_paint(void) /* this flag is event for softbody to refresh weightpaint values */ if(ob->soft) ob->softflag |= OB_SB_REDO; + // same goes for cloth + if(modifiers_isClothEnabled(ob)) { + cloth_free_modifier(modifiers_isClothEnabled(ob)); + } + BIF_undo_push("Weight Paint"); allqueue(REDRAWVIEW3D, 0); } From 7c05d8eb2b254d2f73f50fe3b2ad95c20c689be4 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 17 Sep 2007 10:41:20 +0000 Subject: [PATCH 004/101] Fixed 2 crashers when activating collision object; Also put some additional openMP code in (doesn't hurt since #pragma gets ignored if no openMP available) --- source/blender/blenkernel/intern/cloth.c | 73 +++++++++++++++++++- source/blender/blenkernel/intern/collision.c | 7 +- source/blender/blenkernel/intern/implicit.c | 42 ++++++----- source/blender/blenkernel/intern/kdop.c | 12 ++-- source/blender/src/buttons_object.c | 4 +- 5 files changed, 105 insertions(+), 33 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 18e1d4a6cde..47925e352eb 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -444,6 +444,43 @@ int cloth_cache_search_frame(ClothModifierData *clmd, float time) return 1; } +int cloth_cache_last_frame(ClothModifierData *clmd) +{ + Frame *frame = NULL; + LinkNode *search = NULL; + int temptime = 0; + + Cloth *cloth = NULL; + + if(!clmd) + return 0; + + cloth = clmd->clothObject; + + if(!cloth) + return 0; + + if(clmd->sim_parms.cache) + { + search = clmd->sim_parms.cache; + + // check if frame exists + while(search) + { + frame = search->link; + + if(frame->time > temptime) + { + temptime = frame->time; + } + + search = search->next; + } + } + + return temptime; +} + void cloth_cache_get_frame(ClothModifierData *clmd, float time) { Frame *frame = NULL; @@ -622,8 +659,23 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float deltaTime = current_time - clmd->sim_parms.sim_time; // only be active during a specific period - if((current_time < clmd->sim_parms.firstframe)||(current_time > clmd->sim_parms.lastframe)) + if(current_time < clmd->sim_parms.firstframe) return; + else if(current_time > clmd->sim_parms.lastframe) + { + int frametime = cloth_cache_last_frame(clmd); + if(cloth_cache_search_frame(clmd, frametime)) + { + cloth_cache_get_frame(clmd, frametime); + cloth_to_object (ob, clmd, vertexCos, numverts); + } + return; + } + else if(ABS(deltaTime) >= 2.0f ) // no timewarps allowed + { + if(!cloth_cache_search_frame(clmd, framenr)) + return; + } // unused in the moment clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame; @@ -668,7 +720,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, VECCOPY (verts->txold, verts->x); // Get the current position. - VECCOPY (verts->x, mvert[i].co); + VECCOPY (verts->x, vertexCos[i]); Mat4MulVecfl(ob->obmat, verts->x); // Compute the vertices velocity. @@ -902,6 +954,23 @@ static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh unsigned int i; MVert *mvert = NULL; ClothVertex *verts = NULL; + + /* If we have a clothObject, free it. */ + if (clmd->clothObject != NULL) + cloth_free_modifier (clmd); + + /* Allocate a new cloth object. */ + clmd->clothObject = MEM_callocN (sizeof(Cloth), "cloth"); + if (clmd->clothObject) + { + clmd->clothObject->old_solver_type = -1; + clmd->clothObject->old_collision_type = -1; + } + else if (clmd->clothObject == NULL) + { + modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject."); + return 0; + } switch (ob->type) { diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index cdbac692b35..13327c16006 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -403,7 +403,7 @@ double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData VECCOPY(b[0], cloth2->verts[face2->v1].txold); VECCOPY(b[1], cloth2->verts[face2->v2].txold); VECCOPY(b[2], cloth2->verts[face2->v3].txold); - +#pragma omp critical distance = plNearestPoints(a,b,pa,pb,normal); quadA = quadB = 0; @@ -450,7 +450,7 @@ double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData VECCOPY(b[0], cloth2->verts[indexD].txold); VECCOPY(b[1], cloth2->verts[indexE].txold); VECCOPY(b[2], cloth2->verts[indexF].txold); - +#pragma omp critical tempdistance = plNearestPoints(a,b,tpa,tpb,tnormal); if(tempdistance < distance) @@ -483,7 +483,7 @@ void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clm LinkNode **linknode; double distance = 0; float epsilon = clmd->coll_parms.epsilon; - + collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); linknode = clmd->coll_parms.temp; @@ -505,7 +505,6 @@ void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clm // printf("normal x: %f, y: %f, z: %f\n", collpair->normal[0], collpair->normal[1], collpair->normal[2]); collpair->distance = distance; - BLI_linklist_append(&linknode[tree1->tri_index], collpair); } else diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index c756c220fe6..18044db6049 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -89,7 +89,7 @@ double itval() // intrinsics need better compile flag checking // #include // #include -#include +// #include static struct timeval _itstart, _itend; static struct timezone itz; @@ -247,14 +247,9 @@ DO_INLINE void submul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float s DO_INLINE float dot_lfvector(float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) { unsigned int i = 0; - -#ifndef _WIN32 - float temp __attribute__ ((aligned (16) ) )= 0.0f; // __declspec(align(16)) -#else - float temp = 0.0f; -#endif - -#pragma omp parallel for reduction(+: temp) schedule(guided, 1) + float temp = 0.0; +// schedule(guided, 2) +#pragma omp parallel for reduction(+: temp) for(i = 0; i < verts; i++) { temp += INPR(fLongVectorA[i], fLongVectorB[i]); @@ -264,7 +259,6 @@ DO_INLINE float dot_lfvector(float (*fLongVectorA)[3], float (*fLongVectorB)[3], /* A = B + C --> for big vector */ DO_INLINE void add_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) { - unsigned int i = 0; for(i = 0; i < verts; i++) @@ -576,7 +570,7 @@ DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) /* STATUS: verified */ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (*fLongVector)[3]) { - unsigned int i = 0,j=0; + int i = 0,j=0; zero_lfvector(to, from[0].vcount); /* process diagonal elements */ for(i = 0; i < from[0].vcount; i++) @@ -585,12 +579,21 @@ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (* } /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */ - for(j = from[0].vcount; j < from[0].vcount+from[0].scount; j++) +#pragma parallel for shared(to,from, fLongVector) private(i) + for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) { - muladd_fmatrix_fvector(to[from[j].c], from[j].m, fLongVector[from[j].r]); - muladd_fmatrix_fvector(to[from[j].r], from[j].m, fLongVector[from[j].c]); - } - + // muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); + + to[from[i].c][0] += INPR(from[i].m[0],fLongVector[from[i].r]); + to[from[i].c][1] += INPR(from[i].m[1],fLongVector[from[i].r]); + to[from[i].c][2] += INPR(from[i].m[2],fLongVector[from[i].r]); + + // muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); + + to[from[i].r][0] += INPR(from[i].m[0],fLongVector[from[i].c]); + to[from[i].r][1] += INPR(from[i].m[1],fLongVector[from[i].c]); + to[from[i].r][2] += INPR(from[i].m[2],fLongVector[from[i].c]); + } } /* SPARSE SYMMETRIC add big matrix with big matrix: A = B + C*/ DO_INLINE void add_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) @@ -1195,12 +1198,13 @@ DO_INLINE void calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVect dfdx_spring_type1(dfdx, dir,length,L,k); - dfdv_damp(dfdv, dir,clmd->sim_parms.Cdis); + dfdv_damp(dfdv, dir,clmd->sim_parms.Cdis); + sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, dfdv); sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, dfdv); add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, dfdv); - + } } else // calculate force of bending springs @@ -1424,7 +1428,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase } // call collision function - // result = cloth_bvh_objcollision(clmd, step + dt, bvh_collision_response, dt); + result = cloth_bvh_objcollision(clmd, step + dt, bvh_collision_response, dt); // copy corrected positions back to simulation for(i = 0; i < numverts; i++) diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index cdcb16c67f6..0d9fddf0211 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -728,7 +728,7 @@ DO_INLINE int bvh_overlap(float *bv1, float *bv2) */ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response) { - int i = 0, ret=0; + int i = 0, j = 0, ret=0; /* // Shouldn't be possible @@ -737,8 +737,7 @@ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * 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 @@ -751,7 +750,7 @@ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * if(collision_response) collision_response (clmd, coll_clmd, tree1, tree2); - return 1; + ret = 1; } else { @@ -767,14 +766,15 @@ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * else { // Process the quad tree. - for (i = 0; i < 4; i++) + for (j = 0; j < 4; j++) { // Only traverse nodes that exist. - if (tree1->nodes [i] && bvh_traverse (clmd, coll_clmd, tree1->nodes[i], tree2, step, collision_response)) + if (tree1->nodes [j] && bvh_traverse (clmd, coll_clmd, tree1->nodes[j], tree2, step, collision_response)) ret = 1; } } } + return ret; } diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index df6d88bddd0..2106525e9b2 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3231,8 +3231,8 @@ static void object_panel_cloth_II(Object *ob) uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - 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, 10, 0, "Frame on which the simulation stops"); + uiDefButI(block, NUM, B_DIFF, "First Frame:", 10,160,150,20, &clmd->sim_parms.firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts"); + uiDefButI(block, NUM, B_DIFF, "Last Frame:", 160,160,150,20, &clmd->sim_parms.lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops"); if(clmd->sim_parms.cache) { From 26a0473c8ca6dd0e0c86f09a74ec91a59cc90516 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 17 Sep 2007 11:18:04 +0000 Subject: [PATCH 005/101] compile fix from elubie special request from mfoxdogg: place modifier where you want --- source/blender/blenkernel/intern/modifier.c | 2 +- source/blender/imbuf/intern/thumbs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index d3d41e70d57..7607ce63b9d 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5234,7 +5234,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->type = eModifierTypeType_OnlyDeform; mti->initData = clothModifier_initData; mti->flags = eModifierTypeFlag_AcceptsCVs - | eModifierTypeFlag_RequiresOriginalData; + // | eModifierTypeFlag_RequiresOriginalData; // | eModifierTypeFlag_SupportsMapping // | eModifierTypeFlag_SupportsEditmode // | eModifierTypeFlag_EnableInEditmode; diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index c2e30b091c2..b071331e46b 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -69,7 +69,7 @@ static int get_thumb_dir( char* dir , ThumbSize size) /* yes, applications shouldn't store data there, but so does GIMP :)*/ SHGetSpecialFolderPath(0, dir, CSIDL_PROFILE, 0); #else - home = getenv("HOME"); + char* home = getenv("HOME"); if (!home) return 0; BLI_strncpy(dir, home, FILE_MAX); #endif From ca6e59bc487afeafebdbf4bf76524cfaf767624c Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 17 Sep 2007 11:19:07 +0000 Subject: [PATCH 006/101] stupid missing ";" --- source/blender/blenkernel/intern/modifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 7607ce63b9d..4f1e9a5644c 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5233,7 +5233,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti = INIT_TYPE(Cloth); mti->type = eModifierTypeType_OnlyDeform; mti->initData = clothModifier_initData; - mti->flags = eModifierTypeFlag_AcceptsCVs + mti->flags = eModifierTypeFlag_AcceptsCVs; // | eModifierTypeFlag_RequiresOriginalData; // | eModifierTypeFlag_SupportsMapping // | eModifierTypeFlag_SupportsEditmode From 0e502338fc68e35412c108252e8c1c6f4a544ec2 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 17 Sep 2007 13:25:29 +0000 Subject: [PATCH 007/101] disable parallel for users --- intern/elbeem/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/elbeem/SConscript b/intern/elbeem/SConscript index 75d9b98c82a..bb6637ba32d 100644 --- a/intern/elbeem/SConscript +++ b/intern/elbeem/SConscript @@ -5,7 +5,7 @@ Import('env') sources = env.Glob('intern/*.cpp') -defs = 'PARALLEL NOGUI ELBEEM_BLENDER=1' +defs = 'NOGUI ELBEEM_BLENDER=1' if env['OURPLATFORM']=='win32-vc': defs += ' USE_MSVC6FIXES' incs = env['BF_PNG_INC'] + ' ' + env['BF_ZLIB_INC'] + ' ' +env['BF_SDL_INC'] From deceff52d132041d3f6761a102966dc1aa1299be Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 17 Sep 2007 19:32:15 +0000 Subject: [PATCH 008/101] Add WITH_BF_OPENMP for openmp usage, untested on msvc --- SConstruct | 12 ++++++++++++ intern/elbeem/SConscript | 6 +++++- source/blender/blenkernel/BKE_blender.h | 2 +- tools/btools.py | 7 +++++-- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/SConstruct b/SConstruct index 2cacb91d103..c7a7ac5e298 100644 --- a/SConstruct +++ b/SConstruct @@ -176,6 +176,18 @@ if env['BF_NO_ELBEEM'] == 1: env['CXXFLAGS'].append('-DDISABLE_ELBEEM') env['CCFLAGS'].append('-DDISABLE_ELBEEM') +if env['WITH_BF_OPENMP'] == 1: + if env['OURPLATFORM']=='win32-vc': + env['PLATFORM_LINKFLAGS'].append('/openmp') + env['CCFLAGS'].append('/openmp') + env['CPPFLAGS'].append('/openmp') + env['CXXFLAGS'].append('/openmp') + else: + env['PLATFORM_LINKFLAGS'].append('-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'): diff --git a/intern/elbeem/SConscript b/intern/elbeem/SConscript index bb6637ba32d..bdcb0507987 100644 --- a/intern/elbeem/SConscript +++ b/intern/elbeem/SConscript @@ -5,7 +5,11 @@ Import('env') sources = env.Glob('intern/*.cpp') -defs = 'NOGUI ELBEEM_BLENDER=1' +defs = ' NOGUI ELBEEM_BLENDER=1' + +if env['WITH_BF_OPENMP'] == 1: + defs += ' PARALLEL' + if env['OURPLATFORM']=='win32-vc': defs += ' USE_MSVC6FIXES' incs = env['BF_PNG_INC'] + ' ' + env['BF_ZLIB_INC'] + ' ' +env['BF_SDL_INC'] diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index e2d2dab9aae..6bddd9de932 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -44,7 +44,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 245 -#define BLENDER_SUBVERSION 0 +#define BLENDER_SUBVERSION 1 #define BLENDER_MINVERSION 240 #define BLENDER_MINSUBVERSION 0 diff --git a/tools/btools.py b/tools/btools.py index eb8f844df4d..1b91a3343dc 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -55,8 +55,9 @@ def validate_arguments(args, bc): 'BF_VERSE_INCLUDE', 'VERSE_BUILD_BINARY', 'VERSE_BUILD_DIR', 'VERSE_REGEN_PROTO', 'BF_TWEAK_MODE', - 'WITHOUT_BF_INSTALL' - ] + 'WITHOUT_BF_INSTALL', + 'WITH_BF_OPENMP' + ] arg_list = ['BF_DEBUG', 'BF_QUIET', 'BF_CROSS', 'BF_UPDATE', 'BF_INSTALLDIR', 'BF_TOOLSET', 'BF_BINNAME', @@ -247,6 +248,8 @@ def read_opts(cfg, args): ('BF_FREETYPE_LIB', 'Freetype library', ''), ('BF_FREETYPE_LIBPATH', 'Freetype library path', ''), + (BoolOption('WITH_BF_OPENMP', 'Use OpenMP if true', 'false')), + (BoolOption('WITH_BF_QUICKTIME', 'Use QuickTime if true', 'false')), ('BF_QUICKTIME', 'QuickTime base path', ''), ('BF_QUICKTIME_INC', 'QuickTime include path', ''), From 969397ced28159562ad350ba595da9833266f6ae Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 17 Sep 2007 19:57:47 +0000 Subject: [PATCH 009/101] bf-blender/trunk/blender rev 12059 + 12060 + 12064 merged (this commit is only 12059, others are already merged) --- source/blender/src/editview.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index 176821e0cc9..bd90d887cd0 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -2063,15 +2063,23 @@ void set_render_border(void) G.scene->r.border.ymin= ((float)rect.ymin-vb.ymin)/(vb.ymax-vb.ymin); G.scene->r.border.xmax= ((float)rect.xmax-vb.xmin)/(vb.xmax-vb.xmin); G.scene->r.border.ymax= ((float)rect.ymax-vb.ymin)/(vb.ymax-vb.ymin); - + CLAMP(G.scene->r.border.xmin, 0.0, 1.0); CLAMP(G.scene->r.border.ymin, 0.0, 1.0); CLAMP(G.scene->r.border.xmax, 0.0, 1.0); CLAMP(G.scene->r.border.ymax, 0.0, 1.0); - + allqueue(REDRAWVIEWCAM, 1); - /* if it was not set, we do this */ - G.scene->r.mode |= R_BORDER; + + /* drawing a border surrounding the entire camera view switches off border rendering */ + if (G.scene->r.border.xmin <= 0.0 && G.scene->r.border.xmax >= 1.0 && + G.scene->r.border.ymin <= 0.0 && G.scene->r.border.ymax >= 1.0) + { + G.scene->r.mode &= ~R_BORDER; + } else { + G.scene->r.mode |= R_BORDER; + } + allqueue(REDRAWBUTSSCENE, 1); } } From f473f4ee7987e9f2d66c5f0821bb826ab194a082 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 17 Sep 2007 21:03:45 +0000 Subject: [PATCH 010/101] Fix: No GAMEENGINE=1 needed anymore, only WITH_BF_BULLET=1. Fix: (Hopefully) some fix for linking openmp --- SConstruct | 4 ++-- extern/SConscript | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/SConstruct b/SConstruct index c7a7ac5e298..7fad247ec07 100644 --- a/SConstruct +++ b/SConstruct @@ -178,12 +178,12 @@ if env['BF_NO_ELBEEM'] == 1: if env['WITH_BF_OPENMP'] == 1: if env['OURPLATFORM']=='win32-vc': - env['PLATFORM_LINKFLAGS'].append('/openmp') + env.Append(LINKFLAGS=['/openmp']) env['CCFLAGS'].append('/openmp') env['CPPFLAGS'].append('/openmp') env['CXXFLAGS'].append('/openmp') else: - env['PLATFORM_LINKFLAGS'].append('-lgomp') + env.Append(LINKFLAGS=['-lgomp']) env['CCFLAGS'].append('-fopenmp') env['CPPFLAGS'].append('-fopenmp') env['CXXFLAGS'].append('-fopenmp') diff --git a/extern/SConscript b/extern/SConscript index 0cdf9676862..77e8998e359 100644 --- a/extern/SConscript +++ b/extern/SConscript @@ -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']) From 9dbcffadec1b537e68435d01e5b632d4763a7150 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 18 Sep 2007 07:16:57 +0000 Subject: [PATCH 011/101] Temporary fix for loading crash of .blends with cached frames. Also fixed some goal behavior/init problem to match SB behaviour --- source/blender/blenkernel/intern/cloth.c | 14 ++++++---- source/blender/blenkernel/intern/implicit.c | 2 +- source/blender/blenkernel/intern/modifier.c | 1 + source/blender/blenloader/intern/readfile.c | 10 ++++--- source/blender/blenloader/intern/writefile.c | 29 +++++++++++++++++--- 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 47925e352eb..14370b59d68 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -913,13 +913,10 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v verts = clothObj->verts; for (i = 0; i < numverts; i++, verts++) - { - /* so this will definily be below SOFTGOALSNAP */ - verts->goal= 0.0f; - + { // LATER ON, support also mass painting here if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) - { + { dvert = dm->getVertData(dm, i, CD_MDEFORMVERT); if(dvert) { @@ -1211,7 +1208,12 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d Mat4MulVecfl(ob->obmat, verts->x); verts->mass = clmd->sim_parms.mass; - verts->goal= clmd->sim_parms.defgoal; + + if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) + verts->goal= clmd->sim_parms.defgoal; + else + verts->goal= 0.0f; + verts->flags = 0; VECCOPY(verts->xold, verts->x); VECCOPY(verts->xconst, verts->x); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 18044db6049..aa28f0a2086 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -570,7 +570,7 @@ DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) /* STATUS: verified */ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (*fLongVector)[3]) { - int i = 0,j=0; + unsigned int i = 0,j=0; zero_lfvector(to, from[0].vcount); /* process diagonal elements */ for(i = 0; i < from[0].vcount; i++) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 4f1e9a5644c..546247f8e35 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4873,6 +4873,7 @@ static void clothModifier_deformVerts( DerivedMesh *dm = NULL; // if possible use/create DerivedMesh + if(derivedData) dm = CDDM_copy(derivedData); else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 19f74096e54..3fbfef12f1f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2878,11 +2878,13 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) ClothModifierData *clmd = (ClothModifierData*) md; clmd->clothObject = NULL; - /* - if (clmd->sim_parms.flags & CSIMSETT_FLAG_BAKED) { - clmd->baked_data = newdataadr (fd, clmd->baked_data); + clmd->sim_parms.cache = NULL; + + if (clmd->sim_parms.cache) { + // TODO + // clmd->cache = newdataadr (fd, clmd->cache); printf ("direct_link_modifiers: read cloth baked_data.\n"); - }*/ + } } else if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 4203824ae65..0a0c49c5ef8 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -813,6 +813,23 @@ static void write_constraint_channels(WriteData *wd, ListBase *chanbase) } +/* +// TODO: finish this +static void write_cloth_cache(WriteData *wd, LinkNode *ln) +{ + + while(ln) { + writestruct(wd, DATA, "cloth_cache", 1, ln); + writestruct(wd, DATA, "cloth_cache_frame", 1, ln->link); + writestruct(wd, DATA, "cloth_cache_frame_verts", 1, ln->link); + writestruct(wd, DATA, "cloth_cache_frame_springs", 1, ln->link); + } + + ln = ln->next; + } +} +*/ + static void write_modifiers(WriteData *wd, ListBase *modbase) { ModifierData *md; @@ -832,16 +849,20 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) else if (md->type==eModifierType_Cloth) { int n; ClothModifierData *clmd = (ClothModifierData *) md; - /* - if ((clmd->sim_parms.flags & CSIMSETT_FLAG_BAKED) && clmd->baked_data) { + + if (clmd->sim_parms.cache) { // Compute the number of vertices we're saving. - + // TODO + // write_cloth_cache(); + /* + // old code n = (clmd->sim_parms.bake_end_frame - clmd->sim_parms.bake_start_frame + 1) * clmd->sim_parms.bake_num_verts; writedata (wd, DATA, n * sizeof (clmd->baked_data [0]), clmd->baked_data); printf ("write_modifiers: wrote %d elements of size %d for cloth baked data.\n", n, sizeof (clmd->baked_data [0])); - }*/ + */ + } } } } From 138b436914e6d42acae589633443477bae4425ad Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 18 Sep 2007 11:42:52 +0000 Subject: [PATCH 012/101] Fixed floating point rounding error in goal velocity computation, pointed out my mfoxdogg, additional code cleanup --- source/blender/blenkernel/intern/cloth.c | 2 +- source/blender/blenkernel/intern/implicit.c | 43 +++++++++++---------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 14370b59d68..40f3c9816a6 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -764,7 +764,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, Mat4MulVecfl(ob->obmat, verts->xconst); /* Compute the vertices velocity. */ - VECSUB (verts->v, verts->x, verts->xold); + VECSUB (verts->v, verts->xconst, verts->xold); } tstart(); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index aa28f0a2086..df5830f6a77 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -736,7 +736,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) { id->A[i].r = id->A[i].c = id->dFdV[i].r = id->dFdV[i].c = id->dFdX[i].r = id->dFdX[i].c = id->P[i].c = id->P[i].r = id->Pinv[i].c = id->Pinv[i].r = id->bigI[i].c = id->bigI[i].r = i; - if(verts [i].flags & CVERT_FLAG_PINNED) + if(verts [i].goal >= SOFTGOALSNAP) { id->S[pinned].pinned = 1; id->S[pinned].c = id->S[pinned].r = i; @@ -1199,8 +1199,9 @@ DO_INLINE void calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVect dfdx_spring_type1(dfdx, dir,length,L,k); dfdv_damp(dfdv, dir,clmd->sim_parms.Cdis); - + sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, dfdv); + sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, dfdv); add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, dfdv); @@ -1315,15 +1316,15 @@ void calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *l mul_fvector_S(tvect, tvect, time); VECADD(tvect, tvect, verts[i].xold); - VecSubf(auxvect, tvect, lX[i]); + VECSUB(auxvect, tvect, lX[i]); ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms.goalspring)-1.0f ; VECADDS(lF[i], lF[i], auxvect, -ks); - /* calulate damping forces generated by goals*/ + // calulate damping forces generated by goals VECSUB(velgoal,verts[i].xold, verts[i].xconst); kd = clmd->sim_parms.goalfrict * 0.01f; // friction force scale taken from SB VECSUBADDSS(lF[i], velgoal, kd, lV[i], kd); - + } } } @@ -1404,6 +1405,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase if(verts [i].goal >= SOFTGOALSNAP) { VECSUB(id->V[i], verts[i].xconst, verts[i].xold); + // VecMulf(id->V[i], 1.0 / dt); } } } @@ -1413,15 +1415,30 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase effectors= pdInitEffectors(ob,NULL); // calculate - calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); + calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV); + add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); // collisions itstart(); + // update verts to current positions for(i = 0; i < numverts; i++) { + if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) /* do goal stuff */ + { + if(verts [i].goal >= SOFTGOALSNAP) + { + float tvect[3] = {.0,.0,.0}; + // VECSUB(tvect, id->Xnew[i], verts[i].xold); + mul_fvector_S(tvect, id->V[i], step+dt); + VECADD(tvect, tvect, verts[i].xold); + VECCOPY(id->Xnew[i], tvect); + } + + } + VECCOPY(verts[i].tx, id->Xnew[i]); VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); @@ -1433,7 +1450,6 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // copy corrected positions back to simulation for(i = 0; i < numverts; i++) { - // TODO: calculate v_n+1 from v_n+1/2 if(result) { VECADD(verts[i].tx, verts[i].txold, verts[i].tv); @@ -1509,23 +1525,10 @@ void implicit_set_positions (ClothModifierData *clmd) ClothVertex *verts = cloth->verts; unsigned int numverts = cloth->numverts, i; Implicit_Data *id = cloth->implicit; - unsigned int pinned = 0; - - // reset pinned verts in S matrix to zero - // id->S[0].vcount = 0; id->S[0].scount = 0; for(i = 0; i < numverts; i++) { VECCOPY(id->X[i], verts[i].x); VECCOPY(id->V[i], verts[i].v); - /* - if(verts [i].flags & CVERT_FLAG_PINNED) - { - id->S[pinned].pinned = 1; - id->S[pinned].c = id->S[pinned].r = i; - pinned++; - } - */ } - // id->S[0].vcount = pinned; } From b852223456d9b12ee2e80488ccedc5af65be48e6 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 18 Sep 2007 14:05:36 +0000 Subject: [PATCH 013/101] arround 50% speedup in calculating spring force using OpenMP --- source/blender/blenkernel/BKE_cloth.h | 3 + source/blender/blenkernel/intern/cloth.c | 6 +- source/blender/blenkernel/intern/implicit.c | 139 +++++++++++++------- source/blender/makesdna/DNA_cloth_types.h | 3 + 4 files changed, 98 insertions(+), 53 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 0a50feeb9b0..b9861049fb4 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -52,6 +52,8 @@ struct DerivedMesh; #define DO_INLINE #endif +#define CLOTH_MAX_THREAD 2 + /* goal defines */ #define SOFTGOALSNAP 0.999f @@ -103,6 +105,7 @@ typedef enum typedef enum { CSPRING_FLAG_DEACTIVATE = (1 << 1), + CSPRING_FLAG_NEEDED = (1 << 2), // springs has values to be applied } CSPRINGS_FLAGS; // needed for buttons_object.c diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 40f3c9816a6..57975e56cc3 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -117,10 +117,6 @@ static CM_SOLVER_DEF solvers [] = { // { "Implicit C++", CM_IMPLICITCPP, implicitcpp_init, implicitcpp_solver, implicitcpp_free }, }; -#define DEBUG_CLOTH_VERBOSE 1000 -static int DEBUG_CLOTH = 0; - - /* ********** cloth engine ******* */ /* Prototypes for internal functions. */ @@ -774,7 +770,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors,0,0); tend(); - printf("Cloth simulation time: %f\n", (float)tval()); + // printf("Cloth simulation time: %f\n", (float)tval()); cloth_cache_set_frame(clmd, framenr); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index df5830f6a77..a6fcf7a9a5e 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -570,7 +570,7 @@ DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) /* STATUS: verified */ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (*fLongVector)[3]) { - unsigned int i = 0,j=0; + unsigned int i = 0; zero_lfvector(to, from[0].vcount); /* process diagonal elements */ for(i = 0; i < from[0].vcount; i++) @@ -579,7 +579,8 @@ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (* } /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */ -#pragma parallel for shared(to,from, fLongVector) private(i) + // TODO: pragma below is wrong, correct it! + // #pragma omp parallel for shared(to,from, fLongVector) private(i) for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) { // muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); @@ -804,11 +805,13 @@ int implicit_free (ClothModifierData *clmd) return 1; } + DO_INLINE float fb(float length, float L) { float x = length/L; return (-11.541f*pow(x,4)+34.193f*pow(x,3)-39.083f*pow(x,2)+23.116f*x-9.713f); } + DO_INLINE float fbderiv(float length, float L) { float x = length/L; @@ -827,6 +830,7 @@ DO_INLINE float fbstar(float length, float L, float kb, float cb) else return tempfb; } + DO_INLINE float fbstar_jacobi(float length, float L, float kb, float cb) { float tempfb = kb * fb(length, L); @@ -841,6 +845,7 @@ DO_INLINE float fbstar_jacobi(float length, float L, float kb, float cb) return kb * fbderiv(length, L); } } + DO_INLINE void filter(lfVector *V, fmatrix3x3 *S) { unsigned int i=0; @@ -850,6 +855,7 @@ DO_INLINE void filter(lfVector *V, fmatrix3x3 *S) mul_fvector_fmatrix(V[S[i].r], V[S[i].r], S[i].m); } } + // block diagonalizer void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *S, fmatrix3x3 *bigI) { @@ -874,6 +880,7 @@ void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *S, } } + int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) { // Solves for unknown X in equation AX=B @@ -1101,17 +1108,20 @@ DO_INLINE void dfdx_spring_type1(float to[3][3], float dir[3],float length,float mul_fmatrix_S(temp, k); add_fmatrix_fmatrix(to, temp, to); } + DO_INLINE void dfdx_spring_type2(float to[3][3], float dir[3],float length,float L,float k, float cb) { // return outerprod(dir,dir)*fbstar_jacobi(length, L, k, cb); mul_fvectorT_fvectorS(to, dir, dir, fbstar_jacobi(length, L, k, cb)); } + DO_INLINE void dfdv_damp(float to[3][3], float dir[3], float damping) { // derivative of force wrt velocity. // return outerprod(dir,dir) * damping; mul_fvectorT_fvectorS(to, dir, dir, damping); } + DO_INLINE void dfdx_spring(float to[3][3], float dir[3],float length,float L,float k) { // dir is unit length direction, rest is spring's restlength, k is spring constant. @@ -1122,6 +1132,7 @@ DO_INLINE void dfdx_spring(float to[3][3], float dir[3],float length,float L,fl sub_fmatrix_fmatrix(to, to, I); mul_fmatrix_S(to, -k); } + DO_INLINE void dfdx_damp(float to[3][3], float dir[3],float length,const float vel[3],float rest,float damping) { // inner spring damping vel is the relative velocity of the endpoints. @@ -1132,7 +1143,7 @@ DO_INLINE void dfdx_damp(float to[3][3], float dir[3],float length,const float } -DO_INLINE void calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) +DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) { float extent[3]; float length = 0; @@ -1142,25 +1153,28 @@ DO_INLINE void calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVect float L = s->restlen; float cb = clmd->sim_parms.structural; - float f[3] = {0,0,0}; + float nullf[3] = {0,0,0}; float stretch_force[3] = {0,0,0}; float bending_force[3] = {0,0,0}; float damping_force[3] = {0,0,0}; - float dfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; - float dfdv[3][3]; - int needed = 0; + float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; Cloth *cloth = clmd->clothObject; ClothVertex *verts = cloth->verts; + + VECCOPY(s->f, nullf); + cp_fmatrix(s->dfdx, nulldfdx); + cp_fmatrix(s->dfdv, nulldfdx); // calculate elonglation VECSUB(extent, X[s->kl], X[s->ij]); VECSUB(vel, V[s->kl], V[s->ij]); length = sqrt(INPR(extent, extent)); - + s->flags &= ~CSPRING_FLAG_NEEDED; if(length > ABS(ALMOST_ZERO)) { + /* if(length>L) { if((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) @@ -1170,7 +1184,7 @@ DO_INLINE void calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVect return; } } - + */ mul_fvector_S(dir, extent, 1.0f/length); } else @@ -1184,55 +1198,37 @@ DO_INLINE void calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVect { if(length > L) // only on elonglation { - needed++; + s->flags |= CSPRING_FLAG_NEEDED; k = clmd->sim_parms.structural; mul_fvector_S(stretch_force, dir, (k*(length-L))); - VECADD(f, f, stretch_force); + VECADD(s->f, s->f, stretch_force); // Ascher & Boxman, p.21: Damping only during elonglation mul_fvector_S(damping_force, extent, clmd->sim_parms.Cdis * ((INPR(vel,extent)/length))); - VECADD(f, f, damping_force); + VECADD(s->f, s->f, damping_force); - dfdx_spring_type1(dfdx, dir,length,L,k); + dfdx_spring_type1(s->dfdx, dir,length,L,k); - dfdv_damp(dfdv, dir,clmd->sim_parms.Cdis); - - sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, dfdv); - - sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, dfdv); - - add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, dfdv); - + dfdv_damp(s->dfdv, dir,clmd->sim_parms.Cdis); } } else // calculate force of bending springs { if(length < L) { - k = clmd->sim_parms.bending; - - needed++; + s->flags |= CSPRING_FLAG_NEEDED; + + k = clmd->sim_parms.bending; mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); - VECADD(f, f, bending_force); + VECADD(s->f, s->f, bending_force); - dfdx_spring_type2(dfdx, dir,length,L,k, cb); + dfdx_spring_type2(s->dfdx, dir,length,L,k, cb); } } - - if(needed) - { - VECADD(lF[s->ij], lF[s->ij], f); - VECSUB(lF[s->kl], lF[s->kl], f); - - sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, dfdx); - sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, dfdx); - - add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, dfdx); - } } DO_INLINE void calculateTriangleNormal(float to[3], lfVector *X, MFace mface) @@ -1275,7 +1271,7 @@ DO_INLINE void calc_triangle_force(ClothModifierData *clmd, MFace mface, lfVecto } -void calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time) +void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time) { /* Collect forces and derivatives: F,dFdX,dFdV */ Cloth *cloth = clmd->clothObject; @@ -1332,9 +1328,10 @@ void calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *l /* handle external forces like wind */ if(effectors) { - float wind[3] = {0,1.0f,0}; + float wind[3] = {0.0f,1.0f,0.0f}; float force[3]= {0.0f, 0.0f, 0.0f}; - + + #pragma omp parallel for private (i) shared(lF) for(i = 0; i < cloth->numverts; i++) { float vertexnormal[3]={0,0,0}; @@ -1348,17 +1345,55 @@ void calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *l VECADDS(lF[i], lF[i], wind_normalized, -calculateVertexWindForce(i, wind, vertexnormal)); } } - + /* calculate and apply spring forces */ +#pragma omp parallel private(i) + { +#pragma omp for nowait + for(i = 0; i < cloth->numsprings/2; i++) + { + // only handle active springs + // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) + // { + cloth_calc_spring_force(clmd, &springs[i], lF, lX, lV, dFdV, dFdX); + // } + } +#pragma omp for nowait + for(i = cloth->numsprings/2; i < cloth->numsprings; i++) + { + // only handle active springs + // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) + // { + cloth_calc_spring_force(clmd, &springs[i], lF, lX, lV, dFdV, dFdX); + // } + } +#pragma omp for nowait for(i = 0; i < cloth->numsprings; i++) { // only handle active springs - if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) + // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) { - calc_spring_force(clmd, &springs[i], lF, lX, lV, dFdV, dFdX); + ClothSpring *s = &springs[i]; + if(s->flags & CSPRING_FLAG_NEEDED) + { + if(s->type != BENDING) + { + sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, s->dfdv); + sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv); + add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); + } + + VECADD(lF[s->ij], lF[s->ij], s->f); + VECSUB(lF[s->kl], lF[s->kl], s->f); + + sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx); + sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, s->dfdx); + + add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, s->dfdx); + } } } - + } } void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV) @@ -1375,12 +1410,20 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto mul_bfmatrix_lfvector(dFdXmV, dFdX, lV); add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts); + + itstart(); + cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */ // cg_filtered_pre(dV, A, B, z, olddV, dt); + + itend(); + // printf("cg_filtered calc time: %f\n", (float)itval()); + cp_lfvector(olddV, dV, numverts); // advance velocities add_lfvector_lfvector(Vnew, lV, dV, numverts); + del_lfvector(dFdXmV); } @@ -1415,13 +1458,13 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase effectors= pdInitEffectors(ob,NULL); // calculate - calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); + cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV); add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); // collisions - itstart(); + // itstart(); // update verts to current positions for(i = 0; i < numverts; i++) @@ -1477,11 +1520,11 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase cp_lfvector(id->V, id->Vnew, numverts); // calculate - calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); + cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV); } - itend(); + // itend(); // printf("collision time: %f\n", (float)itval()); // V = Vnew; diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index c756c29f467..c0a47452e3e 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -64,6 +64,9 @@ typedef struct ClothSpring { int matrix_index; /* needed for implicit */ int type; int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ + float dfdx[3][3]; + float dfdv[3][3]; + float f[3]; } ClothSpring; From 98e8486bafc3cb506bb9dead50e9ca9ddbbf857d Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 18 Sep 2007 19:56:58 +0000 Subject: [PATCH 014/101] Fix: kicked springs caching since it's unused and needs lots of memory --- source/blender/blenkernel/intern/cloth.c | 16 ++++++++++------ source/blender/blenkernel/intern/implicit.c | 17 ++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 57975e56cc3..194aa06fc3b 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -518,12 +518,13 @@ void cloth_cache_get_frame(ClothModifierData *clmd, float time) memcpy(cloth->verts, frame->verts, cloth->numverts*sizeof(ClothVertex)); implicit_set_positions(clmd); } - + /* if(frame->springs) { // copy ClothSpring struct memcpy(cloth->springs, frame->springs, cloth->numsprings*sizeof(ClothSpring)); } + */ } } } @@ -546,7 +547,10 @@ void cloth_cache_set_frame(ClothModifierData *clmd, float time) // creat new frame cache frame = (Frame *)MEM_callocN(sizeof(Frame), "cloth frame cache"); frame->verts = (ClothVertex *)MEM_callocN(sizeof(ClothVertex)*cloth->numverts, "cloth frame vertex cache"); + frame->springs = NULL; + /* frame->springs = (ClothSpring *)MEM_callocN(sizeof(ClothSpring)*cloth->numsprings, "cloth frame spring cache"); + */ frame->time = newtime; // copy ClothVertex struct @@ -554,13 +558,13 @@ void cloth_cache_set_frame(ClothModifierData *clmd, float time) { memcpy(&frame->verts[i], &cloth->verts[i], sizeof(ClothVertex)); } - + /* // copy ClothSpring struct for(i = 0; i < cloth->numsprings; i++) { memcpy(&frame->springs[i], &cloth->springs[i], sizeof(ClothSpring)); } - + */ } if(frame) { @@ -600,7 +604,7 @@ void cloth_cache_free(ClothModifierData *clmd, float time) && (frame->time > newtime)) // do not delete the first frame { MEM_freeN(frame->verts); - MEM_freeN(frame->springs); + // MEM_freeN(frame->springs); MEM_freeN(frame); MEM_freeN(search); last_search->next = next; @@ -608,7 +612,7 @@ void cloth_cache_free(ClothModifierData *clmd, float time) else if(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_FREE_ALL) // free COMPLETE cache { MEM_freeN(frame->verts); - MEM_freeN(frame->springs); + // MEM_freeN(frame->springs); MEM_freeN(frame); } else @@ -770,7 +774,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors,0,0); tend(); - // printf("Cloth simulation time: %f\n", (float)tval()); + printf("Cloth simulation time: %f\n", (float)tval()); cloth_cache_set_frame(clmd, framenr); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index a6fcf7a9a5e..3b19839c77d 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -947,7 +947,7 @@ int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatr return conjgrad_loopcountnumsprings/2; i++) { @@ -1367,7 +1367,8 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec cloth_calc_spring_force(clmd, &springs[i], lF, lX, lV, dFdV, dFdX); // } } -#pragma omp for nowait +} // pragma omp parallel + for(i = 0; i < cloth->numsprings; i++) { // only handle active springs @@ -1393,15 +1394,13 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec } } } - } } -void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV) +void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv) { unsigned int numverts = dFdV[0].vcount; lfVector *dFdXmV = create_lfvector(numverts); - initdiag_bfmatrix(A, I); zero_lfvector(dV, numverts); @@ -1414,7 +1413,7 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto itstart(); cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */ - // cg_filtered_pre(dV, A, B, z, olddV, dt); + // cg_filtered_pre(dV, A, B, z, olddV, P, Pinv, dt); itend(); // printf("cg_filtered calc time: %f\n", (float)itval()); @@ -1459,7 +1458,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // calculate cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); - simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); @@ -1521,7 +1520,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // calculate cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); - simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); } // itend(); From 6e755b908951e85c03e15d1e836413ecac58f4bf Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 19 Sep 2007 08:07:47 +0000 Subject: [PATCH 015/101] Fixed wind force direction (reported by mfoxdogg) --- source/blender/blenkernel/intern/collision.c | 8 ++++---- source/blender/blenkernel/intern/implicit.c | 2 +- source/blender/blenkernel/intern/kdop.c | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 13327c16006..c70bf461920 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -403,7 +403,7 @@ double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData VECCOPY(b[0], cloth2->verts[face2->v1].txold); VECCOPY(b[1], cloth2->verts[face2->v2].txold); VECCOPY(b[2], cloth2->verts[face2->v3].txold); -#pragma omp critical + distance = plNearestPoints(a,b,pa,pb,normal); quadA = quadB = 0; @@ -450,7 +450,7 @@ double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData VECCOPY(b[0], cloth2->verts[indexD].txold); VECCOPY(b[1], cloth2->verts[indexE].txold); VECCOPY(b[2], cloth2->verts[indexF].txold); -#pragma omp critical + tempdistance = plNearestPoints(a,b,tpa,tpb,tnormal); if(tempdistance < distance) @@ -531,7 +531,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE cloth = clmd->clothObject; cloth_bvh = (BVH *) cloth->tree; numverts = clmd->clothObject->numverts; - + //////////////////////////////////////////////////////////// // static collisions //////////////////////////////////////////////////////////// @@ -586,7 +586,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response); result += collision_static(clmd, coll_clmd, collision_list); - + printf("result: %d\n", result); // calculate velocities // free temporary list diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 3b19839c77d..cfe17376797 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1342,7 +1342,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec Normalize(wind_normalized); calculateWeightedVertexNormal(clmd, mfaces, vertexnormal, i, lX); - VECADDS(lF[i], lF[i], wind_normalized, -calculateVertexWindForce(i, wind, vertexnormal)); + VECADDS(lF[i], lF[i], wind_normalized, calculateVertexWindForce(i, wind, vertexnormal)); } } diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 0d9fddf0211..0088ff92364 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -728,7 +728,7 @@ DO_INLINE int bvh_overlap(float *bv1, float *bv2) */ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response) { - int i = 0, j = 0, ret=0; + int i = 0, ret=0; /* // Shouldn't be possible @@ -750,7 +750,7 @@ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * if(collision_response) collision_response (clmd, coll_clmd, tree1, tree2); - ret = 1; + return 1; } else { @@ -766,10 +766,10 @@ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * else { // Process the quad tree. - for (j = 0; j < 4; j++) + for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree1->nodes [j] && bvh_traverse (clmd, coll_clmd, tree1->nodes[j], tree2, step, collision_response)) + if (tree1->nodes [i] && bvh_traverse (clmd, coll_clmd, tree1->nodes[i], tree2, step, collision_response)) ret = 1; } } From 4c7c711b8a7fb14e15934fa300bfcef2f038c4f7 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 19 Sep 2007 12:13:16 +0000 Subject: [PATCH 016/101] Fixed collision object init, New: Apply collision impulses so minimum distance is preserved (friction still missing) --- source/blender/blenkernel/intern/cloth.c | 41 ++++----- source/blender/blenkernel/intern/collision.c | 92 +++++++++++++------- source/blender/blenkernel/intern/implicit.c | 1 + source/blender/src/buttons_object.c | 1 - 4 files changed, 84 insertions(+), 51 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 194aa06fc3b..635da0515cb 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -657,24 +657,28 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, Frame *frame = NULL; LinkNode *search = NULL; float deltaTime = current_time - clmd->sim_parms.sim_time; + // only be active during a specific period - if(current_time < clmd->sim_parms.firstframe) - return; - else if(current_time > clmd->sim_parms.lastframe) + if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) { - int frametime = cloth_cache_last_frame(clmd); - if(cloth_cache_search_frame(clmd, frametime)) - { - cloth_cache_get_frame(clmd, frametime); - cloth_to_object (ob, clmd, vertexCos, numverts); - } - return; - } - else if(ABS(deltaTime) >= 2.0f ) // no timewarps allowed - { - if(!cloth_cache_search_frame(clmd, framenr)) + if(current_time < clmd->sim_parms.firstframe) return; + else if(current_time > clmd->sim_parms.lastframe) + { + int frametime = cloth_cache_last_frame(clmd); + if(cloth_cache_search_frame(clmd, frametime)) + { + cloth_cache_get_frame(clmd, frametime); + cloth_to_object (ob, clmd, vertexCos, numverts); + } + return; + } + else if(ABS(deltaTime) >= 2.0f ) // no timewarps allowed + { + if(!cloth_cache_search_frame(clmd, framenr)) + return; + } } // unused in the moment @@ -693,8 +697,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, // This is for collisions objects: check special case CSIMSETT_FLAG_COLLOBJ if (clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) - { - + { // save next position + time if ((clmd->clothObject == NULL) || (numverts != clmd->clothObject->numverts) ) { @@ -723,7 +726,8 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, VECCOPY (verts->x, vertexCos[i]); Mat4MulVecfl(ob->obmat, verts->x); - // Compute the vertices velocity. + // Compute the vertices "velocity". + // (no dt correction here because of float error) VECSUB (verts->v, verts->x, verts->xold); } @@ -762,9 +766,6 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, /* Get the current position. */ VECCOPY (verts->xconst, vertexCos[i]); Mat4MulVecfl(ob->obmat, verts->xconst); - - /* Compute the vertices velocity. */ - VECSUB (verts->v, verts->xconst, verts->xold); } tstart(); diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index c70bf461920..32a2f820894 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -216,18 +216,18 @@ DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], floa VECADDMUL(to, v3, w3); } + DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal[3], double normalVelocity, double frictionConstant, double delta_V_n) { float vrel_t_pre[3]; float vrel_t[3]; VECSUBS(vrel_t_pre, vrel, normal, normalVelocity); - VECCOPY(vrel_t, vrel_t_pre); - VecMulf(vrel_t, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); - VECSUB(to, vrel_t_pre, vrel_t); - VecMulf(to, 1.0f / 2.0f); + VECCOPY(to, vrel_t_pre); + VecMulf(to, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); } + int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, LinkNode **collision_list) { unsigned int i = 0, numverts=0; @@ -271,6 +271,7 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link face2 = &(cloth2->mfaces[collpair->face2]); // compute barycentric coordinates for both collision points + if(!collpair->quadA) bvh_compute_barycentric(collpair->p1, cloth1->verts[face1->v1].txold, @@ -297,16 +298,17 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link cloth2->verts[face2->v3].txold, &u1, &u2, &u3); - // Calculate relative velocity. + // Calculate relative "velocity". + if(!collpair->quadA) - interpolateOnTriangle(v1, cloth1->verts[face1->v1].v, cloth1->verts[face1->v2].v, cloth1->verts[face1->v3].v, w1, w2, w3); + interpolateOnTriangle(v1, cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv, cloth1->verts[face1->v3].tv, w1, w2, w3); else - interpolateOnTriangle(v1, cloth1->verts[face1->v4].v, cloth1->verts[face1->v1].v, cloth1->verts[face1->v3].v, w1, w2, w3); + interpolateOnTriangle(v1, cloth1->verts[face1->v4].tv, cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv, w1, w2, w3); if(!collpair->quadB) - interpolateOnTriangle(v2, cloth2->verts[face2->v1].v, cloth2->verts[face2->v2].v, cloth2->verts[face2->v3].v, u1, u2, u3); + interpolateOnTriangle(v2, cloth2->verts[face2->v1].tv, cloth2->verts[face2->v2].tv, cloth2->verts[face2->v3].tv, u1, u2, u3); else - interpolateOnTriangle(v2, cloth2->verts[face2->v4].v, cloth2->verts[face2->v1].v, cloth2->verts[face2->v3].v, u1, u2, u3); + interpolateOnTriangle(v2, cloth2->verts[face2->v4].tv, cloth2->verts[face2->v1].tv, cloth2->verts[face2->v3].tv, u1, u2, u3); VECSUB(relativeVelocity, v1, v2); @@ -323,18 +325,22 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link // Calculate Impulse magnitude to stop all motion in normal direction. // const double I_mag = v_n_mag / (1/m1 + 1/m2); float magnitude_i = magrelVel / 2.0f; // TODO implement masses - float tangential[3], magtangent; + float tangential[3], magtangent, magnormal, collvel[3]; + float vrel_t_pre[3]; + float vrel_t[3], impulse; + float epsilon = clmd->coll_parms.epsilon; - calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); + // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); - magtangent = INPR(tangential, tangential); + // magtangent = INPR(tangential, tangential); // Apply friction impulse. if (magtangent > ALMOST_ZERO) { - /* - printf("friction applied: %f\n", magtangent); + + // printf("friction applied: %f\n", magtangent); // TODO check original code + /* VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,tangential); VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv,tangential); VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv,tangential); @@ -345,26 +351,52 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case // Apply the impulse and increase impulse counters. - /* - VECADDMUL(cloth1->verts[face1->v1].tv,collpair->normal, -magnitude_i); - VECADDMUL(cloth1->verts[face1->v2].tv,collpair->normal, -magnitude_i); - VECADDMUL(cloth1->verts[face1->v3].tv,collpair->normal, -magnitude_i); - VECADDMUL(cloth1->verts[face1->v4].tv,collpair->normal, -magnitude_i); - */ + // my try, works better than the papers ones (maybe i did just something wrong) + VECSUB(collvel, cloth1->verts[face1->v1].tv, v2); + magnormal = INPR(collvel, collpair->normal); + if(magnormalverts[face1->v1].tv, collpair->normal); - VECADDMUL(cloth1->verts[face1->v1].tv, collpair->normal, -magtangent); + impulse = (epsilon + ALMOST_ZERO-collpair->distance) / 4.0f; + VECADDMUL(cloth1->verts[face1->v1].tv, collpair->normal, -magnormal + impulse); - magtangent = INPR(cloth1->verts[face1->v2].tv, collpair->normal); - VECADDMUL(cloth1->verts[face1->v2].tv, collpair->normal, -magtangent); + // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent); - magtangent = INPR(cloth1->verts[face1->v3].tv, collpair->normal); - VECADDMUL(cloth1->verts[face1->v3].tv, collpair->normal, -magtangent); +/* + VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); + // VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); + magtangent = Normalize(vrel_t_pre); + VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent)); - magtangent = INPR(cloth1->verts[face1->v4].tv, collpair->normal); - VECADDMUL(cloth1->verts[face1->v4].tv, collpair->normal, -magtangent); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre); +*/ + VECSUB(collvel, cloth1->verts[face1->v2].tv, v2); + magnormal = INPR(collvel, collpair->normal); + if(magnormaldistance) / 4.0f; + VECADDMUL(cloth1->verts[face1->v2].tv, collpair->normal, -magnormal+ impulse); + + + VECSUB(collvel, cloth1->verts[face1->v3].tv, v2); + magnormal = INPR(collvel, collpair->normal); + if(magnormaldistance) / 4.0f; + VECADDMUL(cloth1->verts[face1->v3].tv, collpair->normal, -magnormal+ impulse); + + + VECSUB(collvel, cloth1->verts[face1->v4].tv, v2); + magnormal = INPR(collvel, collpair->normal); + if(magnormaldistance) / 4.0f; + VECADDMUL(cloth1->verts[face1->v4].tv, collpair->normal, -magnormal+ impulse); + result = 1; } @@ -586,7 +618,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response); result += collision_static(clmd, coll_clmd, collision_list); - printf("result: %d\n", result); + // calculate velocities // free temporary list diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index cfe17376797..c54897cc89c 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1484,6 +1484,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase VECCOPY(verts[i].tx, id->Xnew[i]); VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + VECSUB(verts[i].v, verts[i].tx, verts[i].txold); } // call collision function diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 2106525e9b2..1e3439d41b5 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3103,7 +3103,6 @@ static void object_panel_cloth(Object *ob) if(clmd) { but = uiDefButBitI(block, TOG, CSIMSETT_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object", 170,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); - // uiButSetFunc(but, object_cloth__enabletoggle, ob, NULL); if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) { From 5b9140a2093852f58e9d2de8fcc5c0db6b98ea3c Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 21 Sep 2007 13:34:19 +0000 Subject: [PATCH 017/101] Fixed some collision response issues. (weekend commit, some half done work in) --- .../BulletDynamics/Dynamics/Bullet-C-Api.cpp | 5 +- source/blender/blenkernel/BKE_cloth.h | 3 +- source/blender/blenkernel/intern/cloth.c | 121 +++-- source/blender/blenkernel/intern/collision.c | 500 ++++++++++-------- source/blender/blenkernel/intern/implicit.c | 2 +- source/blender/blenkernel/intern/modifier.c | 7 +- source/blender/makesdna/DNA_cloth_types.h | 22 +- source/blender/src/buttons_object.c | 7 +- 8 files changed, 388 insertions(+), 279 deletions(-) diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp index 2ae30e851dc..1b843774609 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp @@ -41,11 +41,10 @@ double plNearestPoints(float p[3][3], float q[3][3], float *pa, float *pb, float static btGjkEpaPenetrationDepthSolver Solver0; static btMinkowskiPenetrationDepthSolver Solver1; - + btConvexPenetrationDepthSolver* Solver = NULL; - Solver = &Solver1; - + Solver = &Solver0; btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,Solver); diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index b9861049fb4..e4d1fb0ca99 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -60,7 +60,7 @@ struct DerivedMesh; /* This is approximately the smallest number that can be * represented by a float, given its precision. */ -#define ALMOST_ZERO 0.0000001 +#define ALMOST_ZERO 0.00001 /* Bits to or into the ClothVertex.flags. */ #define CVERT_FLAG_PINNED 1 @@ -91,6 +91,7 @@ typedef enum CSIMSETT_FLAG_CCACHE_FREE_ALL = (1 << 4), // delete all from cache CSIMSETT_FLAG_CCACHE_FREE_PART = (1 << 5), // delete some part of cache CSIMSETT_FLAG_TEARING_ENABLED = (1 << 6), // true if tearing is enabled + CSIMSETT_FLAG_CCACHE_PROTECT = (1 << 7), // true if tearing is enabled } CSIMSETT_FLAGS; /* Spring types as defined in the paper.*/ diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 635da0515cb..7059c59c65b 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -153,7 +153,7 @@ void cloth_init (ClothModifierData *clmd) clmd->sim_parms.mass = 1.0f; clmd->sim_parms.stepsPerFrame = 5; clmd->sim_parms.sim_time = 1.0; - clmd->sim_parms.flags = CSIMSETT_FLAG_RESET; + clmd->sim_parms.flags = CSIMSETT_FLAG_RESET | CSIMSETT_FLAG_CCACHE_PROTECT; clmd->sim_parms.solver_type = 0; clmd->sim_parms.preroll = 0; clmd->sim_parms.maxspringlen = 10; @@ -576,6 +576,7 @@ void cloth_cache_set_frame(ClothModifierData *clmd, float time) } } +// free cloth cache void cloth_cache_free(ClothModifierData *clmd, float time) { Frame *frame = NULL; @@ -659,7 +660,8 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float deltaTime = current_time - clmd->sim_parms.sim_time; - // only be active during a specific period + // only be active during a specific period: + // that's "first frame" and "last frame" on GUI if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) { if(current_time < clmd->sim_parms.firstframe) @@ -681,7 +683,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, } } - // unused in the moment + // unused in the moment, calculated seperately in implicit.c clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame; clmd->sim_parms.sim_time = current_time; @@ -812,46 +814,49 @@ void cloth_free_modifier (ClothModifierData *clmd) return; cloth = clmd->clothObject; - - // free our frame cache - clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_ALL; - cloth_cache_free(clmd, 0); - - if (cloth) - { - // If our solver provides a free function, call it - if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free) - { - solvers [cloth->old_solver_type].free (clmd); - } - - // Free the verts. - if (cloth->verts != NULL) - MEM_freeN (cloth->verts); - - cloth->verts = NULL; - cloth->numverts = -1; - - // Free the springs. - if (cloth->springs != NULL) - MEM_freeN (cloth->springs); - - cloth->springs = NULL; - cloth->numsprings = -1; - - // free BVH collision tree - if(cloth->tree) - bvh_free((BVH *)cloth->tree); - - // we save our faces for collision objects - if(cloth->mfaces) - MEM_freeN(cloth->mfaces); - if(clmd->clothObject->facemarks) - MEM_freeN(clmd->clothObject->facemarks); + if(!(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_PROTECT)) + { + // free our frame cache + clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_ALL; + cloth_cache_free(clmd, 0); + + if (cloth) + { + // If our solver provides a free function, call it + if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free) + { + solvers [cloth->old_solver_type].free (clmd); + } + + // Free the verts. + if (cloth->verts != NULL) + MEM_freeN (cloth->verts); + + cloth->verts = NULL; + cloth->numverts = -1; + + // Free the springs. + if (cloth->springs != NULL) + MEM_freeN (cloth->springs); + + cloth->springs = NULL; + cloth->numsprings = -1; + + // free BVH collision tree + if(cloth->tree) + bvh_free((BVH *)cloth->tree); + + // we save our faces for collision objects + if(cloth->mfaces) + MEM_freeN(cloth->mfaces); - MEM_freeN (cloth); - clmd->clothObject = NULL; + if(clmd->clothObject->facemarks) + MEM_freeN(clmd->clothObject->facemarks); + + MEM_freeN (cloth); + clmd->clothObject = NULL; + } } } @@ -952,6 +957,7 @@ static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh unsigned int i; MVert *mvert = NULL; ClothVertex *verts = NULL; + float tnull[3] = {0,0,0}; /* If we have a clothObject, free it. */ if (clmd->clothObject != NULL) @@ -993,7 +999,9 @@ static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh VECCOPY(verts->xold, verts->x); VECCOPY(verts->txold, verts->x); VECCOPY(verts->tx, verts->x); - VecMulf(verts->v, 0.0f); + VecMulf(verts->v, 0.0f); + verts->impulse_count = 0; + VECCOPY(verts->impulse, tnull); } clmd->clothObject->tree = bvh_build(clmd,clmd->coll_parms.epsilon); @@ -1159,6 +1167,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d // dm->getNumVerts(dm); MVert *mvert = NULL; // CDDM_get_verts(dm); ClothVertex *verts = NULL; + float tnull[3] = {0,0,0}; /* If we have a clothObject, free it. */ if (clmd->clothObject != NULL) @@ -1220,6 +1229,9 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d VECCOPY(verts->xconst, verts->x); VECCOPY(verts->txold, verts->x); VecMulf(verts->v, 0.0f); + + verts->impulse_count = 0; + VECCOPY(verts->impulse, tnull); } /* apply / set vertex groups */ @@ -1363,17 +1375,20 @@ int cloth_build_springs(Cloth *cloth, DerivedMesh *dm) shear_springs++; temp_index++; - - springs[temp_index].ij = mface[i].v2; - springs[temp_index].kl = mface[i].v4; - VECSUB(temp, mvert[springs[temp_index].kl].co, mvert[springs[temp_index].ij].co); - springs[temp_index].restlen = sqrt(INPR(temp, temp)); - springs[temp_index].type = SHEAR; - - BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index])); - BLI_linklist_append(&edgelist[springs[temp_index].kl], &(springs[temp_index])); - - shear_springs++; + + if(mface[i].v4) + { + springs[temp_index].ij = mface[i].v2; + springs[temp_index].kl = mface[i].v4; + VECSUB(temp, mvert[springs[temp_index].kl].co, mvert[springs[temp_index].ij].co); + springs[temp_index].restlen = sqrt(INPR(temp, temp)); + springs[temp_index].type = SHEAR; + + BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index])); + BLI_linklist_append(&edgelist[springs[temp_index].kl], &(springs[temp_index])); + + shear_springs++; + } } // bending springs diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 32a2f820894..8c6a17c4e42 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -186,15 +186,15 @@ void generateTriangleMarks() */ } - +// w3 is not perfect void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], double *w1, double *w2, double *w3) { - float tempV1[3], tempV2[3], tempV4[3]; - double a,b,c,e,f; + double tempV1[3], tempV2[3], tempV4[3]; + double a,b,c,d,e,f; - VECSUB (tempV1, p1, p3); /* x1 - x3 */ - VECSUB (tempV2, p2, p3); /* x2 - x3 */ - VECSUB (tempV4, pv, p3); /* pv - x3 */ + VECSUB (tempV1, p1, p3); + VECSUB (tempV2, p2, p3); + VECSUB (tempV4, pv, p3); a = INPR (tempV1, tempV1); b = INPR (tempV1, tempV2); @@ -202,10 +202,24 @@ void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3] e = INPR (tempV1, tempV4); f = INPR (tempV2, tempV4); + d = (a * c - b * b); + + if (ABS(d) < ALMOST_ZERO) { + *w1 = *w2 = *w3 = 1.0f / 3.0f; + return; + } + + w1[0] = (e * c - b * f) / d; + + if(w1[0] < 0) + w1[0] = 0.0; - w1[0] = (e * c - b * f) / (a * c - b * b); w2[0] = (f - b * w1[0]) / c; - w3[0] = 1.0 - w1[0] - w2[0]; + + if(w2[0] < 0) + w2[0] = 0.0; + + w3[0] = 1.0f - w1[0] - w2[0]; } DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3) @@ -230,36 +244,22 @@ DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, LinkNode **collision_list) { - unsigned int i = 0, numverts=0; + unsigned int i = 0, numfaces = 0; int result = 0; LinkNode *search = NULL; CollPair *collpair = NULL; Cloth *cloth1, *cloth2; MFace *face1, *face2; - double w1, w2, w3, u1, u2, u3; + double w1, w2, w3, u1, u2, u3, a1, a2, a3; float v1[3], v2[3], relativeVelocity[3]; float magrelVel; cloth1 = clmd->clothObject; cloth2 = coll_clmd->clothObject; - numverts = clmd->clothObject->numverts; - - /* - for(i = 0; i < LIST_LENGTH; i++) - { - // calc SIP-code - // TODO for later: calculateSipCode() - - // calc distance (?) + numfaces = clmd->clothObject->numfaces; - // calc impulse - - // apply impulse - } - */ - - for(i = 0; i < numverts; i++) + for(i = 0; i < numfaces; i++) { search = collision_list[i]; @@ -273,11 +273,13 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link // compute barycentric coordinates for both collision points if(!collpair->quadA) + { bvh_compute_barycentric(collpair->p1, cloth1->verts[face1->v1].txold, cloth1->verts[face1->v2].txold, cloth1->verts[face1->v3].txold, &w1, &w2, &w3); + } else bvh_compute_barycentric(collpair->p1, cloth1->verts[face1->v4].txold, @@ -317,25 +319,26 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link // Calculate masses of points. - // printf("relativeVelocity -> x: %f, y: %f, z: %f\n", relativeVelocity[0], relativeVelocity[1],relativeVelocity[2]); - // If v_n_mag > 0 the edges are approaching each other. - if(magrelVel > ALMOST_ZERO) + + if(magrelVel < -ALMOST_ZERO) { // Calculate Impulse magnitude to stop all motion in normal direction. // const double I_mag = v_n_mag / (1/m1 + 1/m2); float magnitude_i = magrelVel / 2.0f; // TODO implement masses float tangential[3], magtangent, magnormal, collvel[3]; float vrel_t_pre[3]; - float vrel_t[3], impulse; + float vrel_t[3]; + double impulse; float epsilon = clmd->coll_parms.epsilon; + float overlap = (epsilon + ALMOST_ZERO-collpair->distance); // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); // magtangent = INPR(tangential, tangential); // Apply friction impulse. - if (magtangent > ALMOST_ZERO) + if (magtangent < ALMOST_ZERO) { // printf("friction applied: %f\n", magtangent); @@ -347,57 +350,64 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential); */ } + + impulse = -magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse); + cloth1->verts[face1->v1].impulse_count++; + + VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse); + cloth1->verts[face1->v2].impulse_count++; + + VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse); + cloth1->verts[face1->v3].impulse_count++; + + if(face1->v4) + { + VECADDMUL(cloth1->verts[face1->v4].impulse, collpair->normal, impulse); + cloth1->verts[face1->v4].impulse_count++; + } + + + if (overlap > ALMOST_ZERO) { + double I_mag = overlap * 0.1; + + impulse = I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse); + cloth1->verts[face1->v1].impulse_count++; + + VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse); + cloth1->verts[face1->v2].impulse_count++; + + VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse); + cloth1->verts[face1->v3].impulse_count++; + + if(face1->v4) + { + VECADDMUL(cloth1->verts[face1->v4].impulse, collpair->normal, impulse); + cloth1->verts[face1->v4].impulse_count++; + } + + } + + result = 1; + // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case // Apply the impulse and increase impulse counters. - // my try, works better than the papers ones (maybe i did just something wrong) - VECSUB(collvel, cloth1->verts[face1->v1].tv, v2); - magnormal = INPR(collvel, collpair->normal); - if(magnormaldistance) / 4.0f; - VECADDMUL(cloth1->verts[face1->v1].tv, collpair->normal, -magnormal + impulse); - + + /* // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent); - -/* VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); // VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); magtangent = Normalize(vrel_t_pre); VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent)); VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre); -*/ - - VECSUB(collvel, cloth1->verts[face1->v2].tv, v2); - magnormal = INPR(collvel, collpair->normal); - if(magnormaldistance) / 4.0f; - VECADDMUL(cloth1->verts[face1->v2].tv, collpair->normal, -magnormal+ impulse); + */ - VECSUB(collvel, cloth1->verts[face1->v3].tv, v2); - magnormal = INPR(collvel, collpair->normal); - if(magnormaldistance) / 4.0f; - VECADDMUL(cloth1->verts[face1->v3].tv, collpair->normal, -magnormal+ impulse); - - - VECSUB(collvel, cloth1->verts[face1->v4].tv, v2); - magnormal = INPR(collvel, collpair->normal); - if(magnormaldistance) / 4.0f; - VECADDMUL(cloth1->verts[face1->v4].tv, collpair->normal, -magnormal+ impulse); - - result = 1; } @@ -444,65 +454,86 @@ double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData { if(i == 0) { - indexA = face1->v4; - indexB = face1->v1; - indexC = face1->v3; - - indexD = face2->v1; - indexE = face2->v2; - indexF = face2->v3; - } - else if(i == 1) - { - indexA = face1->v4; - indexB = face1->v1; - indexC = face1->v3; - - indexD = face2->v4; - indexE = face2->v1; - indexF = face2->v3; - } - else if(i == 2) - { - indexA = face1->v1; - indexB = face1->v2; - indexC = face1->v3; - - indexD = face2->v4; - indexE = face2->v1; - indexF = face2->v3; - } - - // face a2 + face b1 - VECCOPY(a[0], cloth1->verts[indexA].txold); - VECCOPY(a[1], cloth1->verts[indexB].txold); - VECCOPY(a[2], cloth1->verts[indexC].txold); - - - VECCOPY(b[0], cloth2->verts[indexD].txold); - VECCOPY(b[1], cloth2->verts[indexE].txold); - VECCOPY(b[2], cloth2->verts[indexF].txold); - - tempdistance = plNearestPoints(a,b,tpa,tpb,tnormal); - - if(tempdistance < distance) - { - VECCOPY(pa, tpa); - VECCOPY(pb, tpb); - VECCOPY(normal, tnormal); - distance = tempdistance; - - if(i == 0) + if(face1->v4) { - quadA = 1; quadB = 0; + indexA = face1->v4; + indexB = face1->v1; + indexC = face1->v3; + + indexD = face2->v1; + indexE = face2->v2; + indexF = face2->v3; } - else if(i == 1) + else + i+=2; + } + + if(i == 1) + { + if((face1->v4)&&(face2->v4)) { - quadA = quadB = 1; + indexA = face1->v4; + indexB = face1->v1; + indexC = face1->v3; + + indexD = face2->v4; + indexE = face2->v1; + indexF = face2->v3; } - else if(i == 2) + else + i++; + } + + if(i == 2) + { + if(face2->v4) { - quadA = 0; quadB = 1; + indexA = face1->v1; + indexB = face1->v2; + indexC = face1->v3; + + indexD = face2->v4; + indexE = face2->v1; + indexF = face2->v3; + } + else + i++; + + } + + if(i<3) + { + // face a2 + face b1 + VECCOPY(a[0], cloth1->verts[indexA].txold); + VECCOPY(a[1], cloth1->verts[indexB].txold); + VECCOPY(a[2], cloth1->verts[indexC].txold); + + + VECCOPY(b[0], cloth2->verts[indexD].txold); + VECCOPY(b[1], cloth2->verts[indexE].txold); + VECCOPY(b[2], cloth2->verts[indexF].txold); + + tempdistance = plNearestPoints(a,b,tpa,tpb,tnormal); + + if(tempdistance < distance) + { + VECCOPY(pa, tpa); + VECCOPY(pb, tpb); + VECCOPY(normal, tnormal); + distance = tempdistance; + + if(i == 0) + { + quadA = 1; quadB = 0; + } + else if(i == 1) + { + quadA = quadB = 1; + } + else if(i == 2) + { + quadA = 0; quadB = 1; + } } } } @@ -524,20 +555,18 @@ void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clm // calc distance + normal distance = implicit_tri_check_coherence(clmd, coll_clmd, tree1->tri_index, tree2->tri_index, collpair->p1, collpair->p2, collpair->vector, collpair->quadA, collpair->quadB); - if (ABS(distance) <= (epsilon + ALMOST_ZERO)) + if ((distance <= (epsilon + ALMOST_ZERO)) && (distance > -1.0f)) // max overlap = 1.0 { - // printf("distance: %f, epsilon: %f\n", (float)distance, epsilon + ALMOST_ZERO); - + // printf("dist: %f\n", (float)distance); + collpair->face1 = tree1->tri_index; collpair->face2 = tree2->tri_index; VECCOPY(collpair->normal, collpair->vector); Normalize(collpair->normal); - // printf("normal x: %f, y: %f, z: %f\n", collpair->normal[0], collpair->normal[1], collpair->normal[2]); - collpair->distance = distance; - BLI_linklist_append(&linknode[tree1->tri_index], collpair); + BLI_linklist_append(&linknode[tree1->tri_index], collpair); } else { @@ -545,32 +574,14 @@ void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clm } } - -int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RESPONSE collision_response, float dt) +// move collision objects forward in time and update static bounding boxes +void cloth_update_collision_objects(float step) { Base *base=NULL; ClothModifierData *coll_clmd=NULL; - Cloth *cloth=NULL; Object *coll_ob=NULL; - BVH *cloth_bvh=NULL; - unsigned int i=0, numverts=0; - int result = 0; - - if ((clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) - { - return 0; - } - cloth = clmd->clothObject; - cloth_bvh = (BVH *) cloth->tree; - numverts = clmd->clothObject->numverts; + unsigned int i=0; - //////////////////////////////////////////////////////////// - // static collisions - //////////////////////////////////////////////////////////// - - // update cloth bvh - bvh_update_static(clmd, cloth_bvh); - // search all objects for collision object for (base = G.scene->base.first; base; base = base->next) { @@ -584,73 +595,150 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) { if (coll_clmd->clothObject && coll_clmd->clothObject->tree) - { - unsigned int coll_numverts = coll_clmd->clothObject->numverts; + { Cloth *coll_cloth = coll_clmd->clothObject; - - LinkNode **collision_list = MEM_callocN (sizeof(LinkNode *)*numverts, "collision_list"); BVH *coll_bvh = coll_clmd->clothObject->tree; + unsigned int coll_numverts = coll_cloth->numverts; - if(collision_list) - { - // memset(collision_list, 0, sizeof(LinkNode *)*numverts); + // update position of collision object + for(i = 0; i < coll_numverts; i++) + { + VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx); + + VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step); - for(i = 0; i < numverts; i++) - { - collision_list[i] = NULL; - } - - clmd->coll_parms.temp = collision_list; - - // update position of collision object - for(i = 0; i < coll_numverts; i++) - { - VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx); - - VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step); - - VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold); - } - - // update BVH of collision object - bvh_update_static(coll_clmd, coll_bvh); - - bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response); - - result += collision_static(clmd, coll_clmd, collision_list); - - // calculate velocities - - // free temporary list - for(i = 0; i < numverts; i++) - { - LinkNode *search = collision_list[i]; - while(search) - { - LinkNode *next= search->next; - CollPair *collpair = search->link; - - if(collpair) - MEM_freeN(collpair); - - search = next; - } - - BLI_linklist_free(collision_list[i],NULL); - } - if(collision_list) - MEM_freeN(collision_list); - - clmd->coll_parms.temp = NULL; + // no dt here because of float rounding errors + VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold); } - - + + // update BVH of collision object + bvh_update_static(coll_clmd, coll_bvh); } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); } } +} +#define CLOTH_MAX_THRESHOLD 5 + +// cloth - object collisions +int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RESPONSE collision_response, float dt) +{ + Base *base=NULL; + ClothModifierData *coll_clmd=NULL; + Cloth *cloth=NULL; + Object *coll_ob=NULL; + BVH *cloth_bvh=NULL; + unsigned int i=0, numfaces = 0, numverts = 0; + unsigned int result = 0, ic = 0, rounds = 0; + ClothVertex *verts = NULL; + float tnull[3] = {0,0,0}; + + if ((clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) + { + return 0; + } + cloth = clmd->clothObject; + verts = cloth->verts; + cloth_bvh = (BVH *) cloth->tree; + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + + //////////////////////////////////////////////////////////// + // static collisions + //////////////////////////////////////////////////////////// + + // update cloth bvh + bvh_update_static(clmd, cloth_bvh); + + // update collision objects + cloth_update_collision_objects(step); + + do + { + result = 0; + ic = 0; + + // handle all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + LinkNode **collision_list = MEM_callocN (sizeof(LinkNode *)*(numfaces), "collision_list"); + BVH *coll_bvh = coll_clmd->clothObject->tree; + + if(collision_list) + { + memset(collision_list, 0, sizeof(LinkNode *)*numfaces); + clmd->coll_parms.temp = collision_list; + + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response); + + result += collision_static(clmd, coll_clmd, collision_list); + + // calculate velocities + + // free temporary list + for(i = 0; i < numfaces; i++) + { + LinkNode *search = collision_list[i]; + while(search) + { + LinkNode *next= search->next; + CollPair *collpair = search->link; + + if(collpair) + MEM_freeN(collpair); + + search = next; + } + + BLI_linklist_free(collision_list[i],NULL); + } + if(collision_list) + MEM_freeN(collision_list); + + clmd->coll_parms.temp = NULL; + } + + + } + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + // now apply impulses parallel + + for(i = 0; i < numverts; i++) + { + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + } + } + + printf("ic: %d\n", ic); + rounds++; + } + while(result && (CLOTH_MAX_THRESHOLD>rounds)); + + printf("\n"); + //////////////////////////////////////////////////////////// // update positions + velocities //////////////////////////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index c54897cc89c..0d0c7ff0f7b 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1484,7 +1484,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase VECCOPY(verts[i].tx, id->Xnew[i]); VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); - VECSUB(verts[i].v, verts[i].tx, verts[i].txold); + VECCOPY(verts[i].v, verts[i].tv); } // call collision function diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 546247f8e35..5ba3df9a720 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4941,9 +4941,12 @@ static int clothModifier_dependsOnTime(ModifierData *md) static void clothModifier_freeData(ModifierData *md) { ClothModifierData *clmd = (ClothModifierData*) md; - + if (clmd) - cloth_free_modifier (clmd); + { + clmd->sim_parms.flags &= ~CSIMSETT_FLAG_CCACHE_PROTECT; + cloth_free_modifier (clmd); + } } /* Boolean */ diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index c0a47452e3e..574537f2589 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -41,16 +41,18 @@ * is reached. */ typedef struct ClothVertex { - int flags; /* General flags per vertex. */ - float v [3]; /* The velocity of the point. */ - float xconst [3]; /* constrained position */ - float x [3]; /* The current position of this vertice. */ - float xold [3]; /* The previous position of this vertice. */ - float tx [3]; - float txold [3]; - float tv[3]; - float mass; /* mass / weight of the vertex */ - float goal; /* goal, from SB */ + int flags; /* General flags per vertex. */ + float v [3]; /* The velocity of the point. */ + float xconst [3]; /* constrained position */ + float x [3]; /* The current position of this vertex. */ + float xold [3]; /* The previous position of this vertex.*/ + float tx [3]; /* temporary position */ + float txold [3]; /* temporary old position */ + float tv[3]; /* temporary "velocity", mostly used as tv = tx-txold */ + float mass; /* mass / weight of the vertex */ + float goal; /* goal, from SB */ + float impulse[3]; /* used in collision.c */ + unsigned int impulse_count; /* same as above */ } ClothVertex; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 1e3439d41b5..a10ffa09442 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3118,8 +3118,8 @@ static void object_panel_cloth(Object *ob) /* GENERAL STUFF */ uiClearButLock(); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 5000.0, 100, 0, "Overall stiffness of structure"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 1000.0, 1000, 0, "Wrinkle possibility"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility"); uiDefButI(block, NUM, B_CLOTH_RENEW, "Steps per Frame:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); uiBlockEndAlign(block); uiBlockBeginAlign(block); @@ -3249,12 +3249,13 @@ static void object_panel_cloth_II(Object *ob) uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 10, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache without preroll"); uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache"); if(length>1) // B_CLOTH_CHANGEPREROLL - uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); + uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); } else { uiDefBut(block, LABEL, 0, "No frames cached.", 10,120,290,20, NULL, 0.0, 0, 0, 0, ""); } + uiDefButBitI(block, TOG, CSIMSETT_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,50,145,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); uiBlockEndAlign(block); } } From b4fb141ea571ee9c9edefa277eb6f034d54d26d2 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 23 Sep 2007 17:40:44 +0000 Subject: [PATCH 018/101] In the middle of switching to own collision detection, WIP commit (don't expect anything to work, but compile) --- source/blender/blenkernel/BKE_cloth.h | 4 +- source/blender/blenkernel/intern/cloth.c | 2 +- source/blender/blenkernel/intern/collision.c | 351 +++++++++++++++++-- 3 files changed, 323 insertions(+), 34 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index e4d1fb0ca99..ec58382b86a 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -60,7 +60,7 @@ struct DerivedMesh; /* This is approximately the smallest number that can be * represented by a float, given its precision. */ -#define ALMOST_ZERO 0.00001 +#define ALMOST_ZERO 0.000001 /* Bits to or into the ClothVertex.flags. */ #define CVERT_FLAG_PINNED 1 @@ -240,7 +240,7 @@ typedef struct CollPair float p1[3], p2[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 - int quadA, quadB; // indicates the used triangle of the quad: 0 means verts 1,2,3; 1 means verts 4,1,3 + unsigned int Aindex1, Aindex2, Aindex3, Aindex4, Bindex1, Bindex2, Bindex3, Bindex4; } CollPair; diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 7059c59c65b..d9f0bef9f43 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -153,7 +153,7 @@ void cloth_init (ClothModifierData *clmd) clmd->sim_parms.mass = 1.0f; clmd->sim_parms.stepsPerFrame = 5; clmd->sim_parms.sim_time = 1.0; - clmd->sim_parms.flags = CSIMSETT_FLAG_RESET | CSIMSETT_FLAG_CCACHE_PROTECT; + clmd->sim_parms.flags = CSIMSETT_FLAG_RESET; clmd->sim_parms.solver_type = 0; clmd->sim_parms.preroll = 0; clmd->sim_parms.maxspringlen = 10; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 8c6a17c4e42..7eec315e386 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -211,14 +211,8 @@ void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3] w1[0] = (e * c - b * f) / d; - if(w1[0] < 0) - w1[0] = 0.0; - w2[0] = (f - b * w1[0]) / c; - if(w2[0] < 0) - w2[0] = 0.0; - w3[0] = 1.0f - w1[0] - w2[0]; } @@ -241,7 +235,7 @@ DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal VecMulf(to, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); } - +/* int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, LinkNode **collision_list) { unsigned int i = 0, numfaces = 0; @@ -343,12 +337,12 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link // printf("friction applied: %f\n", magtangent); // TODO check original code - /* + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,tangential); VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv,tangential); VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv,tangential); VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential); - */ + } impulse = -magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); @@ -397,7 +391,7 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link // Apply the impulse and increase impulse counters. - /* + / // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent); VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); // VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); @@ -405,7 +399,7 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent)); VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre); - */ + @@ -417,7 +411,8 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Link return result; } - +*/ + // return distance between two triangles using bullet engine double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData *coll_clmd, unsigned int tri_index1, unsigned int tri_index2, float pa[3], float pb[3], float normal[3], int quadA, int quadB) { @@ -540,37 +535,331 @@ double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData return distance; } +// calculate plane normal +void calcPlaneNormal(float normal[3], float p11[3], float p12[3], float p13[3]) +{ + float temp1[3], temp2[3]; + float tnormal[3]; + + VECSUB(temp1, p12,p11); + VECSUB(temp2, p13,p11); + Crossf(normal, temp1, temp2); + Normalize(normal); + // VECCOPY(normal, tnormal); +} + +float distance_triangle_point( float p11[3], float p12[3], float p13[3], float p21[3], float normal[3]) +{ + float temp[3]; + float magnitude = 0; + + VECSUB(temp, p21, p13); + magnitude = INPR(temp, normal); + + if(magnitude < 0) + { + magnitude *= -1.0f; + // VecMulf(normal, -1.0f); + } + + return magnitude; +} + +float nearest_point_triangle_triangle(float p11[3], float p12[3], float p13[3], float p21[3], float p22[3], float p23[3], float normal[3]) +{ + float distance = 0, tdistance = 0, tnormal[3]; + + // first triangle 1-2-3 versus second triangle 1-2-3 + calcPlaneNormal(normal, p11, p12, p13); + distance = distance_triangle_point(p11, p12, p13, p21, normal); + + tdistance = distance_triangle_point(p11, p12, p13, p22, normal); + + if(tdistance < distance) + { + distance = tdistance; + } + + tdistance = distance_triangle_point(p11, p12, p13, p23, normal); + + if(tdistance < distance) + { + distance = tdistance; + } + + // second triangle 1-2-3 versus first triangle 1-2-3 + calcPlaneNormal(tnormal, p21, p22, p23); + + tdistance = distance_triangle_point(p21, p22, p23, p11, tnormal); + + if(tdistance < distance) + { + distance = tdistance; + VECCOPY(normal, tnormal); + } + + tdistance = distance_triangle_point(p21, p22, p23, p12, tnormal); + + if(tdistance < distance) + { + distance = tdistance; + VECCOPY(normal, tnormal); + } + + tdistance = distance_triangle_point(p21, p22, p23, p13, tnormal); + + if(tdistance < distance) + { + distance = tdistance; + VECCOPY(normal, tnormal); + } + + + if (distance < 0) { + VecMulf(normal, -1.0f); + distance = -distance; + } + + return distance; +} + + +int collision_static2(ClothModifierData *clmd, ClothModifierData *coll_clmd, LinkNode **collision_list) +{ + unsigned int i = 0, numfaces = 0; + int result = 0; + LinkNode *search = NULL; + CollPair *collpair = NULL; + Cloth *cloth1, *cloth2; + MFace *face1, *face2; + double w1, w2, w3, u1, u2, u3, a1, a2, a3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + numfaces = clmd->clothObject->numfaces; + + for(i = 0; i < numfaces; i++) + { + search = collision_list[i]; + + while(search) + { + collpair = search->link; + + face1 = &(cloth1->mfaces[collpair->face1]); + face2 = &(cloth2->mfaces[collpair->face2]); + + // compute barycentric coordinates for both collision points + + + bvh_compute_barycentric(collpair->p1, + cloth1->verts[collpair->Aindex1].txold, + cloth1->verts[collpair->Aindex2].txold, + cloth1->verts[collpair->Aindex3].txold, + &w1, &w2, &w3); + + bvh_compute_barycentric(collpair->p2, + cloth2->verts[collpair->Bindex1].txold, + cloth2->verts[collpair->Bindex1].txold, + cloth2->verts[collpair->Bindex3].txold, + &u1, &u2, &u3); + + // Calculate relative "velocity". + interpolateOnTriangle(v1, cloth1->verts[collpair->Aindex1].tv, cloth1->verts[collpair->Aindex2].tv, cloth1->verts[collpair->Aindex3].tv, w1, w2, w3); + + interpolateOnTriangle(v2, cloth2->verts[collpair->Bindex1].tv, cloth2->verts[collpair->Bindex2].tv, cloth2->verts[collpair->Bindex3].tv, u1, u2, u3); + + VECSUB(relativeVelocity, v1, v2); + + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). + magrelVel = INPR(relativeVelocity, collpair->normal); + + // Calculate masses of points. + + // If v_n_mag > 0 the edges are approaching each other. + + if(magrelVel < -ALMOST_ZERO) + { + // Calculate Impulse magnitude to stop all motion in normal direction. + // const double I_mag = v_n_mag / (1/m1 + 1/m2); + float magnitude_i = magrelVel / 2.0f; // TODO implement masses + float tangential[3], magtangent, magnormal, collvel[3]; + float vrel_t_pre[3]; + float vrel_t[3]; + double impulse; + float epsilon = clmd->coll_parms.epsilon; + float overlap = (epsilon + ALMOST_ZERO-collpair->distance); + + /* + impulse = -magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse); + cloth1->verts[face1->v1].impulse_count++; + + VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse); + cloth1->verts[face1->v2].impulse_count++; + + VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse); + cloth1->verts[face1->v3].impulse_count++; + */ + + + /* + if (overlap > ALMOST_ZERO) { + double I_mag = overlap * 0.1; + + impulse = I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse); + cloth1->verts[face1->v1].impulse_count++; + + VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse); + cloth1->verts[face1->v2].impulse_count++; + + VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse); + cloth1->verts[face1->v3].impulse_count++; + + if(face1->v4) + { + VECADDMUL(cloth1->verts[face1->v4].impulse, collpair->normal, impulse); + cloth1->verts[face1->v4].impulse_count++; + } + + } + */ + + result = 1; + } + + search = search->next; + } + } + + return result; +} + void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2) { CollPair *collpair = NULL; LinkNode **linknode; double distance = 0; - float epsilon = clmd->coll_parms.epsilon; - - collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); + float epsilon = clmd->coll_parms.epsilon, tdistance=0; + MFace *face1, *face2; + ClothVertex *verts1, *verts2; + Cloth *cloth1=NULL, *cloth2=NULL; + int i = 0; + linknode = clmd->coll_parms.temp; + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + // calc SIPcode (?) - // calc distance + normal - distance = implicit_tri_check_coherence(clmd, coll_clmd, tree1->tri_index, tree2->tri_index, collpair->p1, collpair->p2, collpair->vector, collpair->quadA, collpair->quadB); - - if ((distance <= (epsilon + ALMOST_ZERO)) && (distance > -1.0f)) // max overlap = 1.0 + for(i = 0; i < 4; i++) { - // printf("dist: %f\n", (float)distance); + collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); - collpair->face1 = tree1->tri_index; - collpair->face2 = tree2->tri_index; + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + verts1 = cloth1->verts; + verts2 = cloth2->verts; - VECCOPY(collpair->normal, collpair->vector); - Normalize(collpair->normal); + if(i == 0) + { + collpair->Aindex1 = face1->v1; + collpair->Aindex2 = face1->v2; + collpair->Aindex3 = face1->v3; + collpair->Aindex4 = face1->v4; + + collpair->Bindex1 = face2->v1; + collpair->Bindex2 = face2->v2; + collpair->Bindex3 = face2->v3; + collpair->Bindex4 = face2->v4; + + } - collpair->distance = distance; - BLI_linklist_append(&linknode[tree1->tri_index], collpair); - } - else - { - MEM_freeN(collpair); + if(i == 1) + { + if(face2->v4) + { + collpair->Aindex1 = face1->v1; + collpair->Aindex2 = face1->v2; + collpair->Aindex3 = face1->v3; + collpair->Aindex4 = face1->v4; + + collpair->Bindex1 = face2->v4; + collpair->Bindex2 = face2->v3; + collpair->Bindex3 = face2->v1; + collpair->Bindex4 = face2->v1; + } + else + i++; + + } + + if(i == 2) + { + if(face1->v4) + { + collpair->Aindex1 = face1->v4; + collpair->Aindex2 = face1->v3; + collpair->Aindex3 = face1->v1; + collpair->Aindex4 = face1->v2; + + collpair->Bindex1 = face2->v1; + collpair->Bindex2 = face2->v2; + collpair->Bindex3 = face2->v3; + collpair->Bindex4 = face2->v4; + } + else + i++; + } + + if(i == 3) + { + if((face2->v4) && (face1->v4)) + { + collpair->Aindex1 = face1->v4; + collpair->Aindex2 = face1->v3; + collpair->Aindex3 = face1->v1; + collpair->Aindex4 = face1->v2; + + collpair->Bindex1 = face2->v4; + collpair->Bindex2 = face2->v3; + collpair->Bindex3 = face2->v1; + collpair->Bindex4 = face2->v2; + } + else + i++; + } + + if(i < 4) + { + distance = nearest_point_triangle_triangle(verts1[collpair->Aindex1].txold, verts1[collpair->Aindex2].txold, verts1[collpair->Aindex3].txold, verts2[collpair->Bindex1].txold, verts2[collpair->Bindex2].txold, verts2[collpair->Bindex3].txold, collpair->normal); + + // calc distance + normal + // distance = implicit_tri_check_coherence(clmd, coll_clmd, tree1->tri_index, tree2->tri_index, collpair->p1, collpair->p2, collpair->vector, collpair->quadA, collpair->quadB); + + if (distance <= (epsilon + ALMOST_ZERO)) // max overlap = 1.0 + { + + printf("dist: %f, tdist: %f\n", (float)distance, tdistance); + + collpair->face1 = tree1->tri_index; + collpair->face2 = tree2->tri_index; + + collpair->distance = distance; + BLI_linklist_append(&linknode[tree1->tri_index], collpair); + } + else + { + MEM_freeN(collpair); + } + } } } @@ -684,7 +973,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response); - result += collision_static(clmd, coll_clmd, collision_list); + result += collision_static2(clmd, coll_clmd, collision_list); // calculate velocities From 6a72fecca73d9f45e04ee942dc85310e12b137cb Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 28 Sep 2007 11:06:13 +0000 Subject: [PATCH 019/101] Some additional wind problems (hopefully) fixed, added force fields, reported by Rui Paulo Sanguinheira Diogo --- source/blender/blenkernel/intern/implicit.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 0d0c7ff0f7b..3994bbf2b40 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1261,7 +1261,7 @@ void calculateWeightedVertexNormal(ClothModifierData *clmd, MFace *mfaces, float } } } -float calculateVertexWindForce(int index, float wind[3], float vertexnormal[3]) +float calculateVertexWindForce(float wind[3], float vertexnormal[3]) { return fabs(INPR(wind, vertexnormal) * 0.5f); } @@ -1328,21 +1328,25 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec /* handle external forces like wind */ if(effectors) { - float wind[3] = {0.0f,1.0f,0.0f}; + float speed[3] = {0.0f, 0.0f,0.0f}; float force[3]= {0.0f, 0.0f, 0.0f}; #pragma omp parallel for private (i) shared(lF) for(i = 0; i < cloth->numverts; i++) { float vertexnormal[3]={0,0,0}; + float fieldfactor = 1000.0f, windfactor = 250.0f; // from sb + + pdDoEffectors(effectors, lX[i], force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); + + // TODO apply forcefields here + VECADDS(lF[i], lF[i], force, fieldfactor*0.01f); - pdDoEffectors(effectors, lX[i], force, wind, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); - - VECCOPY(wind_normalized, wind); + VECCOPY(wind_normalized, speed); Normalize(wind_normalized); - + calculateWeightedVertexNormal(clmd, mfaces, vertexnormal, i, lX); - VECADDS(lF[i], lF[i], wind_normalized, calculateVertexWindForce(i, wind, vertexnormal)); + VECADDS(lF[i], lF[i], wind_normalized, -calculateVertexWindForce(speed, vertexnormal)); } } From 777c16d444d0227a9e59c7beb2ab2be3374fdef2 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 1 Oct 2007 20:19:22 +0000 Subject: [PATCH 020/101] Bullet is back, but now generalized enough to allow own distance/calculation. Some bullet makefile-fix by 'gsr b3d'- please test it. Also fixed some crasher with cache. Also implemented moving-collisions enabled kdop (response missing in the moment) --- extern/bullet2/src/Bullet-C-Api.h | 2 +- .../BulletDynamics/Dynamics/Bullet-C-Api.cpp | 12 +- source/Makefile | 4 +- source/blender/blenkernel/BKE_cloth.h | 105 +- source/blender/blenkernel/intern/Makefile | 3 + source/blender/blenkernel/intern/cloth.c | 20 +- source/blender/blenkernel/intern/collision.c | 1265 ++++++++--------- source/blender/blenkernel/intern/implicit.c | 7 +- source/blender/blenkernel/intern/kdop.c | 98 +- source/blender/makesdna/DNA_cloth_types.h | 2 +- 10 files changed, 712 insertions(+), 806 deletions(-) diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h index 2d35383e902..ccb0c452f3e 100644 --- a/extern/bullet2/src/Bullet-C-Api.h +++ b/extern/bullet2/src/Bullet-C-Api.h @@ -5,7 +5,7 @@ extern "C" { #endif // __cplusplus -double plNearestPoints(float p[3][3], float q[3][3], float *pa, float *pb, float normal[3]); +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 } diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp index 1b843774609..4051d3f3e1f 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp @@ -25,13 +25,13 @@ extern "C" -double plNearestPoints(float p[3][3], float q[3][3], float *pa, float *pb, float normal[3]) +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(p[0][0], p[0][1], p[0][2]), btVector3(p[1][0], p[1][1], p[1][2]), btVector3(p[2][0], p[2][1], p[2][2])); - trishapeA.setMargin(0.001f); + 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(q[0][0], q[0][1], q[0][2]), btVector3(q[1][0], q[1][1], q[1][2]), btVector3(q[2][0], q[2][1], q[2][2])); - trishapeB.setMargin(0.001f); + 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; @@ -44,7 +44,7 @@ double plNearestPoints(float p[3][3], float q[3][3], float *pa, float *pb, float btConvexPenetrationDepthSolver* Solver = NULL; - Solver = &Solver0; + Solver = &Solver1; btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,Solver); diff --git a/source/Makefile b/source/Makefile index 5161f6b73c5..e68aca215a1 100644 --- a/source/Makefile +++ b/source/Makefile @@ -149,9 +149,11 @@ ifneq ($(NAN_NO_KETSJI),true) COMLIB += $(OCGDIR)/gameengine/ketsji/KXNetwork/$(DEBUG_DIR)libKXNetwork.a COMLIB += $(OCGDIR)/gameengine/Network/$(DEBUG_DIR)libNetwork.a COMLIB += $(OCGDIR)/gameengine/Network/LoopBackNetwork/$(DEBUG_DIR)libLoopBackNetwork.a - COMLIB += $(NAN_BULLET2)/lib/libbullet2.a endif +# Required by cloth, not gameengine only anymore +COMLIB += $(NAN_BULLET2)/lib/$(DEBUG_DIR)libbullet2.a + COMLIB += $(NAN_GUARDEDALLOC)/lib/libguardedalloc.a COMLIB += $(NAN_MEMUTIL)/lib/libmemutil.a COMLIB += $(NAN_BMFONT)/lib/$(DEBUG_DIR)libbmfont.a diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index ec58382b86a..bbdf4bc01c9 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -1,36 +1,36 @@ /** -* 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 ***** -*/ + * 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 @@ -46,10 +46,10 @@ struct DerivedMesh; // this is needed for inlining behaviour #ifndef _WIN32 - #define LINUX - #define DO_INLINE inline +#define LINUX +#define DO_INLINE inline #else - #define DO_INLINE +#define DO_INLINE #endif #define CLOTH_MAX_THREAD 2 @@ -86,27 +86,27 @@ struct DerivedMesh; typedef enum { CSIMSETT_FLAG_RESET = (1 << 1), // The CM object requires a reinitializaiton. - CSIMSETT_FLAG_COLLOBJ = (1 << 2), // object is only collision object, no cloth simulation is done - CSIMSETT_FLAG_GOAL = (1 << 3), // we have goals enabled - CSIMSETT_FLAG_CCACHE_FREE_ALL = (1 << 4), // delete all from cache - CSIMSETT_FLAG_CCACHE_FREE_PART = (1 << 5), // delete some part of cache - CSIMSETT_FLAG_TEARING_ENABLED = (1 << 6), // true if tearing is enabled - CSIMSETT_FLAG_CCACHE_PROTECT = (1 << 7), // true if tearing is enabled + CSIMSETT_FLAG_COLLOBJ = (1 << 2), // object is only collision object, no cloth simulation is done + CSIMSETT_FLAG_GOAL = (1 << 3), // we have goals enabled + CSIMSETT_FLAG_CCACHE_FREE_ALL = (1 << 4), // delete all from cache + CSIMSETT_FLAG_CCACHE_FREE_PART = (1 << 5), // delete some part of cache + CSIMSETT_FLAG_TEARING_ENABLED = (1 << 6), // true if tearing is enabled + CSIMSETT_FLAG_CCACHE_PROTECT = (1 << 7), // true if tearing is enabled } CSIMSETT_FLAGS; /* Spring types as defined in the paper.*/ typedef enum { STRUCTURAL = 0, - SHEAR, - BENDING, + SHEAR, + BENDING, } springType; /* SPRING FLAGS */ typedef enum { CSPRING_FLAG_DEACTIVATE = (1 << 1), - CSPRING_FLAG_NEEDED = (1 << 2), // springs has values to be applied + CSPRING_FLAG_NEEDED = (1 << 2), // springs has values to be applied } CSPRINGS_FLAGS; // needed for buttons_object.c @@ -156,7 +156,7 @@ typedef void (*CM_COLLISION_RESPONSE) (ClothModifierData *clmd, ClothModifierDat // needed for implicit.c void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2); -int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RESPONSE collision_response, float dt); +int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt); //////////////////////////////////////////////// @@ -165,16 +165,13 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE // kdop.c //////////////////////////////////////////////// -// needed for implicit.c -void bvh_update_static(ClothModifierData * clmd, BVH * bvh); -void bvh_update_moving(ClothModifierData * clmd, BVH * bvh); - // needed for cloth.c void bvh_free(BVH * bvh); BVH *bvh_build (ClothModifierData *clmd, float epsilon); // needed for collision.c int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response); +void bvh_update(ClothModifierData * clmd, BVH * bvh, int moving); //////////////////////////////////////////////// @@ -209,8 +206,7 @@ typedef struct { char *name; CM_SOLVER_ID id; int (*init) (Object *ob, ClothModifierData *clmd); - int (*solver) (Object *ob, float framenr, ClothModifierData *clmd, ListBase *effectors, - CM_COLLISION_SELF self_collision, CM_COLLISION_OBJ obj_collision); + int (*solver) (Object *ob, float framenr, ClothModifierData *clmd, ListBase *effectors); int (*free) (ClothModifierData *clmd); } CM_SOLVER_DEF; @@ -218,8 +214,7 @@ typedef struct { /* new C implicit simulator */ int implicit_init (Object *ob, ClothModifierData *clmd); int implicit_free (ClothModifierData *clmd); -int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors, - CM_COLLISION_SELF self_collision, CM_COLLISION_OBJ obj_collision); +int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors); /* used for caching in implicit.c */ typedef struct Frame @@ -237,10 +232,10 @@ typedef struct CollPair double distance; // magnitude of vector float normal[3]; float vector[3]; // unnormalized collision vector: p2-p1 - float p1[3], p2[3]; // collision point p1 on face1, p2 on face2 + 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 Aindex1, Aindex2, Aindex3, Aindex4, Bindex1, Bindex2, Bindex3, Bindex4; + unsigned int ap1, ap2, ap3, bp1, bp2, bp3; } CollPair; diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 72fcc466de8..e87eb2a3e3f 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -77,6 +77,9 @@ CPPFLAGS += -I../../nodes # path to our own external headerfiles CPPFLAGS += -I.. +# path to bullet2, for cloth +CPPFLAGS += -I../../../../extern/bullet2/src + ifeq ($(WITH_FREETYPE2), true) CPPFLAGS += -DWITH_FREETYPE2 CPPFLAGS += -I$(NAN_FREETYPE)/include diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index d9f0bef9f43..940fc8b6c5b 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -473,7 +473,6 @@ int cloth_cache_last_frame(ClothModifierData *clmd) search = search->next; } } - return temptime; } @@ -567,12 +566,7 @@ void cloth_cache_set_frame(ClothModifierData *clmd, float time) */ } if(frame) - { - if(!clmd->sim_parms.cache) - BLI_linklist_prepend(&clmd->sim_parms.cache, frame); - else - BLI_linklist_append(&clmd->sim_parms.cache, frame); - } + BLI_linklist_append(&clmd->sim_parms.cache, frame); } } @@ -683,6 +677,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, } } + // unused in the moment, calculated seperately in implicit.c clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame; @@ -774,7 +769,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, /* Call the solver. */ if (solvers [clmd->sim_parms.solver_type].solver) - solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors,0,0); + solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors); tend(); printf("Cloth simulation time: %f\n", (float)tval()); @@ -797,10 +792,13 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, } else if((deltaTime <= 0.0f)||(deltaTime > 1.0f)) { - if(cloth_cache_search_frame(clmd, framenr)) + if((clmd->clothObject != NULL) && (clmd->sim_parms.cache)) { - cloth_cache_get_frame(clmd, framenr); - cloth_to_object (ob, clmd, vertexCos, numverts); + if(cloth_cache_search_frame(clmd, framenr)) + { + cloth_cache_get_frame(clmd, framenr); + cloth_to_object (ob, clmd, vertexCos, numverts); + } } } } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 7eec315e386..20c1548e14b 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -77,13 +77,13 @@ enum TRIANGLE_MARK { TM_MV = 1, - TM_ME = 2, - TM_V1 = 4, - TM_V2 = 8, - TM_V3 = 16, - TM_E1 = 32, - TM_E2 = 64, - TM_E3 = 128 + TM_ME = 2, + TM_V1 = 4, + TM_V2 = 8, + TM_V3 = 16, + TM_E1 = 32, + TM_E2 = 64, + TM_E3 = 128 }; DO_INLINE int hasTriangleMark(unsigned char mark, unsigned char bit) { return mark & bit; } @@ -104,64 +104,64 @@ void generateTriangleMarks() // 2.1 Randomly mark triangles for covering vertices. for (unsigned int v = 0; v < m_vertexCount; ++v) { - if (vertexCover(v) == 0) - { + if (vertexCover(v) == 0) + { // Randomly select an edge whose first triangle we're going to flag. #ifndef DERANDOMIZE - firstEdge = (unsigned int)((float)(random() & 0x7FFFFFFF) / - (float)(0x80000000) * - (float)(m_vertices[v].getEdgeCount())); + firstEdge = (unsigned int)((float)(random() & 0x7FFFFFFF) / + (float)(0x80000000) * + (float)(m_vertices[v].getEdgeCount())); #endif - for (unsigned int ofs = 0; ofs < m_vertices[v].getEdgeCount(); ++ofs) - { - unsigned int edgeIdx = (firstEdge + ofs) % m_vertices[v].getEdgeCount(); - if (m_edges[m_vertices[v].getEdge(edgeIdx)].getTriangleCount()) - setTriangleMark(m_triangleMarks[m_edges[m_vertices[v].getEdge(edgeIdx)].getTriangle(0)], TM_MV); - } - } - } + for (unsigned int ofs = 0; ofs < m_vertices[v].getEdgeCount(); ++ofs) + { + unsigned int edgeIdx = (firstEdge + ofs) % m_vertices[v].getEdgeCount(); + if (m_edges[m_vertices[v].getEdge(edgeIdx)].getTriangleCount()) + setTriangleMark(m_triangleMarks[m_edges[m_vertices[v].getEdge(edgeIdx)].getTriangle(0)], TM_MV); +} +} +} */ /* If the Cloth is malformed (vertices without adjacent triangles) there might still be uncovered vertices. (Bad luck.) */ /* // 2.2 Randomly mark triangles for covering edges. for (unsigned int e = 0; e < m_edgeCount; ++e) { - if (m_edges[e].getTriangleCount() && (edgeCover(e) == 0)) - { + if (m_edges[e].getTriangleCount() && (edgeCover(e) == 0)) + { #ifndef DERANDOMIZE - setTriangleMark(m_triangleMarks[m_edges[e].getTriangle(static_cast((float)(random() & 0x7FFFFFFF) / - (float)(0x80000000) * - (float)(m_edges[e].getTriangleCount())))], TM_ME); + setTriangleMark(m_triangleMarks[m_edges[e].getTriangle(static_cast((float)(random() & 0x7FFFFFFF) / + (float)(0x80000000) * + (float)(m_edges[e].getTriangleCount())))], TM_ME); #else - setTriangleMark(m_triangleMarks[m_edges[e].getTriangle(0)], TM_ME); + setTriangleMark(m_triangleMarks[m_edges[e].getTriangle(0)], TM_ME); #endif - } - } +} +} // 3. The Unmarking Process for (unsigned int t = 0; (t < m_triangleCount); ++t) { - bool overCoveredVertices = true; - bool overCoveredEdges = true; - for (unsigned char i = 0; (i < 3) && (overCoveredVertices || overCoveredEdges); ++i) - { + bool overCoveredVertices = true; + bool overCoveredEdges = true; + for (unsigned char i = 0; (i < 3) && (overCoveredVertices || overCoveredEdges); ++i) + { - if (vertexCover(m_triangles[t].getVertex(i)) == 1) - overCoveredVertices = false; - if (edgeCover(m_triangles[t].getEdge(i)) == 1) - overCoveredEdges = false; + if (vertexCover(m_triangles[t].getVertex(i)) == 1) + overCoveredVertices = false; + if (edgeCover(m_triangles[t].getEdge(i)) == 1) + overCoveredEdges = false; - assert(vertexCover(m_triangles[t].getVertex(i)) > 0); - assert(edgeCover(m_triangles[t].getEdge(i)) > 0); - } - if (overCoveredVertices) - clearTriangleMark(m_triangleMarks[t], TM_MV); - if (overCoveredEdges) - clearTriangleMark(m_triangleMarks[t], TM_ME); - } + assert(vertexCover(m_triangles[t].getVertex(i)) > 0); + assert(edgeCover(m_triangles[t].getEdge(i)) > 0); +} + if (overCoveredVertices) + clearTriangleMark(m_triangleMarks[t], TM_MV); + if (overCoveredEdges) + clearTriangleMark(m_triangleMarks[t], TM_ME); +} // 4. The Bit Masking Process @@ -169,25 +169,25 @@ void generateTriangleMarks() vector edgeAssigned(m_edgeCount, false); for (unsigned int t = 0; (t < m_triangleCount); ++t) { - for (unsigned char i = 0; i < 3; ++i) - { - if (!vertexAssigned[m_triangles[t].getVertex(i)]) - { - vertexAssigned[m_triangles[t].getVertex(i)] = true; - setTriangleMark(m_triangleMarks[t], 1 << (2 + i)); - } - if (!edgeAssigned[m_triangles[t].getEdge(i)]) - { - edgeAssigned[m_triangles[t].getEdge(i)] = true; - setTriangleMark(m_triangleMarks[t], 1 << (5 + i)); - } - } - } + for (unsigned char i = 0; i < 3; ++i) + { + if (!vertexAssigned[m_triangles[t].getVertex(i)]) + { + vertexAssigned[m_triangles[t].getVertex(i)] = true; + setTriangleMark(m_triangleMarks[t], 1 << (2 + i)); +} + if (!edgeAssigned[m_triangles[t].getEdge(i)]) + { + edgeAssigned[m_triangles[t].getEdge(i)] = true; + setTriangleMark(m_triangleMarks[t], 1 << (5 + i)); +} +} +} */ } // w3 is not perfect -void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], double *w1, double *w2, double *w3) +void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) { double tempV1[3], tempV2[3], tempV4[3]; double a,b,c,d,e,f; @@ -205,13 +205,19 @@ void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3] d = (a * c - b * b); if (ABS(d) < ALMOST_ZERO) { - *w1 = *w2 = *w3 = 1.0f / 3.0f; + *w1 = *w2 = *w3 = 1.0 / 3.0; return; } - w1[0] = (e * c - b * f) / d; + w1[0] = (float)((e * c - b * f) / d); - w2[0] = (f - b * w1[0]) / c; + if(w1[0] < 0) + w1[0] = 0; + + w2[0] = (float)((f - b * (double)w1[0]) / c); + + if(w2[0] < 0) + w2[0] = 0; w3[0] = 1.0f - w1[0] - w2[0]; } @@ -226,7 +232,7 @@ DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], floa DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal[3], double normalVelocity, - double frictionConstant, double delta_V_n) + double frictionConstant, double delta_V_n) { float vrel_t_pre[3]; float vrel_t[3]; @@ -235,631 +241,376 @@ DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal VecMulf(to, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); } -/* -int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, LinkNode **collision_list) + +int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) { - unsigned int i = 0, numfaces = 0; + unsigned int i = 0; int result = 0; LinkNode *search = NULL; CollPair *collpair = NULL; Cloth *cloth1, *cloth2; - MFace *face1, *face2; - double w1, w2, w3, u1, u2, u3, a1, a2, a3; + float w1, w2, w3, u1, u2, u3; float v1[3], v2[3], relativeVelocity[3]; float magrelVel; cloth1 = clmd->clothObject; cloth2 = coll_clmd->clothObject; - - numfaces = clmd->clothObject->numfaces; - - for(i = 0; i < numfaces; i++) - { - search = collision_list[i]; - - while(search) - { - collpair = search->link; - - face1 = &(cloth1->mfaces[collpair->face1]); - face2 = &(cloth2->mfaces[collpair->face2]); - - // compute barycentric coordinates for both collision points - - if(!collpair->quadA) - { - bvh_compute_barycentric(collpair->p1, - cloth1->verts[face1->v1].txold, - cloth1->verts[face1->v2].txold, - cloth1->verts[face1->v3].txold, - &w1, &w2, &w3); - } - else - bvh_compute_barycentric(collpair->p1, - cloth1->verts[face1->v4].txold, - cloth1->verts[face1->v1].txold, - cloth1->verts[face1->v3].txold, - &w1, &w2, &w3); - - if(!collpair->quadB) - bvh_compute_barycentric(collpair->p2, - cloth2->verts[face2->v1].txold, - cloth2->verts[face2->v2].txold, - cloth2->verts[face2->v3].txold, - &u1, &u2, &u3); - else - bvh_compute_barycentric(collpair->p2, - cloth2->verts[face2->v4].txold, - cloth2->verts[face2->v1].txold, - cloth2->verts[face2->v3].txold, - &u1, &u2, &u3); - - // Calculate relative "velocity". - - if(!collpair->quadA) - interpolateOnTriangle(v1, cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv, cloth1->verts[face1->v3].tv, w1, w2, w3); - else - interpolateOnTriangle(v1, cloth1->verts[face1->v4].tv, cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv, w1, w2, w3); - - if(!collpair->quadB) - interpolateOnTriangle(v2, cloth2->verts[face2->v1].tv, cloth2->verts[face2->v2].tv, cloth2->verts[face2->v3].tv, u1, u2, u3); - else - interpolateOnTriangle(v2, cloth2->verts[face2->v4].tv, cloth2->verts[face2->v1].tv, cloth2->verts[face2->v3].tv, u1, u2, u3); - - VECSUB(relativeVelocity, v1, v2); - - // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). - magrelVel = INPR(relativeVelocity, collpair->normal); - - // Calculate masses of points. - - // If v_n_mag > 0 the edges are approaching each other. - - if(magrelVel < -ALMOST_ZERO) - { - // Calculate Impulse magnitude to stop all motion in normal direction. - // const double I_mag = v_n_mag / (1/m1 + 1/m2); - float magnitude_i = magrelVel / 2.0f; // TODO implement masses - float tangential[3], magtangent, magnormal, collvel[3]; - float vrel_t_pre[3]; - float vrel_t[3]; - double impulse; - float epsilon = clmd->coll_parms.epsilon; - float overlap = (epsilon + ALMOST_ZERO-collpair->distance); - - // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); - - // magtangent = INPR(tangential, tangential); - - // Apply friction impulse. - if (magtangent < ALMOST_ZERO) - { - - // printf("friction applied: %f\n", magtangent); - // TODO check original code - - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,tangential); - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv,tangential); - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv,tangential); - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential); - - } - - impulse = -magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse); - cloth1->verts[face1->v1].impulse_count++; - - VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse); - cloth1->verts[face1->v2].impulse_count++; - - VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse); - cloth1->verts[face1->v3].impulse_count++; - - if(face1->v4) - { - VECADDMUL(cloth1->verts[face1->v4].impulse, collpair->normal, impulse); - cloth1->verts[face1->v4].impulse_count++; - } - - - if (overlap > ALMOST_ZERO) { - double I_mag = overlap * 0.1; - - impulse = I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - - VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse); - cloth1->verts[face1->v1].impulse_count++; - - VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse); - cloth1->verts[face1->v2].impulse_count++; - - VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse); - cloth1->verts[face1->v3].impulse_count++; - - if(face1->v4) - { - VECADDMUL(cloth1->verts[face1->v4].impulse, collpair->normal, impulse); - cloth1->verts[face1->v4].impulse_count++; - } - - } - - result = 1; - - - // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case - - // Apply the impulse and increase impulse counters. - / - // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent); - VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); - // VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); - magtangent = Normalize(vrel_t_pre); - VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent)); - - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre); - - + search = clmd->coll_parms.collision_list; + + while(search) + { + collpair = search->link; + + // compute barycentric coordinates for both collision points + bvh_compute_barycentric(collpair->pa, + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3); + + bvh_compute_barycentric(collpair->pb, + cloth2->verts[collpair->bp1].txold, + cloth2->verts[collpair->bp2].txold, + cloth2->verts[collpair->bp3].txold, + &u1, &u2, &u3); + + // Calculate relative "velocity". + interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3); + + interpolateOnTriangle(v2, cloth2->verts[collpair->bp1].tv, cloth2->verts[collpair->bp2].tv, cloth2->verts[collpair->bp3].tv, u1, u2, u3); + + VECSUB(relativeVelocity, v1, v2); + + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). + magrelVel = INPR(relativeVelocity, collpair->normal); + + // printf("magrelVel: %f\n", magrelVel); + // Calculate masses of points. + + // If v_n_mag < 0 the edges are approaching each other. + if(magrelVel < -ALMOST_ZERO) + { + // Calculate Impulse magnitude to stop all motion in normal direction. + // const double I_mag = v_n_mag / (1/m1 + 1/m2); + float magnitude_i = magrelVel / 2.0f; // TODO implement masses + float tangential[3], magtangent, magnormal, collvel[3]; + float vrel_t_pre[3]; + float vrel_t[3]; + double impulse; + float epsilon = clmd->coll_parms.epsilon; + float overlap = (epsilon + ALMOST_ZERO-collpair->distance); + + // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); + + // magtangent = INPR(tangential, tangential); + + // Apply friction impulse. + if (magtangent < -ALMOST_ZERO) + { + // printf("friction applied: %f\n", magtangent); + // TODO check original code + /* + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential); + */ } - search = search->next; + + impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + // printf("impulse: %f\n", impulse); + + VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); + cloth1->verts[collpair->ap1].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); + cloth1->verts[collpair->ap2].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); + cloth1->verts[collpair->ap3].impulse_count++; + + result = 1; + + /* + if (overlap > ALMOST_ZERO) { + double I_mag = overlap * 0.1; + + impulse = -I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); + cloth1->verts[collpair->ap1].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); + cloth1->verts[collpair->ap2].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); + cloth1->verts[collpair->ap3].impulse_count++; } + */ + + // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case + + // Apply the impulse and increase impulse counters. + + /* + // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent); + VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); + // VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); + magtangent = Normalize(vrel_t_pre); + VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent)); + + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre); + */ + + + + } + + search = search->next; } + return result; } -*/ - -// return distance between two triangles using bullet engine -double implicit_tri_check_coherence (ClothModifierData *clmd, ClothModifierData *coll_clmd, unsigned int tri_index1, unsigned int tri_index2, float pa[3], float pb[3], float normal[3], int quadA, int quadB) + +void bvh_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) { + CollPair *collpair = NULL; + Cloth *cloth1=NULL, *cloth2=NULL; MFace *face1=NULL, *face2=NULL; - float a[3][3]; - float b[3][3]; - double distance=0, tempdistance=0; - Cloth *cloth1=NULL, *cloth2=NULL; - float tpa[3], tpb[3], tnormal[3]; - unsigned int indexA=0, indexB=0, indexC=0, indexD=0, indexE=0, indexF=0; - int i = 0; - - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - face1 = &(cloth1->mfaces[tri_index1]); - face2 = &(cloth2->mfaces[tri_index2]); - - // face a1 + face b1 - VECCOPY(a[0], cloth1->verts[face1->v1].txold); - VECCOPY(a[1], cloth1->verts[face1->v2].txold); - VECCOPY(a[2], cloth1->verts[face1->v3].txold); - - - VECCOPY(b[0], cloth2->verts[face2->v1].txold); - VECCOPY(b[1], cloth2->verts[face2->v2].txold); - VECCOPY(b[2], cloth2->verts[face2->v3].txold); - - distance = plNearestPoints(a,b,pa,pb,normal); - - quadA = quadB = 0; - - for(i = 0; i < 3; i++) - { - if(i == 0) - { - if(face1->v4) - { - indexA = face1->v4; - indexB = face1->v1; - indexC = face1->v3; - - indexD = face2->v1; - indexE = face2->v2; - indexF = face2->v3; - } - else - i+=2; - } - - if(i == 1) - { - if((face1->v4)&&(face2->v4)) - { - indexA = face1->v4; - indexB = face1->v1; - indexC = face1->v3; - - indexD = face2->v4; - indexE = face2->v1; - indexF = face2->v3; - } - else - i++; - } - - if(i == 2) - { - if(face2->v4) - { - indexA = face1->v1; - indexB = face1->v2; - indexC = face1->v3; - - indexD = face2->v4; - indexE = face2->v1; - indexF = face2->v3; - } - else - i++; - - } - - if(i<3) - { - // face a2 + face b1 - VECCOPY(a[0], cloth1->verts[indexA].txold); - VECCOPY(a[1], cloth1->verts[indexB].txold); - VECCOPY(a[2], cloth1->verts[indexC].txold); - - - VECCOPY(b[0], cloth2->verts[indexD].txold); - VECCOPY(b[1], cloth2->verts[indexE].txold); - VECCOPY(b[2], cloth2->verts[indexF].txold); - - tempdistance = plNearestPoints(a,b,tpa,tpb,tnormal); - - if(tempdistance < distance) - { - VECCOPY(pa, tpa); - VECCOPY(pb, tpb); - VECCOPY(normal, tnormal); - distance = tempdistance; - - if(i == 0) - { - quadA = 1; quadB = 0; - } - else if(i == 1) - { - quadA = quadB = 1; - } - else if(i == 2) - { - quadA = 0; quadB = 1; - } - } - } - } - return distance; -} - -// calculate plane normal -void calcPlaneNormal(float normal[3], float p11[3], float p12[3], float p13[3]) -{ - float temp1[3], temp2[3]; - float tnormal[3]; - - VECSUB(temp1, p12,p11); - VECSUB(temp2, p13,p11); - Crossf(normal, temp1, temp2); - Normalize(normal); - // VECCOPY(normal, tnormal); -} - -float distance_triangle_point( float p11[3], float p12[3], float p13[3], float p21[3], float normal[3]) -{ - float temp[3]; - float magnitude = 0; - - VECSUB(temp, p21, p13); - magnitude = INPR(temp, normal); - - if(magnitude < 0) - { - magnitude *= -1.0f; - // VecMulf(normal, -1.0f); - } - - return magnitude; -} - -float nearest_point_triangle_triangle(float p11[3], float p12[3], float p13[3], float p21[3], float p22[3], float p23[3], float normal[3]) -{ - float distance = 0, tdistance = 0, tnormal[3]; - - // first triangle 1-2-3 versus second triangle 1-2-3 - calcPlaneNormal(normal, p11, p12, p13); - distance = distance_triangle_point(p11, p12, p13, p21, normal); - - tdistance = distance_triangle_point(p11, p12, p13, p22, normal); - - if(tdistance < distance) - { - distance = tdistance; - } - - tdistance = distance_triangle_point(p11, p12, p13, p23, normal); - - if(tdistance < distance) - { - distance = tdistance; - } - - // second triangle 1-2-3 versus first triangle 1-2-3 - calcPlaneNormal(tnormal, p21, p22, p23); - - tdistance = distance_triangle_point(p21, p22, p23, p11, tnormal); - - if(tdistance < distance) - { - distance = tdistance; - VECCOPY(normal, tnormal); - } - - tdistance = distance_triangle_point(p21, p22, p23, p12, tnormal); - - if(tdistance < distance) - { - distance = tdistance; - VECCOPY(normal, tnormal); - } - - tdistance = distance_triangle_point(p21, p22, p23, p13, tnormal); - - if(tdistance < distance) - { - distance = tdistance; - VECCOPY(normal, tnormal); - } - - - if (distance < 0) { - VecMulf(normal, -1.0f); - distance = -distance; - } - - return distance; -} - - -int collision_static2(ClothModifierData *clmd, ClothModifierData *coll_clmd, LinkNode **collision_list) -{ - unsigned int i = 0, numfaces = 0; - int result = 0; - LinkNode *search = NULL; - CollPair *collpair = NULL; - Cloth *cloth1, *cloth2; - MFace *face1, *face2; - double w1, w2, w3, u1, u2, u3, a1, a2, a3; - float v1[3], v2[3], relativeVelocity[3]; - float magrelVel; - - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - numfaces = clmd->clothObject->numfaces; - - for(i = 0; i < numfaces; i++) - { - search = collision_list[i]; - - while(search) - { - collpair = search->link; - - face1 = &(cloth1->mfaces[collpair->face1]); - face2 = &(cloth2->mfaces[collpair->face2]); - - // compute barycentric coordinates for both collision points - - - bvh_compute_barycentric(collpair->p1, - cloth1->verts[collpair->Aindex1].txold, - cloth1->verts[collpair->Aindex2].txold, - cloth1->verts[collpair->Aindex3].txold, - &w1, &w2, &w3); - - bvh_compute_barycentric(collpair->p2, - cloth2->verts[collpair->Bindex1].txold, - cloth2->verts[collpair->Bindex1].txold, - cloth2->verts[collpair->Bindex3].txold, - &u1, &u2, &u3); - - // Calculate relative "velocity". - interpolateOnTriangle(v1, cloth1->verts[collpair->Aindex1].tv, cloth1->verts[collpair->Aindex2].tv, cloth1->verts[collpair->Aindex3].tv, w1, w2, w3); - - interpolateOnTriangle(v2, cloth2->verts[collpair->Bindex1].tv, cloth2->verts[collpair->Bindex2].tv, cloth2->verts[collpair->Bindex3].tv, u1, u2, u3); - - VECSUB(relativeVelocity, v1, v2); - - // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). - magrelVel = INPR(relativeVelocity, collpair->normal); - - // Calculate masses of points. - - // If v_n_mag > 0 the edges are approaching each other. - - if(magrelVel < -ALMOST_ZERO) - { - // Calculate Impulse magnitude to stop all motion in normal direction. - // const double I_mag = v_n_mag / (1/m1 + 1/m2); - float magnitude_i = magrelVel / 2.0f; // TODO implement masses - float tangential[3], magtangent, magnormal, collvel[3]; - float vrel_t_pre[3]; - float vrel_t[3]; - double impulse; - float epsilon = clmd->coll_parms.epsilon; - float overlap = (epsilon + ALMOST_ZERO-collpair->distance); - - /* - impulse = -magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse); - cloth1->verts[face1->v1].impulse_count++; - - VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse); - cloth1->verts[face1->v2].impulse_count++; - - VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse); - cloth1->verts[face1->v3].impulse_count++; - */ - - - /* - if (overlap > ALMOST_ZERO) { - double I_mag = overlap * 0.1; - - impulse = I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - - VECADDMUL(cloth1->verts[face1->v1].impulse, collpair->normal, impulse); - cloth1->verts[face1->v1].impulse_count++; - - VECADDMUL(cloth1->verts[face1->v2].impulse, collpair->normal, impulse); - cloth1->verts[face1->v2].impulse_count++; - - VECADDMUL(cloth1->verts[face1->v3].impulse, collpair->normal, impulse); - cloth1->verts[face1->v3].impulse_count++; - - if(face1->v4) - { - VECADDMUL(cloth1->verts[face1->v4].impulse, collpair->normal, impulse); - cloth1->verts[face1->v4].impulse_count++; - } - - } - */ - - result = 1; - } - - search = search->next; - } - } - - return result; -} - -void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2) -{ - CollPair *collpair = NULL; - LinkNode **linknode; + ClothVertex *verts1=NULL, *verts2=NULL; double distance = 0; - float epsilon = clmd->coll_parms.epsilon, tdistance=0; - MFace *face1, *face2; - ClothVertex *verts1, *verts2; - Cloth *cloth1=NULL, *cloth2=NULL; - int i = 0; - - linknode = clmd->coll_parms.temp; - - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - // calc SIPcode (?) - + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0; + for(i = 0; i < 4; i++) { - collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); + collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; - face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(cloth2->mfaces[tree2->tri_index]); - verts1 = cloth1->verts; verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + // check all possible pairs of triangles if(i == 0) { - collpair->Aindex1 = face1->v1; - collpair->Aindex2 = face1->v2; - collpair->Aindex3 = face1->v3; - collpair->Aindex4 = face1->v4; + collpair->ap1 = face1->v1; + collpair->ap2 = face1->v2; + collpair->ap3 = face1->v3; - collpair->Bindex1 = face2->v1; - collpair->Bindex2 = face2->v2; - collpair->Bindex3 = face2->v3; - collpair->Bindex4 = face2->v4; + collpair->bp1 = face2->v1; + collpair->bp2 = face2->v2; + collpair->bp3 = face2->v3; } if(i == 1) { - if(face2->v4) - { - collpair->Aindex1 = face1->v1; - collpair->Aindex2 = face1->v2; - collpair->Aindex3 = face1->v3; - collpair->Aindex4 = face1->v4; + if(face1->v4) + { + collpair->ap1 = face1->v3; + collpair->ap2 = face1->v4; + collpair->ap3 = face1->v1; - collpair->Bindex1 = face2->v4; - collpair->Bindex2 = face2->v3; - collpair->Bindex3 = face2->v1; - collpair->Bindex4 = face2->v1; + collpair->bp1 = face2->v1; + collpair->bp2 = face2->v2; + collpair->bp3 = face2->v3; } else i++; - } if(i == 2) { - if(face1->v4) - { - collpair->Aindex1 = face1->v4; - collpair->Aindex2 = face1->v3; - collpair->Aindex3 = face1->v1; - collpair->Aindex4 = face1->v2; + if(face2->v4) + { + collpair->ap1 = face1->v1; + collpair->ap2 = face1->v2; + collpair->ap3 = face1->v3; - collpair->Bindex1 = face2->v1; - collpair->Bindex2 = face2->v2; - collpair->Bindex3 = face2->v3; - collpair->Bindex4 = face2->v4; + collpair->bp1 = face2->v3; + collpair->bp2 = face2->v4; + collpair->bp3 = face2->v1; } else - i++; + i+=2; } if(i == 3) { - if((face2->v4) && (face1->v4)) - { - collpair->Aindex1 = face1->v4; - collpair->Aindex2 = face1->v3; - collpair->Aindex3 = face1->v1; - collpair->Aindex4 = face1->v2; + if((face1->v4)&&(face2->v4)) + { + collpair->ap1 = face1->v3; + collpair->ap2 = face1->v4; + collpair->ap3 = face1->v1; - collpair->Bindex1 = face2->v4; - collpair->Bindex2 = face2->v3; - collpair->Bindex3 = face2->v1; - collpair->Bindex4 = face2->v2; + collpair->bp1 = face2->v3; + collpair->bp2 = face2->v4; + collpair->bp3 = face2->v1; } else i++; } + // calc SIPcode (?) + if(i < 4) { - distance = nearest_point_triangle_triangle(verts1[collpair->Aindex1].txold, verts1[collpair->Aindex2].txold, verts1[collpair->Aindex3].txold, verts2[collpair->Bindex1].txold, verts2[collpair->Bindex2].txold, verts2[collpair->Bindex3].txold, collpair->normal); - // calc distance + normal - // distance = implicit_tri_check_coherence(clmd, coll_clmd, tree1->tri_index, tree2->tri_index, collpair->p1, collpair->p2, collpair->vector, collpair->quadA, collpair->quadB); + distance = plNearestPoints( + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, + collpair->pa, collpair->pb, collpair->vector); - if (distance <= (epsilon + ALMOST_ZERO)) // max overlap = 1.0 + if (distance <= (epsilon + ALMOST_ZERO)) { + // printf("dist: %f\n", (float)distance); - printf("dist: %f, tdist: %f\n", (float)distance, tdistance); + // collpair->face1 = tree1->tri_index; + // collpair->face2 = tree2->tri_index; - collpair->face1 = tree1->tri_index; - collpair->face2 = tree2->tri_index; + VECCOPY(collpair->normal, collpair->vector); + Normalize(collpair->normal); collpair->distance = distance; - BLI_linklist_append(&linknode[tree1->tri_index], collpair); + BLI_linklist_append(&clmd->coll_parms.collision_list, collpair); } else { MEM_freeN(collpair); } } + else + { + MEM_freeN(collpair); + } + } +} + +void bvh_collision_response_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +{ + CollPair *collpair = NULL; + Cloth *cloth1=NULL, *cloth2=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL, *verts2=NULL; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0; + + for(i = 0; i < 4; i++) + { + collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + // check all possible pairs of triangles + if(i == 0) + { + collpair->ap1 = face1->v1; + collpair->ap2 = face1->v2; + collpair->ap3 = face1->v3; + + collpair->bp1 = face2->v1; + collpair->bp2 = face2->v2; + collpair->bp3 = face2->v3; + + } + + if(i == 1) + { + if(face1->v4) + { + collpair->ap1 = face1->v3; + collpair->ap2 = face1->v4; + collpair->ap3 = face1->v1; + + collpair->bp1 = face2->v1; + collpair->bp2 = face2->v2; + collpair->bp3 = face2->v3; + } + else + i++; + } + + if(i == 2) + { + if(face2->v4) + { + collpair->ap1 = face1->v1; + collpair->ap2 = face1->v2; + collpair->ap3 = face1->v3; + + collpair->bp1 = face2->v3; + collpair->bp2 = face2->v4; + collpair->bp3 = face2->v1; + } + else + i+=2; + } + + if(i == 3) + { + if((face1->v4)&&(face2->v4)) + { + collpair->ap1 = face1->v3; + collpair->ap2 = face1->v4; + collpair->ap3 = face1->v1; + + collpair->bp1 = face2->v3; + collpair->bp2 = face2->v4; + collpair->bp3 = face2->v1; + } + else + i++; + } + + // calc SIPcode (?) + + if(i < 4) + { + // calc distance + normal + distance = plNearestPoints( + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, + collpair->pa, collpair->pb, collpair->vector); + + if (distance <= (epsilon + ALMOST_ZERO)) + { + // printf("dist: %f\n", (float)distance); + + // collpair->face1 = tree1->tri_index; + // collpair->face2 = tree2->tri_index; + + VECCOPY(collpair->normal, collpair->vector); + Normalize(collpair->normal); + + collpair->distance = distance; + BLI_linklist_append(&clmd->coll_parms.collision_list, collpair); + } + else + { + MEM_freeN(collpair); + } + } + else + { + MEM_freeN(collpair); + } } } @@ -899,9 +650,9 @@ void cloth_update_collision_objects(float step) // no dt here because of float rounding errors VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold); } - + // update BVH of collision object - bvh_update_static(coll_clmd, coll_bvh); + bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); @@ -909,20 +660,22 @@ void cloth_update_collision_objects(float step) } } -#define CLOTH_MAX_THRESHOLD 5 +// CLOTH_MAX_THRESHOLD defines how much collision rounds/loops should be taken +#define CLOTH_MAX_THRESHOLD 10 // cloth - object collisions -int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RESPONSE collision_response, float dt) +int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { Base *base=NULL; ClothModifierData *coll_clmd=NULL; Cloth *cloth=NULL; Object *coll_ob=NULL; BVH *cloth_bvh=NULL; - unsigned int i=0, numfaces = 0, numverts = 0; - unsigned int result = 0, ic = 0, rounds = 0; + unsigned int i=0, j = 0, numfaces = 0, numverts = 0; + unsigned int result = 0, ic = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; float tnull[3] = {0,0,0}; + int ret = 0; if ((clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) { @@ -939,86 +692,96 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE //////////////////////////////////////////////////////////// // update cloth bvh - bvh_update_static(clmd, cloth_bvh); + bvh_update(clmd, cloth_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function) // update collision objects cloth_update_collision_objects(step); - + do { result = 0; ic = 0; - - // handle all collision objects + clmd->coll_parms.collision_list = NULL; + + // check all collision objects for (base = G.scene->base.first; base; base = base->next) { - coll_ob = base->object; coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) continue; - + // if collision object go on if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) { if (coll_clmd->clothObject && coll_clmd->clothObject->tree) { - LinkNode **collision_list = MEM_callocN (sizeof(LinkNode *)*(numfaces), "collision_list"); BVH *coll_bvh = coll_clmd->clothObject->tree; - - if(collision_list) - { - memset(collision_list, 0, sizeof(LinkNode *)*numfaces); - clmd->coll_parms.temp = collision_list; - - bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, collision_response); - - result += collision_static2(clmd, coll_clmd, collision_list); - - // calculate velocities - - // free temporary list - for(i = 0; i < numfaces; i++) - { - LinkNode *search = collision_list[i]; - while(search) - { - LinkNode *next= search->next; - CollPair *collpair = search->link; - - if(collpair) - MEM_freeN(collpair); - - search = next; - } - - BLI_linklist_free(collision_list[i],NULL); - } - if(collision_list) - MEM_freeN(collision_list); - - clmd->coll_parms.temp = NULL; - } - + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, bvh_collision_response_static); } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); } } - // now apply impulses parallel - - for(i = 0; i < numverts; i++) + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 50; j++) // 50 is just a value that ensures convergence { - if(verts[i].impulse_count) + result = 0; + + // handle all collision objects + for (base = G.scene->base.first; base; base = base->next) { - VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); - VECCOPY(verts[i].impulse, tnull); - verts[i].impulse_count = 0; - - ic++; + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject) + result += collision_static(clmd, coll_clmd); + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } } + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } + } + } + + // free collision list + if(clmd->coll_parms.collision_list) + { + LinkNode *search = clmd->coll_parms.collision_list; + while(search) + { + CollPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(clmd->coll_parms.collision_list,NULL); + + clmd->coll_parms.collision_list = NULL; } printf("ic: %d\n", ic); @@ -1029,18 +792,162 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, CM_COLLISION_RE printf("\n"); //////////////////////////////////////////////////////////// - // update positions + velocities + // update positions + // this is needed for bvh_calc_DOP_hull_moving() [kdop.c] + //////////////////////////////////////////////////////////// + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } //////////////////////////////////////////////////////////// - - // TODO - //////////////////////////////////////////////////////////// // moving collisions //////////////////////////////////////////////////////////// - // TODO - // bvh_update_moving(clmd, clmd->clothObject->tree); + + // update cloth bvh + bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING + + // update moving bvh for collision object once + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + if(!coll_clmd->clothObject) + continue; + + // if collision object go on + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + BVH *coll_bvh = coll_clmd->clothObject->tree; + + bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING + } + } + + + do + { + result = 0; + ic = 0; + clmd->coll_parms.collision_list = NULL; + + // check all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + BVH *coll_bvh = coll_clmd->clothObject->tree; + + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, bvh_collision_response_moving); + } + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + /* + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 50; j++) // 50 is just a value that ensures convergence + { + result = 0; + + // handle all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject) + result += collision_moving(clmd, coll_clmd); + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } + } + } + */ + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + + // update cloth bvh + bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING + + + // free collision list + if(clmd->coll_parms.collision_list) + { + LinkNode *search = clmd->coll_parms.collision_list; + while(search) + { + CollPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(clmd->coll_parms.collision_list,NULL); + + clmd->coll_parms.collision_list = NULL; + } + + printf("ic: %d\n", ic); + rounds++; + } + while(result && (CLOTH_MAX_THRESHOLD>rounds)); + + + //////////////////////////////////////////////////////////// + // update positions + velocities + //////////////////////////////////////////////////////////// + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + //////////////////////////////////////////////////////////// - return MIN2(result, 1); + return MIN2(ret, 1); } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 3994bbf2b40..7f156acff71 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1431,8 +1431,7 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto del_lfvector(dFdXmV); } -int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors, - CM_COLLISION_SELF self_collision, CM_COLLISION_OBJ obj_collision) +int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) { unsigned int i=0, j; float step=0.0f, tf=1.0f; @@ -1492,14 +1491,14 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase } // call collision function - result = cloth_bvh_objcollision(clmd, step + dt, bvh_collision_response, dt); + result = cloth_bvh_objcollision(clmd, step + dt, dt); // copy corrected positions back to simulation for(i = 0; i < numverts; i++) { if(result) { - VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + // VECADD(verts[i].tx, verts[i].txold, verts[i].tv); VECCOPY(verts[i].txold, verts[i].tx); diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 0088ff92364..51c571f1959 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -123,7 +123,7 @@ static float KDOP_AXES[13][3] = // #define KDOP_8 // OBB: -#define KDOP_14 +#define KDOP_6 @@ -424,54 +424,52 @@ DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, Tree **tri, int numfaces, flo } } } -/* + DO_INLINE void bvh_calc_DOP_hull_moving(BVH * bvh, Tree **tri, int numfaces, float *bv) { -ClothVertex *tempMVert = bvh->verts; -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(tempMVert[temp].tx, KDOP_AXES[i]); -if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0)) -tempBV[(2 * i)] = newminmax; -// the same like some "else if" but with that condition I -// don't need to insert the first entry manually -if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0)) -tempBV[(2 * i) + 1] = newminmax; + ClothVertex *tempMVert = bvh->verts; + 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(tempMVert[temp].txold, 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(tempMVert[temp].tx, 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(tempMVert[temp].txold, KDOP_AXES[i]); -if (newminmax < tempBV[(2 * i)]) -tempBV[(2 * i)] = newminmax; -if (newminmax > tempBV[(2 * i) + 1]) -tempBV[(2 * i) + 1] = newminmax; -} -} -} -} -*/ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink) { int i = 0; @@ -810,7 +808,7 @@ void bvh_join(Tree * tree) } // update static bvh -void bvh_update_static(ClothModifierData * clmd, BVH * bvh) +void bvh_update(ClothModifierData *clmd, BVH * bvh, int moving) { TreeNode *leaf, *parent; int traversecheck = 1; // if this is zero we don't go further @@ -823,7 +821,10 @@ void bvh_update_static(ClothModifierData * clmd, BVH * bvh) { leaf->parent->traversed = 0; } - bvh_calc_DOP_hull_static(bvh, &leaf, 1, leaf->bv); + 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++) @@ -859,3 +860,4 @@ void bvh_update_static(ClothModifierData * clmd, BVH * bvh) } } } + diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 574537f2589..6e986ae0067 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -123,7 +123,7 @@ typedef struct CollisionSettings { 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. */ - void *temp; /* e.g. pointer to temp memory for collisions */ + struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */ } CollisionSettings; From a5db16f913f736b028e4afb190213d346a086233 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 2 Oct 2007 09:47:08 +0000 Subject: [PATCH 021/101] Fixed crash with ipo'ed collision object --- source/blender/blenkernel/BKE_cloth.h | 14 ++++---- source/blender/blenkernel/intern/cloth.c | 44 +++++++++++++++--------- source/blender/blenkernel/intern/kdop.c | 3 +- source/blender/src/headerbuttons.c | 1 + 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index bbdf4bc01c9..4a160275a99 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -86,12 +86,12 @@ struct DerivedMesh; typedef enum { CSIMSETT_FLAG_RESET = (1 << 1), // The CM object requires a reinitializaiton. - CSIMSETT_FLAG_COLLOBJ = (1 << 2), // object is only collision object, no cloth simulation is done - CSIMSETT_FLAG_GOAL = (1 << 3), // we have goals enabled - CSIMSETT_FLAG_CCACHE_FREE_ALL = (1 << 4), // delete all from cache - CSIMSETT_FLAG_CCACHE_FREE_PART = (1 << 5), // delete some part of cache - CSIMSETT_FLAG_TEARING_ENABLED = (1 << 6), // true if tearing is enabled - CSIMSETT_FLAG_CCACHE_PROTECT = (1 << 7), // true if tearing is enabled + CSIMSETT_FLAG_COLLOBJ = (1 << 2), // object is only collision object, no cloth simulation is done + CSIMSETT_FLAG_GOAL = (1 << 3), // we have goals enabled + CSIMSETT_FLAG_CCACHE_FREE_ALL = (1 << 4), // delete all from cache + CSIMSETT_FLAG_CCACHE_FREE_PART = (1 << 5), // delete some part of cache + CSIMSETT_FLAG_TEARING_ENABLED = (1 << 6), // true if tearing is enabled + CSIMSETT_FLAG_CCACHE_PROTECT = (1 << 7), // true if tearing is enabled } CSIMSETT_FLAGS; /* Spring types as defined in the paper.*/ @@ -106,7 +106,7 @@ typedef enum typedef enum { CSPRING_FLAG_DEACTIVATE = (1 << 1), - CSPRING_FLAG_NEEDED = (1 << 2), // springs has values to be applied + CSPRING_FLAG_NEEDED = (1 << 2), // springs has values to be applied } CSPRINGS_FLAGS; // needed for buttons_object.c diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 940fc8b6c5b..35d5771b135 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -656,6 +656,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, // only be active during a specific period: // that's "first frame" and "last frame" on GUI + if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) { if(current_time < clmd->sim_parms.firstframe) @@ -699,7 +700,11 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, if ((clmd->clothObject == NULL) || (numverts != clmd->clothObject->numverts) ) { if(!collobj_from_object (ob, clmd, dm, vertexCos, framenr)) + { + clmd->sim_parms.flags |= CSIMSETT_FLAG_COLLOBJ; + cloth_free_modifier(clmd); return; + } if(clmd->clothObject == NULL) return; @@ -712,7 +717,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, clmd->sim_parms.sim_time = current_time; verts = cloth->verts; - + for (i = 0; i < clmd->clothObject->numverts; i++, verts++) { // Save the previous position. @@ -753,24 +758,24 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, { verts = cloth->verts; - /* Force any pinned verts to their constrained location. */ + // Force any pinned verts to their constrained location. for (i = 0; i < clmd->clothObject->numverts; i++, verts++) { - /* Save the previous position. */ + // Save the previous position. VECCOPY (verts->xold, verts->xconst); VECCOPY (verts->txold, verts->x); - /* Get the current position. */ + // Get the current position. VECCOPY (verts->xconst, vertexCos[i]); Mat4MulVecfl(ob->obmat, verts->xconst); } tstart(); - /* Call the solver. */ + // Call the solver. if (solvers [clmd->sim_parms.solver_type].solver) solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors); - + tend(); printf("Cloth simulation time: %f\n", (float)tval()); @@ -801,6 +806,7 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, } } } + } /* frees all */ @@ -815,7 +821,7 @@ void cloth_free_modifier (ClothModifierData *clmd) if(!(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_PROTECT)) { - // free our frame cache + // free our frame cache, TODO: but get to first position before clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_ALL; cloth_cache_free(clmd, 0); @@ -848,10 +854,10 @@ void cloth_free_modifier (ClothModifierData *clmd) // we save our faces for collision objects if(cloth->mfaces) MEM_freeN(cloth->mfaces); - + /* if(clmd->clothObject->facemarks) MEM_freeN(clmd->clothObject->facemarks); - + */ MEM_freeN (cloth); clmd->clothObject = NULL; } @@ -965,8 +971,8 @@ static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh clmd->clothObject = MEM_callocN (sizeof(Cloth), "cloth"); if (clmd->clothObject) { - clmd->clothObject->old_solver_type = -1; - clmd->clothObject->old_collision_type = -1; + clmd->clothObject->old_solver_type = 255; + clmd->clothObject->old_collision_type = 255; } else if (clmd->clothObject == NULL) { @@ -986,8 +992,12 @@ static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh if (clmd->clothObject != NULL) { - mvert = CDDM_get_verts(dm); + if (!dm) return 0; + if (!dm->getNumVerts(dm) || !dm->getNumFaces(dm)) return 0; + + mvert = dm->getVertArray(dm); verts = clmd->clothObject->verts; + numverts = clmd->clothObject->numverts = dm->getNumVerts(dm); for (i = 0; i < numverts; i++, verts++) { @@ -1004,7 +1014,7 @@ static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh clmd->clothObject->tree = bvh_build(clmd,clmd->coll_parms.epsilon); } - + return 1; default: return 0; // TODO - we do not support changing meshes } @@ -1175,8 +1185,8 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject = MEM_callocN (sizeof(Cloth), "cloth"); if (clmd->clothObject) { - clmd->clothObject->old_solver_type = -1; - clmd->clothObject->old_collision_type = -1; + clmd->clothObject->old_solver_type = 255; + clmd->clothObject->old_collision_type = 255; } else if (clmd->clothObject == NULL) { @@ -1242,7 +1252,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); - cloth_cache_set_frame(clmd, 1); + // cloth_cache_set_frame(clmd, 1); } return 1; @@ -1265,7 +1275,7 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d { unsigned int numverts = dm->getNumVerts(dm); unsigned int numfaces = dm->getNumFaces(dm); - MFace *mface = CDDM_get_faces(dm); + MFace *mface = dm->getFaceArray(dm); unsigned int i = 0; /* Allocate our vertices. diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 51c571f1959..a2d89be5d09 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -572,6 +572,7 @@ BVH *bvh_build (ClothModifierData *clmd, float epsilon) bvh->flags = 0; bvh->leaf_tree = NULL; bvh->leaf_root = NULL; + bvh->tree = NULL; bvh->epsilon = epsilon; bvh->numfaces = cloth->numfaces; @@ -581,7 +582,7 @@ BVH *bvh_build (ClothModifierData *clmd, float epsilon) bvh->verts = cloth->verts; tree = (Tree *)MEM_callocN(sizeof(Tree), "Tree"); // TODO: check succesfull alloc - BLI_linklist_prepend(&bvh->tree, tree); + BLI_linklist_append(&bvh->tree, tree); nlink = bvh->tree; diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c index 4564db8d918..617bef705df 100644 --- a/source/blender/src/headerbuttons.c +++ b/source/blender/src/headerbuttons.c @@ -1067,6 +1067,7 @@ void do_global_buttons(unsigned short event) else if(nr==ID_LA) idtest= (ID *)add_ipo("LaIpo", nr); else if(nr==ID_CA) idtest= (ID *)add_ipo("CaIpo", nr); else if(nr==ID_SO) idtest= (ID *)add_ipo("SndIpo", nr); + else if(nr==ID_FLUIDSIM) idtest= (ID *)add_ipo("FluidsimIpo", nr); else error("Warn bugtracker!"); } idtest->us--; From 179a1b5bbc9d2bd238883e6135209357c53e4235 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 2 Oct 2007 16:55:10 +0000 Subject: [PATCH 022/101] Compile fix for bug on OSX reported by Jens Verwiebe --- source/blender/blenkernel/intern/kdop.c | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index a2d89be5d09..7ce5e6928ea 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -165,7 +165,7 @@ static int size_threshold = 16; /* * Common methods for all algorithms */ -DO_INLINE void exchange(Tree **a, int i, int j) +DO_INLINE void bvh_exchange(Tree **a, int i, int j) { Tree *t=a[i]; a[i]=a[j]; @@ -179,7 +179,7 @@ DO_INLINE int floor_lg(int a) /* * Insertion sort algorithm */ -static void insertionsort(Tree **a, int lo, int hi, int axis) +static void bvh_insertionsort(Tree **a, int lo, int hi, int axis) { int i,j; Tree *t; @@ -196,7 +196,7 @@ static void insertionsort(Tree **a, int lo, int hi, int axis) } } -static int partition(Tree **a, int lo, int hi, Tree * x, int axis) +static int bvh_partition(Tree **a, int lo, int hi, Tree * x, int axis) { int i=lo, j=hi; while (1) @@ -206,7 +206,7 @@ static int partition(Tree **a, int lo, int hi, Tree * x, int axis) while (x->bv[axis] < (a[j])->bv[axis]) j=j-1; if(!(i < j)) return i; - exchange(a, i,j); + bvh_exchange(a, i,j); i++; } } @@ -214,7 +214,7 @@ static int partition(Tree **a, int lo, int hi, Tree * x, int axis) /* * Heapsort algorithm */ -static void downheap(Tree **a, int i, int n, int lo, int axis) +static void bvh_downheap(Tree **a, int i, int n, int lo, int axis) { Tree * d = a[lo+i-1]; int child; @@ -232,21 +232,21 @@ static void downheap(Tree **a, int i, int n, int lo, int axis) a[lo+i-1] = d; } -static void heapsort(Tree **a, int lo, int hi, int axis) +static void bvh_heapsort(Tree **a, int lo, int hi, int axis) { int n = hi-lo, i; for (i=n/2; i>=1; i=i-1) { - downheap(a, i,n,lo, axis); + bvh_downheap(a, i,n,lo, axis); } for (i=n; i>1; i=i-1) { - exchange(a, lo,lo+i-1); - downheap(a, 1,i-1,lo, axis); + bvh_exchange(a, lo,lo+i-1); + bvh_downheap(a, 1,i-1,lo, axis); } } -static Tree *medianof3(Tree **a, int lo, int mid, int hi, int axis) // returns Sortable +static Tree *bvh_medianof3(Tree **a, int lo, int mid, int hi, int axis) // returns Sortable { if ((a[mid])->bv[axis] < (a[lo])->bv[axis]) { @@ -276,7 +276,7 @@ static Tree *medianof3(Tree **a, int lo, int mid, int hi, int axis) // returns S /* * Quicksort algorithm modified for Introsort */ -static void introsort_loop (Tree **a, int lo, int hi, int depth_limit, int axis) +static void bvh_introsort_loop (Tree **a, int lo, int hi, int depth_limit, int axis) { int p; @@ -284,28 +284,28 @@ static void introsort_loop (Tree **a, int lo, int hi, int depth_limit, int axis) { if (depth_limit == 0) { - heapsort(a, lo, hi, axis); + bvh_heapsort(a, lo, hi, axis); return; } depth_limit=depth_limit-1; - p=partition(a, lo, hi, medianof3(a, lo, lo+((hi-lo)/2)+1, hi-1, axis), axis); - introsort_loop(a, p, hi, depth_limit, axis); + 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 sort(Tree **a0, int begin, int end, int axis) +DO_INLINE void bvh_sort(Tree **a0, int begin, int end, int axis) { if (begin < end) { Tree **a=a0; - introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis); - insertionsort(a, begin, end, axis); + 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(Tree **face_list, int start, int end, int axis) { - sort(face_list, start, end, axis); + bvh_sort(face_list, start, end, axis); } //////////////////////////////////////////////////////////////////////////////////////////////// void bvh_free(BVH * bvh) From 62107985dd1db0337827da9a919b2ee04da8a127 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 3 Oct 2007 13:58:05 +0000 Subject: [PATCH 023/101] Recoded cache, fixed some crashes there --- source/blender/blenkernel/BKE_cloth.h | 8 +- source/blender/blenkernel/intern/cloth.c | 372 +++++++++++------------ source/blender/src/buttons_object.c | 10 +- 3 files changed, 187 insertions(+), 203 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 4a160275a99..8750fe3878c 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -34,6 +34,7 @@ #ifndef BKE_CLOTH_H #define BKE_CLOTH_H +#include "BLI_linklist.h" #include "BKE_DerivedMesh.h" #include "DNA_customdata_types.h" #include "BKE_customdata.h" @@ -88,10 +89,8 @@ typedef enum CSIMSETT_FLAG_RESET = (1 << 1), // The CM object requires a reinitializaiton. CSIMSETT_FLAG_COLLOBJ = (1 << 2), // object is only collision object, no cloth simulation is done CSIMSETT_FLAG_GOAL = (1 << 3), // we have goals enabled - CSIMSETT_FLAG_CCACHE_FREE_ALL = (1 << 4), // delete all from cache - CSIMSETT_FLAG_CCACHE_FREE_PART = (1 << 5), // delete some part of cache - CSIMSETT_FLAG_TEARING_ENABLED = (1 << 6), // true if tearing is enabled - CSIMSETT_FLAG_CCACHE_PROTECT = (1 << 7), // true if tearing is enabled + CSIMSETT_FLAG_TEARING_ENABLED = (1 << 4), // true if tearing is enabled + CSIMSETT_FLAG_CCACHE_PROTECT = (1 << 5), // true if tearing is enabled } CSIMSETT_FLAGS; /* Spring types as defined in the paper.*/ @@ -221,6 +220,7 @@ typedef struct Frame { ClothVertex *verts; ClothSpring *springs; + unsigned int numverts, numsprings; float time; /* we need float since we want to support sub-frames */ } Frame; diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 35d5771b135..e86d1c50b69 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -403,230 +403,198 @@ DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) int cloth_cache_search_frame(ClothModifierData *clmd, float time) { Frame *frame = NULL; - LinkNode *search = NULL; - int newtime = time + clmd->sim_parms.preroll; - - Cloth *cloth = NULL; - - if(!clmd) - return 0; - - cloth = clmd->clothObject; - - if(!cloth) - return 0; - - if(clmd->sim_parms.cache) - { + LinkNode *search = NULL; + + if(clmd->clothObject) + { search = clmd->sim_parms.cache; - - // check if frame exists + while(search) { - frame = search->link; - - if(frame->time == newtime) - break; - - frame = NULL; - - search = search->next; - } - } - - if(!frame) - return 0; - - return 1; -} - -int cloth_cache_last_frame(ClothModifierData *clmd) -{ - Frame *frame = NULL; - LinkNode *search = NULL; - int temptime = 0; - - Cloth *cloth = NULL; - - if(!clmd) - return 0; - - cloth = clmd->clothObject; - - if(!cloth) - return 0; - - if(clmd->sim_parms.cache) - { - search = clmd->sim_parms.cache; - - // check if frame exists - while(search) - { - frame = search->link; - - if(frame->time > temptime) + frame = (Frame *)search->link; + + if(frame) { - temptime = frame->time; + if(frame->time == time) + return 1; } - + search = search->next; } - } - return temptime; + } + + return 0; + +} + +float cloth_cache_last_frame(ClothModifierData *clmd) +{ + Frame *frame = NULL; + LinkNode *search = NULL; + float time = 0; + + if(clmd->clothObject) + { + search = clmd->sim_parms.cache; + + while(search) + { + frame = (Frame *)search->link; + + if(frame) + { + if(frame->time > time) + time = frame->time; + } + } + } + return time; +} + +float cloth_cache_first_frame(ClothModifierData *clmd) +{ + Frame *frame = NULL; + LinkNode *search = NULL; + float time = -1.0; + + if(clmd->clothObject) + { + search = clmd->sim_parms.cache; + + while(search) + { + frame = (Frame *)search->link; + + if(frame) + { + if(time < 0.0) + time = frame->time; + else + { + if(frame->time < time) + time = frame->time; + } + } + } + } + return time; } void cloth_cache_get_frame(ClothModifierData *clmd, float time) { Frame *frame = NULL; LinkNode *search = NULL; - unsigned int i = 0; - Cloth *cloth = NULL; - int newtime = time + clmd->sim_parms.preroll; - - if(clmd) + float newtime = time + clmd->sim_parms.preroll; + + if(clmd->clothObject) { - cloth = clmd->clothObject; - - if(!cloth) - return; - - // get cache - if(clmd->sim_parms.cache) + search = clmd->sim_parms.cache; + + while(search) { - search = clmd->sim_parms.cache; - frame = NULL; - // check if frame exists - while(search) - { - frame = search->link; - if(frame->time == newtime) - break; - - frame = NULL; - - search = search->next; - } - + frame = (Frame *)search->link; + if(frame) { - if(frame->verts) + if(frame->time == newtime) { - - // copy ClothVertex struct - memcpy(cloth->verts, frame->verts, cloth->numverts*sizeof(ClothVertex)); + // something changed, free cache! + if(clmd->clothObject->numverts != frame->numverts) + { + cloth_cache_free(clmd, 0); + printf("clmd->clothObject->numverts != frame->numverts\n"); + return; + } + + memcpy(clmd->clothObject->verts, frame->verts, sizeof(ClothVertex)*frame->numverts); implicit_set_positions(clmd); + + return; } - /* - if(frame->springs) - { - // copy ClothSpring struct - memcpy(cloth->springs, frame->springs, cloth->numsprings*sizeof(ClothSpring)); - } - */ } + + search = search->next; } } - } void cloth_cache_set_frame(ClothModifierData *clmd, float time) { Frame *frame = NULL; - unsigned int i = 0; - Cloth *cloth = NULL; - int newtime = time + clmd->sim_parms.preroll; - - if(clmd) + LinkNode *search = NULL; + + if(clmd->clothObject) { - cloth = clmd->clothObject; - - if(cloth) - { - // creat new frame cache - frame = (Frame *)MEM_callocN(sizeof(Frame), "cloth frame cache"); - frame->verts = (ClothVertex *)MEM_callocN(sizeof(ClothVertex)*cloth->numverts, "cloth frame vertex cache"); - frame->springs = NULL; - /* - frame->springs = (ClothSpring *)MEM_callocN(sizeof(ClothSpring)*cloth->numsprings, "cloth frame spring cache"); - */ - frame->time = newtime; - - // copy ClothVertex struct - for(i = 0; i < cloth->numverts; i++) - { - memcpy(&frame->verts[i], &cloth->verts[i], sizeof(ClothVertex)); - } - /* - // copy ClothSpring struct - for(i = 0; i < cloth->numsprings; i++) - { - memcpy(&frame->springs[i], &cloth->springs[i], sizeof(ClothSpring)); - } - */ - } + frame = (Frame *)MEM_callocN (sizeof (Frame), "cloth_cache_frame"); + if(frame) + { + frame->time = time; + frame->numverts = clmd->clothObject->numverts; + frame->verts = MEM_dupallocN(clmd->clothObject->verts); + + if(!frame->verts) + { + MEM_freeN(frame); + return; + } + BLI_linklist_append(&clmd->sim_parms.cache, frame); - } + + } + } + } // free cloth cache void cloth_cache_free(ClothModifierData *clmd, float time) { Frame *frame = NULL; - LinkNode *search, *last_search; - int newtime = time + clmd->sim_parms.preroll; + LinkNode *search = NULL, *lastsearch = NULL; + float newtime = time + clmd->sim_parms.preroll; + + if(time <= 2.0) + newtime = time; - // do never free first cached frame - if((newtime<1.0f) && !(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_FREE_ALL)) - return; - - /* Calls the solver and collision frees first as they - * might depend on data in clmd->clothObject. */ - - if (clmd) + if(clmd->clothObject) { if(clmd->sim_parms.cache) - { - last_search = search = clmd->sim_parms.cache; + { + lastsearch = search = clmd->sim_parms.cache; + while(search) { - LinkNode *next= search->next; - frame = search->link; - - // free part of cache, but not preroll cache and first framer - if((clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_FREE_PART) - && (frame->time > newtime)) // do not delete the first frame + frame = (Frame *)search->link; + + if(frame->time >= newtime) { - MEM_freeN(frame->verts); - // MEM_freeN(frame->springs); - MEM_freeN(frame); + if(frame->verts) + { + MEM_freeN(frame->verts); + } + MEM_freeN(frame); + + lastsearch->next = search->next; MEM_freeN(search); - last_search->next = next; - } - else if(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_FREE_ALL) // free COMPLETE cache - { - MEM_freeN(frame->verts); - // MEM_freeN(frame->springs); - MEM_freeN(frame); + search = lastsearch->next; + lastsearch->next = NULL; } else - last_search = search; - search = next; + { + lastsearch = search; + search = search->next; + } } - - if(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_FREE_ALL) + + if(time <= 1.0) { - BLI_linklist_free(clmd->sim_parms.cache,NULL); clmd->sim_parms.cache = NULL; } + + if(time <= 2.0) + clmd->sim_parms.preroll = 0; } } - - /* clear flags */ - clmd->sim_parms.flags &= ~CSIMSETT_FLAG_CCACHE_FREE_ALL; - clmd->sim_parms.flags &= ~CSIMSETT_FLAG_CCACHE_FREE_PART; - } @@ -656,25 +624,44 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, // only be active during a specific period: // that's "first frame" and "last frame" on GUI - if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) { - if(current_time < clmd->sim_parms.firstframe) - return; - else if(current_time > clmd->sim_parms.lastframe) + if(clmd->clothObject) { - int frametime = cloth_cache_last_frame(clmd); - if(cloth_cache_search_frame(clmd, frametime)) + if(clmd->sim_parms.cache) { - cloth_cache_get_frame(clmd, frametime); - cloth_to_object (ob, clmd, vertexCos, numverts); + if(current_time < clmd->sim_parms.firstframe) + { + int frametime = cloth_cache_first_frame(clmd); + if(cloth_cache_search_frame(clmd, frametime)) + { + cloth_cache_get_frame(clmd, frametime); + cloth_to_object (ob, clmd, vertexCos, numverts); + } + return; + } + else if(current_time > clmd->sim_parms.lastframe) + { + int frametime = cloth_cache_last_frame(clmd); + if(cloth_cache_search_frame(clmd, frametime)) + { + cloth_cache_get_frame(clmd, frametime); + cloth_to_object (ob, clmd, vertexCos, numverts); + } + return; + } + else if(ABS(deltaTime) >= 2.0f ) // no timewarps allowed + { + if(cloth_cache_search_frame(clmd, framenr)) + { + cloth_cache_get_frame(clmd, framenr); + cloth_to_object (ob, clmd, vertexCos, numverts); + } + clmd->sim_parms.sim_time = current_time; + return; + } } - return; - } - else if(ABS(deltaTime) >= 2.0f ) // no timewarps allowed - { - if(!cloth_cache_search_frame(clmd, framenr)) - return; + } } @@ -822,7 +809,6 @@ void cloth_free_modifier (ClothModifierData *clmd) if(!(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_PROTECT)) { // free our frame cache, TODO: but get to first position before - clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_ALL; cloth_cache_free(clmd, 0); if (cloth) @@ -838,14 +824,14 @@ void cloth_free_modifier (ClothModifierData *clmd) MEM_freeN (cloth->verts); cloth->verts = NULL; - cloth->numverts = -1; + cloth->numverts = 0; // Free the springs. if (cloth->springs != NULL) MEM_freeN (cloth->springs); cloth->springs = NULL; - cloth->numsprings = -1; + cloth->numsprings = 0; // free BVH collision tree if(cloth->tree) @@ -1242,17 +1228,17 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d VECCOPY(verts->impulse, tnull); } - /* apply / set vertex groups */ + // apply / set vertex groups if (clmd->sim_parms.vgroup_mass > 0) cloth_apply_vgroup (clmd, dm, clmd->sim_parms.vgroup_mass); - /* init our solver */ + // init our solver if (solvers [clmd->sim_parms.solver_type].init) solvers [clmd->sim_parms.solver_type].init (ob, clmd); clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); - // cloth_cache_set_frame(clmd, 1); + cloth_cache_set_frame(clmd, 1); } return 1; @@ -1392,7 +1378,7 @@ int cloth_build_springs(Cloth *cloth, DerivedMesh *dm) springs[temp_index].restlen = sqrt(INPR(temp, temp)); springs[temp_index].type = SHEAR; - BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index])); + BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index])); BLI_linklist_append(&edgelist[springs[temp_index].kl], &(springs[temp_index])); shear_springs++; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 37e232a9f97..3faf298db0e 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2160,8 +2160,7 @@ void do_object_panels(unsigned short event) CFRA= 1; update_for_newframe_muted(); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_PART; - cloth_cache_free(clmd, 1); + cloth_cache_free(clmd, 2); allqueue(REDRAWBUTSOBJECT, 0); allqueue(REDRAWVIEW3D, 0); } @@ -2172,11 +2171,8 @@ void do_object_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - clmd->sim_parms.flags |= CSIMSETT_FLAG_CCACHE_FREE_PART; - cloth_cache_free(clmd, G.scene->r.cfra); - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + cloth_cache_free(clmd, MAX2(2.0,G.scene->r.cfra+1.0)); allqueue(REDRAWBUTSOBJECT, 0); - allqueue(REDRAWVIEW3D, 0); } } break; @@ -3256,6 +3252,8 @@ static void object_panel_cloth_II(Object *ob) uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache"); if(length>1) // B_CLOTH_CHANGEPREROLL uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); + else + uiDefBut(block, LABEL, 0, " ", 10,80,145,20, NULL, 0.0, 0, 0, 0, ""); } else { From 265572744e00a9b746b01a57aac950298933623a Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 3 Oct 2007 22:43:26 +0000 Subject: [PATCH 024/101] New: Collision detection for inter-timestep-collisions for triangle-point contacts. No response yet though. --- source/blender/blenkernel/BKE_cloth.h | 24 +- source/blender/blenkernel/intern/collision.c | 506 +++++++++++-------- 2 files changed, 329 insertions(+), 201 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 8750fe3878c..dc8d33804ee 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -235,9 +235,31 @@ typedef struct CollPair 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; + unsigned int ap1, ap2, ap3, bp1, bp2, bp3, bp4; + unsigned int pointsb[4]; } CollPair; +/* used for collisions in collision.c */ +typedef struct EdgeCollPair +{ + unsigned int p11, p12, p21, p22; + float normal[3]; + float vector[3]; + float time; + int lastsign; + float pa[3], pb[3]; // collision point p1 on face1, p2 on face2 +} EdgeCollPair; + +/* used for collisions in collision.c */ +typedef struct FaceCollPair +{ + unsigned int p11, p12, p13, p21; + float normal[3]; + float vector[3]; + float time; + int lastsign; + float pa[3], pb[3]; // collision point p1 on face1, p2 on face2 +} FaceCollPair; #endif diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 20c1548e14b..6100ff143d5 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -71,123 +71,254 @@ #include "Bullet-C-Api.h" -#define DERANDOMIZE 1 +/** + * gsl_poly_solve_cubic - + * + * copied from SOLVE_CUBIC.C --> GSL + */ +#define mySWAP(a,b) do { float tmp = b ; b = a ; a = tmp ; } while(0) -enum TRIANGLE_MARK -{ - TM_MV = 1, - TM_ME = 2, - TM_V1 = 4, - TM_V2 = 8, - TM_V3 = 16, - TM_E1 = 32, - TM_E2 = 64, - TM_E3 = 128 -}; - -DO_INLINE int hasTriangleMark(unsigned char mark, unsigned char bit) { return mark & bit; } -DO_INLINE void setTriangleMark(unsigned char *mark, unsigned char bit) { mark[0] |= bit; } -DO_INLINE void clearTriangleMark(unsigned char *mark, unsigned char bit) { mark[0] &= ~bit; } - - -void generateTriangleMarks() +int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float *x2) { - /* - unsigned int firstEdge = 0; + float q = (a * a - 3 * b); + float r = (2 * a * a * a - 9 * a * b + 27 * c); + + float Q = q / 9; + float R = r / 54; + + float Q3 = Q * Q * Q; + float R2 = R * R; + + float CR2 = 729 * r * r; + float CQ3 = 2916 * q * q * q; + + if (R == 0 && Q == 0) + { + *x0 = - a / 3 ; + *x1 = - a / 3 ; + *x2 = - a / 3 ; + return 3 ; + } + else if (CR2 == CQ3) + { + /* this test is actually R2 == Q3, written in a form suitable + for exact computation with integers */ + + /* Due to finite precision some float roots may be missed, and + considered to be a pair of complex roots z = x +/- epsilon i + close to the real axis. */ + + float sqrtQ = sqrtf (Q); + + if (R > 0) + { + *x0 = -2 * sqrtQ - a / 3; + *x1 = sqrtQ - a / 3; + *x2 = sqrtQ - a / 3; + } + else + { + *x0 = - sqrtQ - a / 3; + *x1 = - sqrtQ - a / 3; + *x2 = 2 * sqrtQ - a / 3; + } + return 3 ; + } + else if (CR2 < CQ3) /* equivalent to R2 < Q3 */ + { + float sqrtQ = sqrtf (Q); + float sqrtQ3 = sqrtQ * sqrtQ * sqrtQ; + float theta = acosf (R / sqrtQ3); + float norm = -2 * sqrtQ; + *x0 = norm * cosf (theta / 3) - a / 3; + *x1 = norm * cosf ((theta + 2.0 * M_PI) / 3) - a / 3; + *x2 = norm * cosf ((theta - 2.0 * M_PI) / 3) - a / 3; + + /* Sort *x0, *x1, *x2 into increasing order */ + + if (*x0 > *x1) + mySWAP(*x0, *x1) ; + + if (*x1 > *x2) + { + mySWAP(*x1, *x2) ; + + if (*x0 > *x1) + mySWAP(*x0, *x1) ; + } + + return 3; + } + else + { + float sgnR = (R >= 0 ? 1 : -1); + float A = -sgnR * powf (fabs (R) + sqrtf (R2 - Q3), 1.0/3.0); + float B = Q / A ; + *x0 = A + B - a / 3; + return 1; + } +} + + +/** + * gsl_poly_solve_quadratic + * + * copied from GSL + */ +int gsl_poly_solve_quadratic (float a, float b, float c, float *x0, float *x1) +{ + float disc = b * b - 4 * a * c; + + if (disc > 0) + { + if (b == 0) + { + float r = fabs (0.5 * sqrtf (disc) / a); + *x0 = -r; + *x1 = r; + } + else + { + float sgnb = (b > 0 ? 1 : -1); + float temp = -0.5 * (b + sgnb * sqrtf (disc)); + float r1 = temp / a ; + float r2 = c / temp ; + + if (r1 < r2) + { + *x0 = r1 ; + *x1 = r2 ; + } + else + { + *x0 = r2 ; + *x1 = r1 ; + } + } + return 2; + } + else if (disc == 0) + { + *x0 = -0.5 * b / a ; + *x1 = -0.5 * b / a ; + return 2 ; + } + else + { + return 0; + } +} + + + +/* + * See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation" + * page 4, left column + */ + +int cloth_get_collision_time(float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3]) +{ + int num_sols = 0; - // 1. Initialization - memset(m_triangleMarks, 0, sizeof(unsigned char) * m_triangleCount); + float g = -a[2] * c[1] * e[0] + a[1] * c[2] * e[0] + + a[2] * c[0] * e[1] - a[0] * c[2] * e[1] - + a[1] * c[0] * e[2] + a[0] * c[1] * e[2]; - // 2. The Marking Process - - // 2.1 Randomly mark triangles for covering vertices. - for (unsigned int v = 0; v < m_vertexCount; ++v) + float h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] + + a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] + + a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] + + b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] - + a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] - + a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2]; + + float i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] + + b[2] * d[0] * e[1] - b[0] * d[2] * e[1] - + b[1] * d[0] * e[2] + b[0] * d[1] * e[2] - + b[2] * c[1] * f[0] + b[1] * c[2] * f[0] - + a[2] * d[1] * f[0] + a[1] * d[2] * f[0] + + b[2] * c[0] * f[1] - b[0] * c[2] * f[1] + + a[2] * d[0] * f[1] - a[0] * d[2] * f[1] - + b[1] * c[0] * f[2] + b[0] * c[1] * f[2] - + a[1] * d[0] * f[2] + a[0] * d[1] * f[2]; + + float j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] + + b[2] * d[0] * f[1] - b[0] * d[2] * f[1] - + b[1] * d[0] * f[2] + b[0] * d[1] * f[2]; + + // Solve cubic equation to determine times t1, t2, t3, when the collision will occur. + if(ABS(j) > ALMOST_ZERO) { - if (vertexCover(v) == 0) + i /= j; + h /= j; + g /= j; + + num_sols = gsl_poly_solve_cubic(i, h, g, &solution[0], &solution[1], &solution[2]); + } + else if(ABS(i) > ALMOST_ZERO) + { + num_sols = gsl_poly_solve_quadratic(i, h, g, &solution[0], &solution[1]); + solution[2] = -1.0; + } + else if(ABS(h) > ALMOST_ZERO) + { + solution[0] = -g / h; + solution[1] = solution[2] = -1.0; + num_sols = 1; + } + else if(ABS(g) > ALMOST_ZERO) + { + solution[0] = 0; + solution[1] = solution[2] = -1.0; + num_sols = 1; + } + + // Discard negative solutions + if ((num_sols >= 1) && (solution[0] < 0)) + { + --num_sols; + solution[0] = solution[num_sols]; + } + if ((num_sols >= 2) && (solution[1] < 0)) + { + --num_sols; + solution[1] = solution[num_sols]; + } + if ((num_sols == 3) && (solution[2] < 0)) + { + --num_sols; + } + + // Sort + if (num_sols == 2) + { + if (solution[0] > solution[1]) + { + double tmp = solution[0]; + solution[0] = solution[1]; + solution[1] = tmp; + } + } + else if (num_sols == 3) { - // Randomly select an edge whose first triangle we're going to flag. + // Bubblesort + if (solution[0] > solution[1]) { + double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp; + } + if (solution[1] > solution[2]) { + double tmp = solution[1]; solution[1] = solution[2]; solution[2] = tmp; + } + if (solution[0] > solution[1]) { + double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp; + } + } -#ifndef DERANDOMIZE - firstEdge = (unsigned int)((float)(random() & 0x7FFFFFFF) / - (float)(0x80000000) * - (float)(m_vertices[v].getEdgeCount())); -#endif - for (unsigned int ofs = 0; ofs < m_vertices[v].getEdgeCount(); ++ofs) - { - unsigned int edgeIdx = (firstEdge + ofs) % m_vertices[v].getEdgeCount(); - if (m_edges[m_vertices[v].getEdge(edgeIdx)].getTriangleCount()) - setTriangleMark(m_triangleMarks[m_edges[m_vertices[v].getEdge(edgeIdx)].getTriangle(0)], TM_MV); -} -} -} - */ - /* If the Cloth is malformed (vertices without adjacent triangles) there might still be uncovered vertices. (Bad luck.) */ - /* - // 2.2 Randomly mark triangles for covering edges. - for (unsigned int e = 0; e < m_edgeCount; ++e) - { - if (m_edges[e].getTriangleCount() && (edgeCover(e) == 0)) - { -#ifndef DERANDOMIZE - setTriangleMark(m_triangleMarks[m_edges[e].getTriangle(static_cast((float)(random() & 0x7FFFFFFF) / - (float)(0x80000000) * - (float)(m_edges[e].getTriangleCount())))], TM_ME); -#else - setTriangleMark(m_triangleMarks[m_edges[e].getTriangle(0)], TM_ME); -#endif -} -} - - - // 3. The Unmarking Process - for (unsigned int t = 0; (t < m_triangleCount); ++t) - { - bool overCoveredVertices = true; - bool overCoveredEdges = true; - for (unsigned char i = 0; (i < 3) && (overCoveredVertices || overCoveredEdges); ++i) - { - - if (vertexCover(m_triangles[t].getVertex(i)) == 1) - overCoveredVertices = false; - if (edgeCover(m_triangles[t].getEdge(i)) == 1) - overCoveredEdges = false; - - assert(vertexCover(m_triangles[t].getVertex(i)) > 0); - assert(edgeCover(m_triangles[t].getEdge(i)) > 0); -} - if (overCoveredVertices) - clearTriangleMark(m_triangleMarks[t], TM_MV); - if (overCoveredEdges) - clearTriangleMark(m_triangleMarks[t], TM_ME); -} - - - // 4. The Bit Masking Process - vector vertexAssigned(m_vertexCount, false); - vector edgeAssigned(m_edgeCount, false); - for (unsigned int t = 0; (t < m_triangleCount); ++t) - { - for (unsigned char i = 0; i < 3; ++i) - { - if (!vertexAssigned[m_triangles[t].getVertex(i)]) - { - vertexAssigned[m_triangles[t].getVertex(i)] = true; - setTriangleMark(m_triangleMarks[t], 1 << (2 + i)); -} - if (!edgeAssigned[m_triangles[t].getEdge(i)]) - { - edgeAssigned[m_triangles[t].getEdge(i)] = true; - setTriangleMark(m_triangleMarks[t], 1 << (5 + i)); -} -} -} - */ + return num_sols; } // w3 is not perfect -void bvh_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) +void cloth_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) { double tempV1[3], tempV2[3], tempV4[3]; double a,b,c,d,e,f; @@ -231,6 +362,8 @@ DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], floa } + +// unused in the moment, has some bug in DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal[3], double normalVelocity, double frictionConstant, double delta_V_n) { @@ -241,8 +374,7 @@ DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal VecMulf(to, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); } - -int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) +int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) { unsigned int i = 0; int result = 0; @@ -263,17 +395,17 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) collpair = search->link; // compute barycentric coordinates for both collision points - bvh_compute_barycentric(collpair->pa, + cloth_compute_barycentric(collpair->pa, cloth1->verts[collpair->ap1].txold, - cloth1->verts[collpair->ap2].txold, - cloth1->verts[collpair->ap3].txold, - &w1, &w2, &w3); + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3); - bvh_compute_barycentric(collpair->pb, + cloth_compute_barycentric(collpair->pb, cloth2->verts[collpair->bp1].txold, - cloth2->verts[collpair->bp2].txold, - cloth2->verts[collpair->bp3].txold, - &u1, &u2, &u3); + cloth2->verts[collpair->bp2].txold, + cloth2->verts[collpair->bp3].txold, + &u1, &u2, &u3); // Calculate relative "velocity". interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3); @@ -378,7 +510,7 @@ int collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) return result; } -void bvh_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) { CollPair *collpair = NULL; Cloth *cloth1=NULL, *cloth2=NULL; @@ -468,8 +600,7 @@ void bvh_collision_response_static(ClothModifierData *clmd, ClothModifierData *c { // calc distance + normal distance = plNearestPoints( - verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, - collpair->pa, collpair->pb, collpair->vector); + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, collpair->pa,collpair->pb,collpair->vector); if (distance <= (epsilon + ALMOST_ZERO)) { @@ -496,20 +627,20 @@ void bvh_collision_response_static(ClothModifierData *clmd, ClothModifierData *c } } -void bvh_collision_response_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) { - CollPair *collpair = NULL; + CollPair collpair; Cloth *cloth1=NULL, *cloth2=NULL; MFace *face1=NULL, *face2=NULL; ClothVertex *verts1=NULL, *verts2=NULL; double distance = 0; float epsilon = clmd->coll_parms.epsilon; - unsigned int i = 0; + unsigned int i = 0, j = 0, k = 0; + int numsolutions = 0; + float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; - for(i = 0; i < 4; i++) - { - collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); - + for(i = 0; i < 2; i++) + { cloth1 = clmd->clothObject; cloth2 = coll_clmd->clothObject; @@ -522,59 +653,28 @@ void bvh_collision_response_moving(ClothModifierData *clmd, ClothModifierData *c // check all possible pairs of triangles if(i == 0) { - collpair->ap1 = face1->v1; - collpair->ap2 = face1->v2; - collpair->ap3 = face1->v3; - - collpair->bp1 = face2->v1; - collpair->bp2 = face2->v2; - collpair->bp3 = face2->v3; + collpair.ap1 = face1->v1; + collpair.ap2 = face1->v2; + collpair.ap3 = face1->v3; + collpair.pointsb[0] = face2->v1; + collpair.pointsb[1] = face2->v2; + collpair.pointsb[2] = face2->v3; + collpair.pointsb[3] = face2->v4; } if(i == 1) { if(face1->v4) { - collpair->ap1 = face1->v3; - collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; + collpair.ap1 = face1->v3; + collpair.ap2 = face1->v4; + collpair.ap3 = face1->v1; - collpair->bp1 = face2->v1; - collpair->bp2 = face2->v2; - collpair->bp3 = face2->v3; - } - else - i++; - } - - if(i == 2) - { - if(face2->v4) - { - collpair->ap1 = face1->v1; - collpair->ap2 = face1->v2; - collpair->ap3 = face1->v3; - - collpair->bp1 = face2->v3; - collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; - } - else - i+=2; - } - - if(i == 3) - { - if((face1->v4)&&(face2->v4)) - { - collpair->ap1 = face1->v3; - collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; - - collpair->bp1 = face2->v3; - collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; + collpair.pointsb[0] = face2->v1; + collpair.pointsb[1] = face2->v2; + collpair.pointsb[2] = face2->v3; + collpair.pointsb[3] = face2->v4; } else i++; @@ -582,34 +682,40 @@ void bvh_collision_response_moving(ClothModifierData *clmd, ClothModifierData *c // calc SIPcode (?) - if(i < 4) + if(i < 2) { - // calc distance + normal - distance = plNearestPoints( - verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, - collpair->pa, collpair->pb, collpair->vector); + VECSUB(a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold); + VECSUB(b, verts1[collpair.ap2].v, verts1[collpair.ap1].v); + VECSUB(c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold); + VECSUB(d, verts1[collpair.ap3].v, verts1[collpair.ap1].v); + + for(j = 0; j < 4; j++) + { + if((j==3) && !(face2->v4)) + break; + + VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold); + VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v); + + numsolutions = cloth_get_collision_time(a, b, c, d, e, f, solution); + + for (k = 0; k < numsolutions; k++) + { + if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) + { + float out_collisionTime = solution[k]; + + // TODO: check for collisions + + // TODO: put into collision list + + printf("Moving found!\n"); + } + } + + // TODO: check borders for collisions + } - if (distance <= (epsilon + ALMOST_ZERO)) - { - // printf("dist: %f\n", (float)distance); - - // collpair->face1 = tree1->tri_index; - // collpair->face2 = tree2->tri_index; - - VECCOPY(collpair->normal, collpair->vector); - Normalize(collpair->normal); - - collpair->distance = distance; - BLI_linklist_append(&clmd->coll_parms.collision_list, collpair); - } - else - { - MEM_freeN(collpair); - } - } - else - { - MEM_freeN(collpair); } } } @@ -719,7 +825,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { BVH *coll_bvh = coll_clmd->clothObject->tree; - bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, bvh_collision_response_static); + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static); } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); @@ -745,7 +851,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) { if (coll_clmd->clothObject) - result += collision_static(clmd, coll_clmd); + result += cloth_collision_response_static(clmd, coll_clmd); else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); } @@ -855,7 +961,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { BVH *coll_bvh = coll_clmd->clothObject->tree; - bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, bvh_collision_response_moving); + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving_tris); } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); @@ -882,7 +988,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) { if (coll_clmd->clothObject) - result += collision_moving(clmd, coll_clmd); + result += cloth_collision_response_moving_tris(clmd, coll_clmd); else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); } From 626edd8de8c3ce237c0ece95f99fb56f1b90bbe8 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 4 Oct 2007 00:19:59 +0000 Subject: [PATCH 025/101] New: Collision detection for inter-timestep-collisions for edge-edge contacts. --- source/blender/blenkernel/intern/collision.c | 226 +++++++++++++++++-- 1 file changed, 202 insertions(+), 24 deletions(-) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 6100ff143d5..a89cd3dc4b9 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -627,6 +627,175 @@ void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clm } } +int cloth_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) +{ + Cloth *cloth1, *cloth2; + ClothVertex *verts1, *verts2; + float temp[3]; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + return 0; +} + +void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +{ + EdgeCollPair edgecollpair; + Cloth *cloth1=NULL, *cloth2=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL, *verts2=NULL; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0, j = 0, k = 0; + int numsolutions = 0; + float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + for( i = 0; i < 5; i++) + { + if(i == 0) + { + edgecollpair.p11 = face1->v1; + edgecollpair.p12 = face1->v2; + } + else if(i == 1) + { + edgecollpair.p11 = face1->v2; + edgecollpair.p12 = face1->v3; + } + else if(i == 2) + { + if(face1->v4) + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v4; + } + else + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v1; + i+=5; // get out of here! + } + } + else if(i == 3) + { + if(face1->v4) + { + edgecollpair.p11 = face1->v4; + edgecollpair.p12 = face1->v1; + } + else + continue; + } + else + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v1; + } + + + for( j = 0; j < 5; j++) + { + if(j == 0) + { + edgecollpair.p21 = face2->v1; + edgecollpair.p22 = face2->v2; + } + else if(j == 1) + { + edgecollpair.p21 = face2->v2; + edgecollpair.p22 = face2->v3; + } + else if(j == 2) + { + if(face2->v4) + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v4; + } + else + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v1; + } + } + else if(j == 3) + { + if(face2->v4) + { + edgecollpair.p21 = face2->v4; + edgecollpair.p22 = face2->v1; + } + else + continue; + } + else + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v1; + } + + + if(!cloth_are_edges_adjacent(clmd, coll_clmd, &edgecollpair)) + { + VECSUB(a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold); + VECSUB(b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v); + VECSUB(c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold); + VECSUB(d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v); + VECSUB(e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold); + VECSUB(f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v); + + numsolutions = cloth_get_collision_time(a, b, c, d, e, f, solution); + + for (k = 0; k < numsolutions; k++) + { + if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) + { + float out_collisionTime = solution[k]; + + // TODO: check for collisions + + // TODO: put into collision list + + printf("Moving edge found!\n"); + } + } + } + } + } + + + +} + void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) { CollPair collpair; @@ -690,36 +859,45 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col VECSUB(d, verts1[collpair.ap3].v, verts1[collpair.ap1].v); for(j = 0; j < 4; j++) - { - if((j==3) && !(face2->v4)) - break; - - VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold); - VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v); - - numsolutions = cloth_get_collision_time(a, b, c, d, e, f, solution); - - for (k = 0; k < numsolutions; k++) - { - if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) - { - float out_collisionTime = solution[k]; - - // TODO: check for collisions - - // TODO: put into collision list - - printf("Moving found!\n"); - } + { + if((j==3) && !(face2->v4)) + break; + + VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold); + VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v); + + numsolutions = cloth_get_collision_time(a, b, c, d, e, f, solution); + + for (k = 0; k < numsolutions; k++) + { + if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) + { + float out_collisionTime = solution[k]; + + // TODO: check for collisions + + // TODO: put into collision list + + printf("Moving found!\n"); } - - // TODO: check borders for collisions } + + // TODO: check borders for collisions + } } } } +void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +{ + // TODO: check for adjacent + cloth_collision_moving_edges(clmd, coll_clmd, tree1, tree2); + + cloth_collision_moving_tris(clmd, coll_clmd, tree1, tree2); + // cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); +} + // move collision objects forward in time and update static bounding boxes void cloth_update_collision_objects(float step) { @@ -961,7 +1139,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { BVH *coll_bvh = coll_clmd->clothObject->tree; - bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving_tris); + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving); } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); From e59bf9fa6f54700f7ba8ef41da5d93b6f177c6e5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 10 Oct 2007 09:33:34 +0000 Subject: [PATCH 026/101] initial splitting of egde/face response --- source/blender/blenkernel/intern/collision.c | 98 +++++++++++--------- 1 file changed, 54 insertions(+), 44 deletions(-) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 5e90dd581d8..c3dbc572b4e 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -510,6 +510,17 @@ int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData * return result; } +int cloth_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + +} + + +int cloth_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + +} + void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) { CollPair *collpair = NULL; @@ -783,15 +794,14 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co // TODO: check for collisions - // TODO: put into collision list + // TODO: put into (edge) collision list printf("Moving edge found!\n"); } } } } - } - + } } void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) @@ -874,7 +884,7 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col // TODO: check for collisions - // TODO: put into collision list + // TODO: put into (point-face) collision list printf("Moving found!\n"); } @@ -893,7 +903,7 @@ void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clm cloth_collision_moving_edges(clmd, coll_clmd, tree1, tree2); cloth_collision_moving_tris(clmd, coll_clmd, tree1, tree2); - // cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); + cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); } // move collision objects forward in time and update static bounding boxes @@ -1010,7 +1020,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) // process all collisions (calculate impulses, TODO: also repulses if distance too short) result = 1; - for(j = 0; j < 50; j++) // 50 is just a value that ensures convergence + for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence { result = 0; @@ -1143,50 +1153,50 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); } } - /* + // process all collisions (calculate impulses, TODO: also repulses if distance too short) result = 1; - for(j = 0; j < 50; j++) // 50 is just a value that ensures convergence + for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence { - result = 0; - + result = 0; + // handle all collision objects - for (base = G.scene->base.first; base; base = base->next) - { - - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - - if (!coll_clmd) - continue; - - // if collision object go on - if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) - { - if (coll_clmd->clothObject) - result += cloth_collision_response_moving_tris(clmd, coll_clmd); - else - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } - } + for (base = G.scene->base.first; base; base = base->next) + { - // apply impulses in parallel - ic=0; - for(i = 0; i < numverts; i++) - { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if(verts[i].impulse_count) - { - VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); - VECCOPY(verts[i].impulse, tnull); - verts[i].impulse_count = 0; + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + + if (!coll_clmd) + continue; - ic++; - ret++; - } - } - } - */ + // if collision object go on + if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject) + result += cloth_collision_response_moving_tris(clmd, coll_clmd); + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } + } + } + // verts come from clmd for(i = 0; i < numverts; i++) From 5b019072a8fb486278e653761b1c2864549615c9 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 18 Oct 2007 23:12:30 +0000 Subject: [PATCH 027/101] Springs are in a dynamic list now, New function cloth_add_spring() for easier access to spring handling, cleared up names, functions, code. Collisions can be enabled/disabled for cloth objects now --- source/blender/blenkernel/BKE_cloth.h | 147 +- source/blender/blenkernel/intern/cloth.c | 1255 ++++++++---------- source/blender/blenkernel/intern/collision.c | 17 +- source/blender/blenkernel/intern/implicit.c | 213 +-- source/blender/blenkernel/intern/kdop.c | 2 +- source/blender/blenkernel/intern/modifier.c | 9 +- source/blender/makesdna/DNA_cloth_types.h | 59 +- source/blender/src/buttons_object.c | 26 +- 8 files changed, 840 insertions(+), 888 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index dc8d33804ee..692692dbf5a 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -1,6 +1,6 @@ /** - * BKE_cloth.h - * + * BKE_cloth.h + * * $Id: BKE_cloth.h,v 1.1 2007/08/01 02:07:27 daniel Exp $ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** @@ -47,7 +47,7 @@ struct DerivedMesh; // this is needed for inlining behaviour #ifndef _WIN32 -#define LINUX +#define LINUX #define DO_INLINE inline #else #define DO_INLINE @@ -57,17 +57,12 @@ struct DerivedMesh; /* goal defines */ -#define SOFTGOALSNAP 0.999f +#define SOFTGOALSNAP 0.999f /* This is approximately the smallest number that can be * represented by a float, given its precision. */ #define ALMOST_ZERO 0.000001 -/* Bits to or into the ClothVertex.flags. */ -#define CVERT_FLAG_PINNED 1 -#define CVERT_FLAG_COLLISION 2 - - // 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);} @@ -84,56 +79,70 @@ struct DerivedMesh; /* SIMULATION FLAGS: goal flags,.. */ /* These are the bits used in SimSettings.flags. */ -typedef enum +typedef enum { - CSIMSETT_FLAG_RESET = (1 << 1), // The CM object requires a reinitializaiton. - CSIMSETT_FLAG_COLLOBJ = (1 << 2), // object is only collision object, no cloth simulation is done - CSIMSETT_FLAG_GOAL = (1 << 3), // we have goals enabled - CSIMSETT_FLAG_TEARING_ENABLED = (1 << 4), // true if tearing is enabled - CSIMSETT_FLAG_CCACHE_PROTECT = (1 << 5), // true if tearing is enabled -} CSIMSETT_FLAGS; - -/* Spring types as defined in the paper.*/ -typedef enum -{ - STRUCTURAL = 0, - SHEAR, - BENDING, -} springType; + CLOTH_SIMSETTINGS_FLAG_RESET = ( 1 << 1 ), // The CM object requires a reinitializaiton. + CLOTH_SIMSETTINGS_FLAG_COLLOBJ = ( 1 << 2 ), // object is only collision object, no cloth simulation is done + CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ), // we have goals enabled + CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ), // true if tearing is enabled + CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ), // true if tearing is enabled +} CLOTH_SIMSETTINGS_FLAGS; /* SPRING FLAGS */ -typedef enum +typedef enum { - CSPRING_FLAG_DEACTIVATE = (1 << 1), - CSPRING_FLAG_NEEDED = (1 << 2), // springs has values to be applied -} CSPRINGS_FLAGS; + CLOTH_COLLISIONSETTINGS_FLAG_ENABLED = ( 1 << 1 ), +} CLOTH_COLLISIONSETTINGS_FLAGS; + +/* Spring types as defined in the paper.*/ +typedef enum +{ + CLOTH_SPRING_TYPE_STRUCTURAL = 0, + CLOTH_SPRING_TYPE_SHEAR, + CLOTH_SPRING_TYPE_BENDING, +} CLOTH_SPRING_TYPES; + +/* SPRING FLAGS */ +typedef enum +{ + CLOTH_SPRING_FLAG_DEACTIVATE = ( 1 << 1 ), + CLOTH_SPRING_FLAG_NEEDED = ( 1 << 2 ), // springs has values to be applied +} CLOTH_SPRINGS_FLAGS; + +/* Bits to or into the ClothVertex.flags. */ +#define CVERT_FLAG_PINNED 1 +#define CVERT_FLAG_COLLISION 2 + // needed for buttons_object.c -void cloth_cache_free(ClothModifierData *clmd, float time); -void cloth_free_modifier (ClothModifierData *clmd); +void cloth_cache_free ( ClothModifierData *clmd, float time ); +void cloth_free_modifier ( ClothModifierData *clmd ); // needed for cloth.c -void implicit_set_positions (ClothModifierData *clmd); +void implicit_set_positions ( ClothModifierData *clmd ); // from cloth.c, needed for modifier.c -void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numverts); +void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float ( *vertexCos ) [3], int numverts ); // used in collision.c -typedef struct Tree { +typedef struct Tree +{ struct Tree *nodes[4]; // 4 children --> quad-tree struct Tree *parent; - struct Tree *nextLeaf; + struct Tree *nextLeaf; struct Tree *prevLeaf; float bv[26]; // Bounding volume of all nodes / we have 7 axes on a 14-DOP unsigned int tri_index; // this saves the index of the face int count_nodes; // how many nodes are used int traversed; // how many nodes already traversed until this level? int isleaf; -} Tree; +} +Tree; typedef struct Tree TreeNode; -typedef struct BVH{ +typedef struct BVH +{ unsigned int numfaces; unsigned int numverts; ClothVertex *verts; // just a pointer to the original datastructure @@ -143,10 +152,11 @@ typedef struct BVH{ TreeNode *leaf_tree; /* Tail of the leaf linked list. */ TreeNode *leaf_root; /* Head of the leaf linked list. */ float epsilon; /* epslion is used for inflation of the k-dop */ - int flags; /* bvhFlags */ -} BVH; + int flags; /* bvhFlags */ +} +BVH; -typedef void (*CM_COLLISION_RESPONSE) (ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2); +typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 ); ///////////////////////////////////////////////// @@ -154,8 +164,8 @@ typedef void (*CM_COLLISION_RESPONSE) (ClothModifierData *clmd, ClothModifierDat //////////////////////////////////////////////// // needed for implicit.c -void bvh_collision_response(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2); -int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt); +void bvh_collision_response ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 ); +int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ); //////////////////////////////////////////////// @@ -165,12 +175,13 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt); //////////////////////////////////////////////// // needed for cloth.c -void bvh_free(BVH * bvh); -BVH *bvh_build (ClothModifierData *clmd, float epsilon); +void bvh_free ( BVH * bvh ); +BVH *bvh_build ( ClothModifierData *clmd, float epsilon ); +LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr ); // needed for collision.c -int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response); -void bvh_update(ClothModifierData * clmd, BVH * bvh, int moving); +int bvh_traverse ( ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response ); +void bvh_update ( ClothModifierData * clmd, BVH * bvh, int moving ); //////////////////////////////////////////////// @@ -179,41 +190,43 @@ void bvh_update(ClothModifierData * clmd, BVH * bvh, int moving); ///////////////////////////////////////////////// // cloth.c //////////////////////////////////////////////// -void cloth_free_modifier (ClothModifierData *clmd); -void cloth_init (ClothModifierData *clmd); -void cloth_deform_verts(struct Object *ob, float framenr, float (*vertexCos)[3], int numVerts, void *derivedData, ClothModifierData *clmd); -void cloth_update_normals (ClothVertex *verts, int nVerts, MFace *face, int totface); +void cloth_free_modifier ( ClothModifierData *clmd ); +void cloth_init ( ClothModifierData *clmd ); +void cloth_deform_verts ( struct Object *ob, float framenr, float ( *vertexCos ) [3], int numVerts, void *derivedData, ClothModifierData *clmd ); +void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int totface ); //////////////////////////////////////////////// /* Typedefs for function pointers we need for solvers and collision detection. */ -typedef void (*CM_COLLISION_SELF) (ClothModifierData *clmd, int step); -typedef void (*CM_COLLISION_OBJ) (ClothModifierData *clmd, int step, CM_COLLISION_RESPONSE collision_response); +typedef void ( *CM_COLLISION_SELF ) ( ClothModifierData *clmd, int step ); +typedef void ( *CM_COLLISION_OBJ ) ( ClothModifierData *clmd, int step, CM_COLLISION_RESPONSE collision_response ); /* This enum provides the IDs for our solvers. */ // only one available in the moment typedef enum { - CM_IMPLICIT = 0, + CM_IMPLICIT = 0, } CM_SOLVER_ID; /* This structure defines how to call the solver. */ -typedef struct { +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; + int ( *init ) ( Object *ob, ClothModifierData *clmd ); + int ( *solver ) ( Object *ob, float framenr, ClothModifierData *clmd, ListBase *effectors ); + int ( *free ) ( ClothModifierData *clmd ); +} +CM_SOLVER_DEF; /* new C implicit simulator */ -int implicit_init (Object *ob, ClothModifierData *clmd); -int implicit_free (ClothModifierData *clmd); -int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors); +int implicit_init ( Object *ob, ClothModifierData *clmd ); +int implicit_free ( ClothModifierData *clmd ); +int implicit_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors ); /* used for caching in implicit.c */ typedef struct Frame @@ -222,7 +235,8 @@ typedef struct Frame ClothSpring *springs; unsigned int numverts, numsprings; float time; /* we need float since we want to support sub-frames */ -} Frame; +} +Frame; /* used for collisions in collision.c */ typedef struct CollPair @@ -230,14 +244,15 @@ typedef struct CollPair unsigned int face1; // cloth face unsigned int face2; // object face double distance; // magnitude of vector - float normal[3]; + 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; +} +CollPair; /* used for collisions in collision.c */ typedef struct EdgeCollPair @@ -248,7 +263,8 @@ typedef struct EdgeCollPair float time; int lastsign; float pa[3], pb[3]; // collision point p1 on face1, p2 on face2 -} EdgeCollPair; +} +EdgeCollPair; /* used for collisions in collision.c */ typedef struct FaceCollPair @@ -259,7 +275,8 @@ typedef struct FaceCollPair float time; int lastsign; float pa[3], pb[3]; // collision point p1 on face1, p2 on face2 -} FaceCollPair; +} +FaceCollPair; #endif diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index e86d1c50b69..eb7454ccd42 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -1,5 +1,5 @@ -/* cloth.c -* +/* cloth.c +* * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * @@ -41,7 +41,7 @@ #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" -#include "DNA_cloth_types.h" +#include "DNA_cloth_types.h" #include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -77,12 +77,10 @@ #include "mydevice.h" #ifdef _WIN32 -void tstart(void) +void tstart ( void ) +{} +void tend ( void ) { -} -void tend(void) -{ - } double tval() { @@ -92,19 +90,19 @@ double tval() #include static struct timeval _tstart, _tend; static struct timezone tz; -void tstart(void) +void tstart ( void ) { - gettimeofday(&_tstart, &tz); + gettimeofday ( &_tstart, &tz ); } -void tend(void) +void tend ( void ) { - gettimeofday(&_tend,&tz); + gettimeofday ( &_tend,&tz ); } double tval() { double t1, t2; - t1 = (double)_tstart.tv_sec + (double)_tstart.tv_usec/(1000*1000); - t2 = (double)_tend.tv_sec + (double)_tend.tv_usec/(1000*1000); + t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 ); + t2 = ( double ) _tend.tv_sec + ( double ) _tend.tv_usec/ ( 1000*1000 ); return t2-t1; } #endif @@ -112,20 +110,21 @@ double tval() /* Our available solvers. */ // 255 is the magic reserved number, so NEVER try to put 255 solvers in here! // 254 = MAX! -static CM_SOLVER_DEF solvers [] = { - { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free }, - // { "Implicit C++", CM_IMPLICITCPP, implicitcpp_init, implicitcpp_solver, implicitcpp_free }, -}; +static CM_SOLVER_DEF solvers [] = + { + { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free }, + // { "Implicit C++", CM_IMPLICITCPP, implicitcpp_init, implicitcpp_solver, implicitcpp_free }, + }; /* ********** cloth engine ******* */ /* Prototypes for internal functions. */ -static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3], unsigned int numverts); -static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm); -static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float (*vertexCos)[3], unsigned int numverts); -static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float (*vertexCos)[3], unsigned int numverts); -int cloth_build_springs(Cloth *cloth, DerivedMesh *dm); -static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup); +static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ); +static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); +static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ); +static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ); +int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ); +static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ); /****************************************************************************** @@ -137,9 +136,9 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v * cloth_init - creates a new cloth simulation. * * 1. create object -* 2. fill object with standard values or with the GUI settings if given +* 2. fill object with standard values or with the GUI settings if given */ -void cloth_init (ClothModifierData *clmd) +void cloth_init ( ClothModifierData *clmd ) { /* Initialize our new data structure to reasonable values. */ clmd->sim_parms.gravity [0] = 0.0; @@ -153,8 +152,8 @@ void cloth_init (ClothModifierData *clmd) clmd->sim_parms.mass = 1.0f; clmd->sim_parms.stepsPerFrame = 5; clmd->sim_parms.sim_time = 1.0; - clmd->sim_parms.flags = CSIMSETT_FLAG_RESET; - clmd->sim_parms.solver_type = 0; + clmd->sim_parms.flags = CLOTH_SIMSETTINGS_FLAG_RESET; + clmd->sim_parms.solver_type = 0; clmd->sim_parms.preroll = 0; clmd->sim_parms.maxspringlen = 10; clmd->sim_parms.firstframe = 1; @@ -163,7 +162,8 @@ void cloth_init (ClothModifierData *clmd) clmd->coll_parms.friction = 10.0; clmd->coll_parms.loop_count = 1; clmd->coll_parms.epsilon = 0.01f; - + clmd->coll_parms.flags = 0; + /* These defaults are copied from softbody.c's * softbody_calc_forces() function. */ @@ -181,17 +181,17 @@ void cloth_init (ClothModifierData *clmd) } // unused in the moment, cloth needs quads from mesh -DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) +DerivedMesh *CDDM_convert_to_triangle ( DerivedMesh *dm ) { DerivedMesh *result = NULL; int i; - int numverts = dm->getNumVerts(dm); - int numedges = dm->getNumEdges(dm); - int numfaces = dm->getNumFaces(dm); + int numverts = dm->getNumVerts ( dm ); + int numedges = dm->getNumEdges ( dm ); + int numfaces = dm->getNumFaces ( dm ); - MVert *mvert = CDDM_get_verts(dm); - MEdge *medge = CDDM_get_edges(dm); - MFace *mface = CDDM_get_faces(dm); + MVert *mvert = CDDM_get_verts ( dm ); + MEdge *medge = CDDM_get_edges ( dm ); + MFace *mface = CDDM_get_faces ( dm ); MVert *mvert2; MFace *mface2; @@ -203,36 +203,36 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) float vec1[3], vec2[3], vec3[3], vec4[3], vec5[3]; float mag1=0, mag2=0; - for(i = 0; i < numfaces; i++) + for ( i = 0; i < numfaces; i++ ) { - if(mface[i].v4) + if ( mface[i].v4 ) numquads++; else - numtris++; + numtris++; } - result = CDDM_from_template(dm, numverts, 0, numtris + 2*numquads); + result = CDDM_from_template ( dm, numverts, 0, numtris + 2*numquads ); - if(!result) + if ( !result ) return NULL; // do verts - mvert2 = CDDM_get_verts(result); - for(a=0; av1 = mface[a].v2; mf->v2 = mface[a].v3; @@ -260,9 +260,9 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) mf->v4 = 0; mf->flag |= ME_SMOOTH; - test_index_face(mf, NULL, 0, 3); + test_index_face ( mf, NULL, 0, 3 ); - if(mface[a].v4) + if ( mface[a].v4 ) { MFace *mf2; @@ -275,7 +275,7 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) *mf2 = *inMF; */ - if(random==1) + if ( random==1 ) { mf2->v1 = mface[a].v1; mf2->v2 = mface[a].v2; @@ -290,31 +290,31 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) mf2->v4 = 0; mf2->flag |= ME_SMOOTH; - test_index_face(mf2, NULL, 0, 3); + test_index_face ( mf2, NULL, 0, 3 ); } i++; } - CDDM_calc_edges(result); - CDDM_calc_normals(result); + CDDM_calc_edges ( result ); + CDDM_calc_normals ( result ); return result; } -DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) +DerivedMesh *CDDM_create_tearing ( ClothModifierData *clmd, DerivedMesh *dm ) { DerivedMesh *result = NULL; unsigned int i = 0, a = 0, j=0; - int numverts = dm->getNumVerts(dm); - int numedges = dm->getNumEdges(dm); - int numfaces = dm->getNumFaces(dm); + int numverts = dm->getNumVerts ( dm ); + int numedges = dm->getNumEdges ( dm ); + int numfaces = dm->getNumFaces ( dm ); - MVert *mvert = CDDM_get_verts(dm); - MEdge *medge = CDDM_get_edges(dm); - MFace *mface = CDDM_get_faces(dm); + MVert *mvert = CDDM_get_verts ( dm ); + MEdge *medge = CDDM_get_edges ( dm ); + MFace *mface = CDDM_get_faces ( dm ); MVert *mvert2; MFace *mface2; @@ -324,45 +324,45 @@ DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) Cloth *cloth = clmd->clothObject; ClothSpring *springs = cloth->springs; unsigned int numsprings = cloth->numsprings; - + // create spring tearing hash edgehash = BLI_edgehash_new(); - - for(i = 0; i < numsprings; i++) + + for ( i = 0; i < numsprings; i++ ) { - if((springs[i].flags & CSPRING_FLAG_DEACTIVATE) - &&(!BLI_edgehash_haskey(edgehash, springs[i].ij, springs[i].kl))) + if ( ( springs[i].flags & CLOTH_SPRING_FLAG_DEACTIVATE ) + && ( !BLI_edgehash_haskey ( edgehash, springs[i].ij, springs[i].kl ) ) ) { - BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL); - BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL); + BLI_edgehash_insert ( edgehash, springs[i].ij, springs[i].kl, NULL ); + BLI_edgehash_insert ( edgehash, springs[i].kl, springs[i].ij, NULL ); j++; } } - - // printf("found %d tears\n", j); - - result = CDDM_from_template(dm, numverts, 0, numfaces); - if(!result) + // printf("found %d tears\n", j); + + result = CDDM_from_template ( dm, numverts, 0, numfaces ); + + if ( !result ) return NULL; // do verts - mvert2 = CDDM_get_verts(result); - for(a=0; av1 = mface[a].v1; mf->v2 = mface[a].v2; mf->v3 = mface[a].v3; mf->v4 = mface[a].v4; - - test_index_face(mf, NULL, 0, 4); - + + test_index_face ( mf, NULL, 0, 4 ); + i++; } } - CDDM_lower_num_faces(result, i); - CDDM_calc_edges(result); - CDDM_calc_normals(result); - - BLI_edgehash_free(edgehash, NULL); + CDDM_lower_num_faces ( result, i ); + CDDM_calc_edges ( result ); + CDDM_calc_normals ( result ); + + BLI_edgehash_free ( edgehash, NULL ); return result; } -int cloth_cache_search_frame(ClothModifierData *clmd, float time) +int cloth_cache_search_frame ( ClothModifierData *clmd, float time ) { Frame *frame = NULL; - LinkNode *search = NULL; - - if(clmd->clothObject) + LinkNode *search = NULL; + + if ( clmd->clothObject ) { search = clmd->sim_parms.cache; - - while(search) + + while ( search ) { - frame = (Frame *)search->link; - - if(frame) + frame = ( Frame * ) search->link; + + if ( frame ) { - if(frame->time == time) + if ( frame->time == time ) return 1; } - + search = search->next; } } - + return 0; - + } -float cloth_cache_last_frame(ClothModifierData *clmd) +float cloth_cache_last_frame ( ClothModifierData *clmd ) { Frame *frame = NULL; - LinkNode *search = NULL; + LinkNode *search = NULL; float time = 0; - - if(clmd->clothObject) + + if ( clmd->clothObject ) { search = clmd->sim_parms.cache; - - while(search) + + while ( search ) { - frame = (Frame *)search->link; - - if(frame) + frame = ( Frame * ) search->link; + + if ( frame ) { - if(frame->time > time) + if ( frame->time > time ) time = frame->time; } } @@ -451,27 +451,27 @@ float cloth_cache_last_frame(ClothModifierData *clmd) return time; } -float cloth_cache_first_frame(ClothModifierData *clmd) +float cloth_cache_first_frame ( ClothModifierData *clmd ) { Frame *frame = NULL; - LinkNode *search = NULL; + LinkNode *search = NULL; float time = -1.0; - - if(clmd->clothObject) + + if ( clmd->clothObject ) { search = clmd->sim_parms.cache; - - while(search) + + while ( search ) { - frame = (Frame *)search->link; - - if(frame) + frame = ( Frame * ) search->link; + + if ( frame ) { - if(time < 0.0) + if ( time < 0.0 ) time = frame->time; else { - if(frame->time < time) + if ( frame->time < time ) time = frame->time; } } @@ -480,102 +480,102 @@ float cloth_cache_first_frame(ClothModifierData *clmd) return time; } -void cloth_cache_get_frame(ClothModifierData *clmd, float time) +void cloth_cache_get_frame ( ClothModifierData *clmd, float time ) { Frame *frame = NULL; LinkNode *search = NULL; - float newtime = time + clmd->sim_parms.preroll; - - if(clmd->clothObject) + float newtime = time + clmd->sim_parms.preroll; + + if ( clmd->clothObject ) { search = clmd->sim_parms.cache; - - while(search) + + while ( search ) { - frame = (Frame *)search->link; - - if(frame) + frame = ( Frame * ) search->link; + + if ( frame ) { - if(frame->time == newtime) + if ( frame->time == newtime ) { // something changed, free cache! - if(clmd->clothObject->numverts != frame->numverts) + if ( clmd->clothObject->numverts != frame->numverts ) { - cloth_cache_free(clmd, 0); - printf("clmd->clothObject->numverts != frame->numverts\n"); + cloth_cache_free ( clmd, 0 ); + printf ( "clmd->clothObject->numverts != frame->numverts\n" ); return; } - - memcpy(clmd->clothObject->verts, frame->verts, sizeof(ClothVertex)*frame->numverts); - implicit_set_positions(clmd); - + + memcpy ( clmd->clothObject->verts, frame->verts, sizeof ( ClothVertex ) *frame->numverts ); + implicit_set_positions ( clmd ); + return; } } - + search = search->next; } } } -void cloth_cache_set_frame(ClothModifierData *clmd, float time) +void cloth_cache_set_frame ( ClothModifierData *clmd, float time ) { Frame *frame = NULL; LinkNode *search = NULL; - - if(clmd->clothObject) + + if ( clmd->clothObject ) { - frame = (Frame *)MEM_callocN (sizeof (Frame), "cloth_cache_frame"); - - if(frame) + frame = ( Frame * ) MEM_callocN ( sizeof ( Frame ), "cloth_cache_frame" ); + + if ( frame ) { frame->time = time; frame->numverts = clmd->clothObject->numverts; - frame->verts = MEM_dupallocN(clmd->clothObject->verts); - - if(!frame->verts) + frame->verts = MEM_dupallocN ( clmd->clothObject->verts ); + + if ( !frame->verts ) { - MEM_freeN(frame); + MEM_freeN ( frame ); return; } - - BLI_linklist_append(&clmd->sim_parms.cache, frame); - + + BLI_linklist_append ( &clmd->sim_parms.cache, frame ); + } - } - + } + } // free cloth cache -void cloth_cache_free(ClothModifierData *clmd, float time) +void cloth_cache_free ( ClothModifierData *clmd, float time ) { Frame *frame = NULL; - LinkNode *search = NULL, *lastsearch = NULL; + LinkNode *search = NULL, *lastsearch = NULL; float newtime = time + clmd->sim_parms.preroll; - - if(time <= 2.0) + + if ( time <= 2.0 ) newtime = time; - if(clmd->clothObject) + if ( clmd->clothObject ) { - if(clmd->sim_parms.cache) - { + if ( clmd->sim_parms.cache ) + { lastsearch = search = clmd->sim_parms.cache; - - while(search) + + while ( search ) { - frame = (Frame *)search->link; - - if(frame->time >= newtime) + frame = ( Frame * ) search->link; + + if ( frame->time >= newtime ) { - if(frame->verts) + if ( frame->verts ) { - MEM_freeN(frame->verts); + MEM_freeN ( frame->verts ); } - MEM_freeN(frame); - + MEM_freeN ( frame ); + lastsearch->next = search->next; - MEM_freeN(search); + MEM_freeN ( search ); search = lastsearch->next; lastsearch->next = NULL; } @@ -585,13 +585,13 @@ void cloth_cache_free(ClothModifierData *clmd, float time) search = search->next; } } - - if(time <= 1.0) + + if ( time <= 1.0 ) { clmd->sim_parms.cache = NULL; } - - if(time <= 2.0) + + if ( time <= 2.0 ) clmd->sim_parms.preroll = 0; } } @@ -600,10 +600,10 @@ void cloth_cache_free(ClothModifierData *clmd, float time) /** * cloth_deform_verts - simulates one step, framenr is in frames. -* +* **/ -void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, - float (*vertexCos)[3], int numverts) +void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, + float ( *vertexCos ) [3], int numverts ) { unsigned int i; unsigned int numedges = -1; @@ -613,124 +613,124 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, MFace *mface = NULL; DerivedMesh *result = NULL, *result2 = NULL; Cloth *cloth = clmd->clothObject; - unsigned int framenr = (float)G.scene->r.cfra; - float current_time = bsystem_time(ob, (float)G.scene->r.cfra, 0.0); + unsigned int framenr = ( float ) G.scene->r.cfra; + float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); ListBase *effectors = NULL; ClothVertex *newframe= NULL, *verts; Frame *frame = NULL; LinkNode *search = NULL; - float deltaTime = current_time - clmd->sim_parms.sim_time; - - + float deltaTime = current_time - clmd->sim_parms.sim_time; + + // only be active during a specific period: // that's "first frame" and "last frame" on GUI - if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) + if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) ) { - if(clmd->clothObject) + if ( clmd->clothObject ) { - if(clmd->sim_parms.cache) + if ( clmd->sim_parms.cache ) { - if(current_time < clmd->sim_parms.firstframe) + if ( current_time < clmd->sim_parms.firstframe ) { - int frametime = cloth_cache_first_frame(clmd); - if(cloth_cache_search_frame(clmd, frametime)) + int frametime = cloth_cache_first_frame ( clmd ); + if ( cloth_cache_search_frame ( clmd, frametime ) ) { - cloth_cache_get_frame(clmd, frametime); - cloth_to_object (ob, clmd, vertexCos, numverts); + cloth_cache_get_frame ( clmd, frametime ); + cloth_to_object ( ob, clmd, vertexCos, numverts ); } return; } - else if(current_time > clmd->sim_parms.lastframe) + else if ( current_time > clmd->sim_parms.lastframe ) { - int frametime = cloth_cache_last_frame(clmd); - if(cloth_cache_search_frame(clmd, frametime)) + int frametime = cloth_cache_last_frame ( clmd ); + if ( cloth_cache_search_frame ( clmd, frametime ) ) { - cloth_cache_get_frame(clmd, frametime); - cloth_to_object (ob, clmd, vertexCos, numverts); + cloth_cache_get_frame ( clmd, frametime ); + cloth_to_object ( ob, clmd, vertexCos, numverts ); } return; } - else if(ABS(deltaTime) >= 2.0f ) // no timewarps allowed + else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed { - if(cloth_cache_search_frame(clmd, framenr)) + if ( cloth_cache_search_frame ( clmd, framenr ) ) { - cloth_cache_get_frame(clmd, framenr); - cloth_to_object (ob, clmd, vertexCos, numverts); + cloth_cache_get_frame ( clmd, framenr ); + cloth_to_object ( ob, clmd, vertexCos, numverts ); } clmd->sim_parms.sim_time = current_time; return; } } - + } } - - + + // unused in the moment, calculated seperately in implicit.c clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame; - + clmd->sim_parms.sim_time = current_time; - + // check if cloth object was some collision object before and needs freeing now - if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) && (clmd->clothObject != NULL) && (clmd->clothObject->old_solver_type == 255)) + if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) && ( clmd->clothObject != NULL ) && ( clmd->clothObject->old_solver_type == 255 ) ) { - // temporary set CSIMSETT_FLAG_COLLOBJ flag for proper freeing - clmd->sim_parms.flags |= CSIMSETT_FLAG_COLLOBJ; - cloth_free_modifier(clmd); - clmd->sim_parms.flags &= ~CSIMSETT_FLAG_COLLOBJ; + // temporary set CSIMSETT_FLAG_COLLOBJ flag for proper freeing + clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; + cloth_free_modifier ( clmd ); + clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_COLLOBJ; } // This is for collisions objects: check special case CSIMSETT_FLAG_COLLOBJ - if (clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) { - // save next position + time - if ((clmd->clothObject == NULL) || (numverts != clmd->clothObject->numverts) ) + // save next position + time + if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) ) { - if(!collobj_from_object (ob, clmd, dm, vertexCos, framenr)) + if ( !collobj_from_object ( ob, clmd, dm, vertexCos, framenr ) ) { - clmd->sim_parms.flags |= CSIMSETT_FLAG_COLLOBJ; - cloth_free_modifier(clmd); + clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; + cloth_free_modifier ( clmd ); return; } - if(clmd->clothObject == NULL) + if ( clmd->clothObject == NULL ) return; cloth = clmd->clothObject; } - // Save old position + // Save old position clmd->sim_parms.sim_time_old = clmd->sim_parms.sim_time; - clmd->sim_parms.sim_time = current_time; - - verts = cloth->verts; - - for (i = 0; i < clmd->clothObject->numverts; i++, verts++) - { - // Save the previous position. - VECCOPY (verts->xold, verts->x); - VECCOPY (verts->txold, verts->x); + clmd->sim_parms.sim_time = current_time; - // Get the current position. - VECCOPY (verts->x, vertexCos[i]); - Mat4MulVecfl(ob->obmat, verts->x); + verts = cloth->verts; + + for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) + { + // Save the previous position. + VECCOPY ( verts->xold, verts->x ); + VECCOPY ( verts->txold, verts->x ); + + // Get the current position. + VECCOPY ( verts->x, vertexCos[i] ); + Mat4MulVecfl ( ob->obmat, verts->x ); // Compute the vertices "velocity". // (no dt correction here because of float error) - VECSUB (verts->v, verts->x, verts->xold); + VECSUB ( verts->v, verts->x, verts->xold ); } - - return; - } - if(deltaTime == 1.0f) + return; + } + + if ( deltaTime == 1.0f ) { - if ((clmd->clothObject == NULL) || (numverts != clmd->clothObject->numverts) ) + if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) ) { - if(!cloth_from_object (ob, clmd, dm, vertexCos, numverts)) + if ( !cloth_from_object ( ob, clmd, dm, vertexCos, numverts ) ) return; - if(clmd->clothObject == NULL) + if ( clmd->clothObject == NULL ) return; cloth = clmd->clothObject; @@ -739,112 +739,125 @@ void clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, clmd->clothObject->old_solver_type = clmd->sim_parms.solver_type; // Insure we have a clmd->clothObject, in case allocation failed. - if (clmd->clothObject != NULL) - { - if(!cloth_cache_search_frame(clmd, framenr)) + if ( clmd->clothObject != NULL ) + { + if ( !cloth_cache_search_frame ( clmd, framenr ) ) { verts = cloth->verts; - - // Force any pinned verts to their constrained location. - for (i = 0; i < clmd->clothObject->numverts; i++, verts++) - { - // Save the previous position. - VECCOPY (verts->xold, verts->xconst); - VECCOPY (verts->txold, verts->x); - // Get the current position. - VECCOPY (verts->xconst, vertexCos[i]); - Mat4MulVecfl(ob->obmat, verts->xconst); + // Force any pinned verts to their constrained location. + for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) + { + // Save the previous position. + VECCOPY ( verts->xold, verts->xconst ); + VECCOPY ( verts->txold, verts->x ); + + // Get the current position. + VECCOPY ( verts->xconst, vertexCos[i] ); + Mat4MulVecfl ( ob->obmat, verts->xconst ); } tstart(); // Call the solver. - if (solvers [clmd->sim_parms.solver_type].solver) - solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors); - - tend(); - printf("Cloth simulation time: %f\n", (float)tval()); + if ( solvers [clmd->sim_parms.solver_type].solver ) + solvers [clmd->sim_parms.solver_type].solver ( ob, framenr, clmd, effectors ); - cloth_cache_set_frame(clmd, framenr); + tend(); + printf ( "Cloth simulation time: %f\n", ( float ) tval() ); + + cloth_cache_set_frame ( clmd, framenr ); } else // just retrieve the cached frame { - cloth_cache_get_frame(clmd, framenr); + cloth_cache_get_frame ( clmd, framenr ); } // Copy the result back to the object. - cloth_to_object (ob, clmd, vertexCos, numverts); - + cloth_to_object ( ob, clmd, vertexCos, numverts ); + // bvh_free(clmd->clothObject->tree); // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); - } + } } - else if((deltaTime <= 0.0f)||(deltaTime > 1.0f)) + else if ( ( deltaTime <= 0.0f ) || ( deltaTime > 1.0f ) ) { - if((clmd->clothObject != NULL) && (clmd->sim_parms.cache)) + if ( ( clmd->clothObject != NULL ) && ( clmd->sim_parms.cache ) ) { - if(cloth_cache_search_frame(clmd, framenr)) + if ( cloth_cache_search_frame ( clmd, framenr ) ) { - cloth_cache_get_frame(clmd, framenr); - cloth_to_object (ob, clmd, vertexCos, numverts); + cloth_cache_get_frame ( clmd, framenr ); + cloth_to_object ( ob, clmd, vertexCos, numverts ); } } } - + } /* frees all */ -void cloth_free_modifier (ClothModifierData *clmd) +void cloth_free_modifier ( ClothModifierData *clmd ) { Cloth *cloth = NULL; - if(!clmd) + if ( !clmd ) return; cloth = clmd->clothObject; - - if(!(clmd->sim_parms.flags & CSIMSETT_FLAG_CCACHE_PROTECT)) + + if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT ) ) { // free our frame cache, TODO: but get to first position before - cloth_cache_free(clmd, 0); - - if (cloth) - { + cloth_cache_free ( clmd, 0 ); + + if ( cloth ) + { + // If our solver provides a free function, call it - if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free) - { - solvers [cloth->old_solver_type].free (clmd); + if ( cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free ) + { + solvers [cloth->old_solver_type].free ( clmd ); } - + // Free the verts. - if (cloth->verts != NULL) - MEM_freeN (cloth->verts); - + if ( cloth->verts != NULL ) + MEM_freeN ( cloth->verts ); + cloth->verts = NULL; cloth->numverts = 0; - + // Free the springs. - if (cloth->springs != NULL) - MEM_freeN (cloth->springs); - + if ( cloth->springs != NULL ) + { + LinkNode *search = cloth->springs; + while(search) + { + ClothSpring *spring = search->link; + + MEM_freeN ( spring ); + search = search->next; + } + BLI_linklist_free(cloth->springs, NULL); + + cloth->springs = NULL; + } + cloth->springs = NULL; - cloth->numsprings = 0; - + cloth->numsprings = 0; + // free BVH collision tree - if(cloth->tree) - bvh_free((BVH *)cloth->tree); - + if ( cloth->tree ) + bvh_free ( ( BVH * ) cloth->tree ); + // we save our faces for collision objects - if(cloth->mfaces) - MEM_freeN(cloth->mfaces); + if ( cloth->mfaces ) + MEM_freeN ( cloth->mfaces ); /* if(clmd->clothObject->facemarks) MEM_freeN(clmd->clothObject->facemarks); */ - MEM_freeN (cloth); + MEM_freeN ( cloth ); clmd->clothObject = NULL; } } @@ -862,21 +875,22 @@ void cloth_free_modifier (ClothModifierData *clmd) * * This function is a modified version of the softbody.c:softbody_to_object() function. **/ -static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3], unsigned int numverts) +static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ) { ClothVertex *verts = NULL; unsigned int i = 0; - if (clmd->clothObject) { + if ( clmd->clothObject ) + { verts = clmd->clothObject->verts; /* inverse matrix is not uptodate... */ - Mat4Invert (ob->imat, ob->obmat); + Mat4Invert ( ob->imat, ob->obmat ); - for (i = 0; i < numverts; i++, verts++) + for ( i = 0; i < numverts; i++, verts++ ) { - VECCOPY (vertexCos[i], verts->x); - Mat4MulVecfl (ob->imat, vertexCos[i]); /* softbody is in global coords */ + VECCOPY ( vertexCos[i], verts->x ); + Mat4MulVecfl ( ob->imat, vertexCos[i] ); /* softbody is in global coords */ } } } @@ -886,46 +900,46 @@ static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertex * cloth_apply_vgroup - applies a vertex group as specified by type * **/ -static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup) +static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ) { unsigned int i = 0; unsigned int j = 0; MDeformVert *dvert = NULL; Cloth *clothObj = NULL; - unsigned int numverts = dm->getNumVerts(dm); + unsigned int numverts = dm->getNumVerts ( dm ); float goalfac = 0; ClothVertex *verts = NULL; clothObj = clmd->clothObject; - - if(!dm) + + if ( !dm ) return; - - numverts = dm->getNumVerts(dm); + + numverts = dm->getNumVerts ( dm ); /* vgroup is 1 based, decrement so we can match the right group. */ --vgroup; - + verts = clothObj->verts; - for (i = 0; i < numverts; i++, verts++) - { + for ( i = 0; i < numverts; i++, verts++ ) + { // LATER ON, support also mass painting here - if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) - { - dvert = dm->getVertData(dm, i, CD_MDEFORMVERT); - if(dvert) - { - for(j = 0; j < dvert->totweight; j++) + if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + { + dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT ); + if ( dvert ) + { + for ( j = 0; j < dvert->totweight; j++ ) { - if(dvert->dw[j].def_nr == vgroup) + if ( dvert->dw[j].def_nr == vgroup ) { verts->goal = dvert->dw [j].weight; - goalfac= ABS(clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal); - verts->goal = (float)pow(verts->goal , 4.0f); + goalfac= ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal ); + verts->goal = ( float ) pow ( verts->goal , 4.0f ); - if(dvert->dw [j].weight >=SOFTGOALSNAP) + if ( dvert->dw [j].weight >=SOFTGOALSNAP ) { verts->flags |= CVERT_FLAG_PINNED; } @@ -942,360 +956,221 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v // only meshes supported at the moment /* collision objects */ -static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float (*vertexCos)[3], unsigned int numverts) +static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ) { unsigned int i; - MVert *mvert = NULL; + MVert *mvert = NULL; ClothVertex *verts = NULL; - float tnull[3] = {0,0,0}; - + float tnull[3] = {0,0,0}; + /* If we have a clothObject, free it. */ - if (clmd->clothObject != NULL) - cloth_free_modifier (clmd); + if ( clmd->clothObject != NULL ) + cloth_free_modifier ( clmd ); /* Allocate a new cloth object. */ - clmd->clothObject = MEM_callocN (sizeof(Cloth), "cloth"); - if (clmd->clothObject) + clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" ); + if ( clmd->clothObject ) { clmd->clothObject->old_solver_type = 255; - clmd->clothObject->old_collision_type = 255; + // clmd->clothObject->old_collision_type = 255; } - else if (clmd->clothObject == NULL) + else if ( clmd->clothObject == NULL ) { - modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject."); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject." ); return 0; } - switch (ob->type) + switch ( ob->type ) { - case OB_MESH: - - // mesh input objects need DerivedMesh - if(!dm) - return 0; - - cloth_from_mesh (ob, clmd, dm); - - if (clmd->clothObject != NULL) - { - if (!dm) return 0; - if (!dm->getNumVerts(dm) || !dm->getNumFaces(dm)) return 0; - - mvert = dm->getVertArray(dm); - verts = clmd->clothObject->verts; - numverts = clmd->clothObject->numverts = dm->getNumVerts(dm); - - for (i = 0; i < numverts; i++, verts++) + case OB_MESH: + + // mesh input objects need DerivedMesh + if ( !dm ) + return 0; + + cloth_from_mesh ( ob, clmd, dm ); + + if ( clmd->clothObject != NULL ) { - VECCOPY (verts->x, mvert[i].co); - Mat4MulVecfl(ob->obmat, verts->x); - verts->flags = 0; - VECCOPY(verts->xold, verts->x); - VECCOPY(verts->txold, verts->x); - VECCOPY(verts->tx, verts->x); - VecMulf(verts->v, 0.0f); - verts->impulse_count = 0; - VECCOPY(verts->impulse, tnull); + if ( !dm ) return 0; + if ( !dm->getNumVerts ( dm ) || !dm->getNumFaces ( dm ) ) return 0; + + mvert = dm->getVertArray ( dm ); + verts = clmd->clothObject->verts; + numverts = clmd->clothObject->numverts = dm->getNumVerts ( dm ); + + for ( i = 0; i < numverts; i++, verts++ ) + { + VECCOPY ( verts->x, mvert[i].co ); + Mat4MulVecfl ( ob->obmat, verts->x ); + verts->flags = 0; + VECCOPY ( verts->xold, verts->x ); + VECCOPY ( verts->txold, verts->x ); + VECCOPY ( verts->tx, verts->x ); + VecMulf ( verts->v, 0.0f ); + verts->impulse_count = 0; + VECCOPY ( verts->impulse, tnull ); + } + clmd->clothObject->tree = bvh_build ( clmd,clmd->coll_parms.epsilon ); + } - clmd->clothObject->tree = bvh_build(clmd,clmd->coll_parms.epsilon); - - } - - return 1; - default: return 0; // TODO - we do not support changing meshes + + return 1; + default: return 0; // TODO - we do not support changing meshes } } /* -helper function to get proper spring length +helper function to get proper spring length when object is rescaled */ -float cloth_globallen(float *v1,float *v2,Object *ob) +float cloth_globallen ( float *v1,float *v2,Object *ob ) { float p1[3],p2[3]; - VECCOPY(p1,v1); - Mat4MulVecfl(ob->obmat, p1); - VECCOPY(p2,v2); - Mat4MulVecfl(ob->obmat, p2); - return VecLenf(p1,p2); + VECCOPY ( p1,v1 ); + Mat4MulVecfl ( ob->obmat, p1 ); + VECCOPY ( p2,v2 ); + Mat4MulVecfl ( ob->obmat, p2 ); + return VecLenf ( p1,p2 ); } -static void curve_surf_to_cloth(Object *ob, ClothModifierData *clmd, float (*vertexCos)[3]) -{ - Curve *cu= ob->data; - Nurb *nu; - BezTriple *bezt; - float goalfac; - unsigned int a, curindex=0, i=0; - unsigned int numverts, numsprings = 0, setgoal=0; - Cloth *clothObj; - ClothVertex *verts = NULL; - - clmd->clothObject->numverts = numverts= count_curveverts(&cu->nurb); - clothObj = clmd->clothObject; - - if(ob->type==OB_CURVE) - { - numsprings = numverts - BLI_countlist(&cu->nurb); - } - - /* Allocate our vertices. - */ - clmd->clothObject->numverts = numverts; - clmd->clothObject->verts = MEM_callocN (sizeof (ClothVertex) * clmd->clothObject->numverts, "clothVertex"); - if (clmd->clothObject->verts == NULL) - { - cloth_free_modifier (clmd); - modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts."); - return; - } - - verts = clmd->clothObject->verts; - - // copy vertex positions - for (i = 0; i < numverts; i++) - { - VECCOPY (verts->x, vertexCos[i]); - Mat4MulVecfl(ob->obmat, verts->x); - - verts->mass = clmd->sim_parms.mass; - // verts->goal= clmd->sim_parms.defgoal; - verts->flags = 0; - VECCOPY(verts->xold, verts->x); - VECCOPY(verts->xconst, verts->x); - VECCOPY(verts->txold, verts->x); - VecMulf(verts->v, 0.0f); - } - - clmd->clothObject->mfaces = NULL; // update face pointer - clmd->clothObject->numfaces = 0; - - clmd->clothObject->springs = MEM_callocN (sizeof (ClothSpring) * (numsprings), "cloth_springs_alloc"); - - // set vars now - goalfac= ABS(clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal); - // clothObj->verts [i].goal = clmd->sim_parms.mingoal + bezt->weight*goalfac; - - /* apply / set vertex groups */ - if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) - { - if (clmd->sim_parms.vgroup_mass > 0) - { - setgoal = 1; - } - } - -/* - for(nu= cu->nurb.first; nu; nu= nu->next) - { - if(nu->bezt) - { - for(bezt=nu->bezt, a=0; apntsu; a++, bezt++, bp+=3, curindex+=3) - { - if(setgoal) - { - bp->goal= sb->mingoal + bezt->weight*goalfac; - // a little ad hoc changing the goal control to be less *sharp* - bp->goal = (float)pow(bp->goal, 4.0f); - - // all three triples - (bp+1)->goal= bp->goal; - (bp+2)->goal= bp->goal; - } - - if(totspring) - { - if(a>0) - { - bs->v1= curindex-1; - bs->v2= curindex; - bs->strength= 1.0; - bs->order=1; - bs->len= globallen( (bezt-1)->vec[2], bezt->vec[0], ob ); - bs++; - } - bs->v1= curindex; - bs->v2= curindex+1; - bs->strength= 1.0; - bs->order=1; - bs->len= globallen( bezt->vec[0], bezt->vec[1], ob ); - bs++; - - bs->v1= curindex+1; - bs->v2= curindex+2; - bs->strength= 1.0; - bs->order=1; - bs->len= globallen( bezt->vec[1], bezt->vec[2], ob ); - bs++; - } - } - } - else { - for(bpnt=nu->bp, a=0; apntsu*nu->pntsv; a++, bpnt++, bp++, curindex++) - { - if(setgoal) - { - bp->goal= sb->mingoal + bpnt->weight*goalfac; - // a little ad hoc changing the goal control to be less *sharp* - bp->goal = (float)pow(bp->goal, 4.0f); - } - if(totspring && a>0) - { - bs->v1= curindex-1; - bs->v2= curindex; - bs->strength= 1.0; - bs->order=1; - bs->len= globallen( (bpnt-1)->vec, bpnt->vec , ob ); - bs++; - } - } - } - } - */ -} - // only meshes supported at the moment -static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float (*vertexCos)[3], unsigned int numverts) +static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ) { unsigned int i = 0; // dm->getNumVerts(dm); MVert *mvert = NULL; // CDDM_get_verts(dm); ClothVertex *verts = NULL; float tnull[3] = {0,0,0}; - + /* If we have a clothObject, free it. */ - if (clmd->clothObject != NULL) - cloth_free_modifier (clmd); + if ( clmd->clothObject != NULL ) + cloth_free_modifier ( clmd ); /* Allocate a new cloth object. */ - clmd->clothObject = MEM_callocN (sizeof(Cloth), "cloth"); - if (clmd->clothObject) + clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" ); + if ( clmd->clothObject ) { clmd->clothObject->old_solver_type = 255; - clmd->clothObject->old_collision_type = 255; + // clmd->clothObject->old_collision_type = 255; } - else if (clmd->clothObject == NULL) + else if ( !clmd->clothObject ) { - modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject."); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject." ); return 0; } - switch (ob->type) + switch ( ob->type ) { case OB_MESH: - - // mesh input objects need DerivedMesh - if(!dm) - return 0; - - cloth_from_mesh (ob, clmd, dm); - if (clmd->clothObject != NULL) - { - /* create springs */ - clmd->clothObject->springs = NULL; - clmd->clothObject->numsprings = -1; - - if (!cloth_build_springs (clmd->clothObject, dm) ) - { - modifier_setError (&(clmd->modifier), "Can't build springs."); + // mesh input objects need DerivedMesh + if ( !dm ) return 0; - } - - mvert = CDDM_get_verts(dm); - verts = clmd->clothObject->verts; - /* set initial values */ - for (i = 0; i < numverts; i++, verts++) + cloth_from_mesh ( ob, clmd, dm ); + + if ( clmd->clothObject != NULL ) { - VECCOPY (verts->x, mvert[i].co); - Mat4MulVecfl(ob->obmat, verts->x); + /* create springs */ + clmd->clothObject->springs = NULL; + clmd->clothObject->numsprings = -1; - verts->mass = clmd->sim_parms.mass; - - if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) - verts->goal= clmd->sim_parms.defgoal; - else - verts->goal= 0.0f; - - verts->flags = 0; - VECCOPY(verts->xold, verts->x); - VECCOPY(verts->xconst, verts->x); - VECCOPY(verts->txold, verts->x); - VecMulf(verts->v, 0.0f); - - verts->impulse_count = 0; - VECCOPY(verts->impulse, tnull); + if ( !cloth_build_springs ( clmd->clothObject, dm ) ) + { + modifier_setError ( & ( clmd->modifier ), "Can't build springs." ); + return 0; + } + + mvert = CDDM_get_verts ( dm ); + verts = clmd->clothObject->verts; + + /* set initial values */ + for ( i = 0; i < numverts; i++, verts++ ) + { + VECCOPY ( verts->x, mvert[i].co ); + Mat4MulVecfl ( ob->obmat, verts->x ); + + verts->mass = clmd->sim_parms.mass; + + if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + verts->goal= clmd->sim_parms.defgoal; + else + verts->goal= 0.0f; + + verts->flags = 0; + VECCOPY ( verts->xold, verts->x ); + VECCOPY ( verts->xconst, verts->x ); + VECCOPY ( verts->txold, verts->x ); + VecMulf ( verts->v, 0.0f ); + + verts->impulse_count = 0; + VECCOPY ( verts->impulse, tnull ); + } + + // apply / set vertex groups + if ( clmd->sim_parms.vgroup_mass > 0 ) + cloth_apply_vgroup ( clmd, dm, clmd->sim_parms.vgroup_mass ); + + // init our solver + if ( solvers [clmd->sim_parms.solver_type].init ) + solvers [clmd->sim_parms.solver_type].init ( ob, clmd ); + + clmd->clothObject->tree = bvh_build ( clmd, clmd->coll_parms.epsilon ); + + cloth_cache_set_frame ( clmd, 1 ); } - // apply / set vertex groups - if (clmd->sim_parms.vgroup_mass > 0) - cloth_apply_vgroup (clmd, dm, clmd->sim_parms.vgroup_mass); - - // init our solver - if (solvers [clmd->sim_parms.solver_type].init) - solvers [clmd->sim_parms.solver_type].init (ob, clmd); - - clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); - - cloth_cache_set_frame(clmd, 1); - } - - return 1; + return 1; case OB_LATTICE: - printf("OB_LATTICE\n"); - // lattice_to_softbody(ob); - return 1; + printf ( "Not supported: OB_LATTICE\n" ); + // lattice_to_softbody(ob); + return 1; case OB_CURVE: case OB_SURF: - printf("OB_SURF| OB_CURVE\n"); - curve_surf_to_cloth(ob, clmd, vertexCos); - return 1; + printf ( "Not supported: OB_SURF| OB_CURVE\n" ); + return 1; default: return 0; // TODO - we do not support changing meshes } - + return 0; } -static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm) +static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) { - unsigned int numverts = dm->getNumVerts(dm); - unsigned int numfaces = dm->getNumFaces(dm); - MFace *mface = dm->getFaceArray(dm); + unsigned int numverts = dm->getNumVerts ( dm ); + unsigned int numfaces = dm->getNumFaces ( dm ); + MFace *mface = dm->getFaceArray ( dm ); unsigned int i = 0; /* Allocate our vertices. */ clmd->clothObject->numverts = numverts; - clmd->clothObject->verts = MEM_callocN (sizeof (ClothVertex) * clmd->clothObject->numverts, "clothVertex"); - if (clmd->clothObject->verts == NULL) + clmd->clothObject->verts = MEM_callocN ( sizeof ( ClothVertex ) * clmd->clothObject->numverts, "clothVertex" ); + if ( clmd->clothObject->verts == NULL ) { - cloth_free_modifier (clmd); - modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts."); + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." ); return; } - + // save face information clmd->clothObject->numfaces = numfaces; - clmd->clothObject->mfaces = MEM_callocN (sizeof (MFace) * clmd->clothObject->numfaces, "clothMFaces"); - if (clmd->clothObject->mfaces == NULL) + clmd->clothObject->mfaces = MEM_callocN ( sizeof ( MFace ) * clmd->clothObject->numfaces, "clothMFaces" ); + if ( clmd->clothObject->mfaces == NULL ) { - cloth_free_modifier (clmd); - modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->mfaces."); + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->mfaces." ); return; } - for(i = 0; i < numfaces; i++) - memcpy(&clmd->clothObject->mfaces[i], &mface[i], sizeof(MFace)); - - - // for SIP code - // clmd->clothObject->facemarks = MEM_callocN (sizeof (unsigned char) * clmd->clothObject->numfaces, "clothFaceMarks"); + for ( i = 0; i < numfaces; i++ ) + memcpy ( &clmd->clothObject->mfaces[i], &mface[i], sizeof ( MFace ) ); /* Free the springs since they can't be correct if the vertices * changed. */ - if (clmd->clothObject->springs != NULL) - MEM_freeN (clmd->clothObject->springs); + if ( clmd->clothObject->springs != NULL ) + MEM_freeN ( clmd->clothObject->springs ); } @@ -1303,126 +1178,166 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d * SPRING NETWORK BUILDING IMPLEMENTATION BEGIN ***************************************************************************************/ -int cloth_build_springs(Cloth *cloth, DerivedMesh *dm) +// be carefull: implicit solver has to be resettet when using this one! +int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type) { - ClothSpring *springs = NULL; + Cloth *cloth = clmd->clothObject; + ClothSpring *spring = NULL; + + if(cloth) + { + // TODO: look if this spring is already there + + spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); + + spring->ij = indexA; + spring->kl = indexB; + spring->restlen = restlength; + spring->type = spring_type; + spring->flags = 0; + + cloth->numsprings++; + + BLI_linklist_append ( &cloth->springs, spring ); + } +} + +int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) +{ + ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0; unsigned int i = 0; - unsigned int numverts = dm->getNumVerts(dm); - unsigned int numedges = dm->getNumEdges(dm); - unsigned int numfaces = dm->getNumFaces(dm); - MVert *mvert = CDDM_get_verts(dm); - MEdge *medge = CDDM_get_edges(dm); - MFace *mface = CDDM_get_faces(dm); + unsigned int numverts = dm->getNumVerts ( dm ); + unsigned int numedges = dm->getNumEdges ( dm ); + unsigned int numfaces = dm->getNumFaces ( dm ); + MVert *mvert = CDDM_get_verts ( dm ); + MEdge *medge = CDDM_get_edges ( dm ); + MFace *mface = CDDM_get_faces ( dm ); unsigned int index2 = 0; // our second vertex index LinkNode **edgelist = NULL; EdgeHash *edgehash = NULL; - LinkNode *search = NULL; + LinkNode *search = NULL, *search2 = NULL; float temp[3]; - unsigned int temp_index = 0; - ClothSpring *tspring = NULL; // error handling - if(numedges==0) + if ( numedges==0 ) return 0; - edgelist = MEM_callocN (sizeof (LinkNode *) * numverts, "cloth_edgelist_alloc"); - for(i = 0; i < numverts; i++) + cloth->springs = NULL; + + edgelist = MEM_callocN ( sizeof ( LinkNode * ) * numverts, "cloth_edgelist_alloc" ); + for ( i = 0; i < numverts; i++ ) { edgelist[i] = NULL; } - if(cloth->springs) - MEM_freeN(cloth->springs); + if ( cloth->springs ) + MEM_freeN ( cloth->springs ); // create spring network hash edgehash = BLI_edgehash_new(); - // should be 4 for maximal bending springs, using 5 to be sure ;) - springs = cloth->springs = MEM_callocN (sizeof (ClothSpring) * (numedges + numfaces * 2 + 6 * numverts), "cloth_springs_alloc"); - // structural springs - for(i = 0; i < numedges; i++) + for ( i = 0; i < numedges; i++ ) { - springs[i].ij = medge[i].v1; - springs[i].kl = medge[i].v2; - VECSUB(temp, mvert[springs[i].kl].co, mvert[springs[i].ij].co); - springs[i].restlen = sqrt(INPR(temp, temp)); - springs[i].type = STRUCTURAL; - springs[i].flags = 0; - struct_springs++; + spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); + + if ( spring ) + { + spring->ij = medge[i].v1; + spring->kl = medge[i].v2; + VECSUB ( temp, mvert[spring->kl].co, mvert[spring->ij].co ); + spring->restlen = sqrt ( INPR ( temp, temp ) ); + spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; + spring->flags = 0; + struct_springs++; + + BLI_linklist_append ( &cloth->springs, spring ); + } } // shear springs - for(i = 0; i < numfaces; i++) + for ( i = 0; i < numfaces; i++ ) { - temp_index = struct_springs + shear_springs; + spring = ( ClothSpring *) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); - springs[temp_index].ij = mface[i].v1; - springs[temp_index].kl = mface[i].v3; - VECSUB(temp, mvert[springs[temp_index].kl].co, mvert[springs[temp_index].ij].co); - springs[temp_index].restlen = sqrt(INPR(temp, temp)); - springs[temp_index].type = SHEAR; - - BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index])); - BLI_linklist_append(&edgelist[springs[temp_index].kl], &(springs[temp_index])); + spring->ij = mface[i].v1; + spring->kl = mface[i].v3; + VECSUB ( temp, mvert[spring->kl].co, mvert[spring->ij].co ); + spring->restlen = sqrt ( INPR ( temp, temp ) ); + spring->type = CLOTH_SPRING_TYPE_SHEAR; + BLI_linklist_append ( &edgelist[spring->ij], spring ); + BLI_linklist_append ( &edgelist[spring->kl], spring ); shear_springs++; - temp_index++; - - if(mface[i].v4) + + BLI_linklist_append ( &cloth->springs, spring ); + + if ( mface[i].v4 ) { - springs[temp_index].ij = mface[i].v2; - springs[temp_index].kl = mface[i].v4; - VECSUB(temp, mvert[springs[temp_index].kl].co, mvert[springs[temp_index].ij].co); - springs[temp_index].restlen = sqrt(INPR(temp, temp)); - springs[temp_index].type = SHEAR; - - BLI_linklist_append(&edgelist[springs[temp_index].ij], &(springs[temp_index])); - BLI_linklist_append(&edgelist[springs[temp_index].kl], &(springs[temp_index])); - - shear_springs++; + spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); + + spring->ij = mface[i].v1; + spring->kl = mface[i].v3; + VECSUB ( temp, mvert[spring->kl].co, mvert[spring->ij].co ); + spring->restlen = sqrt ( INPR ( temp, temp ) ); + spring->type = CLOTH_SPRING_TYPE_SHEAR; + + BLI_linklist_append ( &edgelist[spring->ij], spring ); + BLI_linklist_append ( &edgelist[spring->kl], spring ); + shear_springs++; + + BLI_linklist_append ( &cloth->springs, spring ); } } // bending springs - for(i = struct_springs; i < struct_springs+shear_springs; i++) - { - search = edgelist[springs[i].kl]; - while(search) + search2 = cloth->springs; + for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) + { + if ( !search2 ) + break; + + tspring2 = search2->link; + search = edgelist[tspring2->kl]; + while ( search ) { tspring = search->link; - index2 = ((tspring->ij==springs[i].kl) ? (tspring->kl) : (tspring->ij)); - - if(!BLI_edgehash_haskey(edgehash, index2, springs[i].ij) // check for existing spring - && !BLI_edgehash_haskey(edgehash, springs[i].ij, index2) // same - && (index2!=springs[i].ij)) // check if startpoint is equal to endpoint + index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) ); + + // check for existing spring + // check also if startpoint is equal to endpoint + if ( !BLI_edgehash_haskey ( edgehash, index2, tspring2->ij ) + && !BLI_edgehash_haskey ( edgehash, tspring2->ij, index2 ) + && ( index2!=tspring2->ij ) ) { - temp_index = struct_springs + shear_springs + bend_springs; + spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); - springs[temp_index].ij = springs[i].ij; - springs[temp_index].kl = index2; - VECSUB(temp, mvert[index2].co, mvert[springs[i].ij].co); - springs[temp_index].restlen = sqrt(INPR(temp, temp)); - springs[temp_index].type = BENDING; - BLI_edgehash_insert(edgehash, springs[temp_index].ij, index2, NULL); + spring->ij = tspring2->ij; + spring->kl = index2; + VECSUB ( temp, mvert[index2].co, mvert[tspring2->ij].co ); + spring->restlen = sqrt ( INPR ( temp, temp ) ); + spring->type = CLOTH_SPRING_TYPE_BENDING; + BLI_edgehash_insert ( edgehash, spring->ij, index2, NULL ); bend_springs++; + BLI_linklist_append ( &cloth->springs, spring ); } - search = search->next; + search = search->next; } + search2 = search2->next; } cloth->numsprings = struct_springs + shear_springs + bend_springs; - for(i = 0; i < numverts; i++) + for ( i = 0; i < numverts; i++ ) { - BLI_linklist_free(edgelist[i],NULL); + BLI_linklist_free ( edgelist[i],NULL ); } - if(edgelist) - MEM_freeN(edgelist); + if ( edgelist ) + MEM_freeN ( edgelist ); - BLI_edgehash_free(edgehash, NULL); + BLI_edgehash_free ( edgehash, NULL ); return 1; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index c3dbc572b4e..a5a382f7624 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -77,7 +77,7 @@ * * copied from SOLVE_CUBIC.C --> GSL */ -#define mySWAP(a,b) do { float tmp = b ; b = a ; a = tmp ; } while(0) +#define mySWAP(a,b) { float tmp = b ; b = a ; a = tmp ; } int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float *x2) { @@ -361,8 +361,6 @@ DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], floa VECADDMUL(to, v3, w3); } - - // unused in the moment, has some bug in DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal[3], double normalVelocity, double frictionConstant, double delta_V_n) @@ -887,6 +885,7 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col // TODO: put into (point-face) collision list printf("Moving found!\n"); + } } @@ -924,7 +923,7 @@ void cloth_update_collision_objects(float step) continue; // if collision object go on - if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) { if (coll_clmd->clothObject && coll_clmd->clothObject->tree) { @@ -969,7 +968,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) float tnull[3] = {0,0,0}; int ret = 0; - if ((clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) + if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) { return 0; } @@ -1005,7 +1004,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) continue; // if collision object go on - if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) { if (coll_clmd->clothObject && coll_clmd->clothObject->tree) { @@ -1034,7 +1033,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) continue; // if collision object go on - if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) { if (coll_clmd->clothObject) result += cloth_collision_response_static(clmd, coll_clmd); @@ -1141,7 +1140,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) continue; // if collision object go on - if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) { if (coll_clmd->clothObject && coll_clmd->clothObject->tree) { @@ -1171,7 +1170,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) continue; // if collision object go on - if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) { if (coll_clmd->clothObject) result += cloth_collision_response_moving_tris(clmd, coll_clmd); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 7f156acff71..1ee4475a6cc 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -700,15 +700,15 @@ int implicit_init (Object *ob, ClothModifierData *clmd) unsigned int pinned = 0; Cloth *cloth = NULL; ClothVertex *verts = NULL; - ClothSpring *springs = NULL; + ClothSpring *spring = NULL; Implicit_Data *id = NULL; + LinkNode *search = NULL; // init memory guard // MEMORY_BASE.first = MEMORY_BASE.last = NULL; cloth = (Cloth *)clmd->clothObject; verts = cloth->verts; - springs = cloth->springs; // create implicit base id = (Implicit_Data *)MEM_callocN (sizeof(Implicit_Data), "implicit vecmat"); @@ -749,17 +749,22 @@ int implicit_init (Object *ob, ClothModifierData *clmd) id->S[0].vcount = pinned; id->S[0].scount = 0; // init springs */ + search = cloth->springs; for(i=0;inumsprings;i++) { + spring = search->link; + // dFdV_start[i].r = big_I[i].r = big_zero[i].r = id->A[i+cloth->numverts].r = id->dFdV[i+cloth->numverts].r = id->dFdX[i+cloth->numverts].r = - id->P[i+cloth->numverts].r = id->Pinv[i+cloth->numverts].r = id->bigI[i+cloth->numverts].r = springs[i].ij; + id->P[i+cloth->numverts].r = id->Pinv[i+cloth->numverts].r = id->bigI[i+cloth->numverts].r = spring->ij; // dFdV_start[i].c = big_I[i].c = big_zero[i].c = id->A[i+cloth->numverts].c = id->dFdV[i+cloth->numverts].c = id->dFdX[i+cloth->numverts].c = - id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = springs[i].kl; + id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = spring->kl; - springs[i].matrix_index = i + cloth->numverts; + spring->matrix_index = i + cloth->numverts; + + search = search->next; } for(i = 0; i < cloth->numverts; i++) @@ -1170,7 +1175,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, VECSUB(vel, V[s->kl], V[s->ij]); length = sqrt(INPR(extent, extent)); - s->flags &= ~CSPRING_FLAG_NEEDED; + s->flags &= ~CLOTH_SPRING_FLAG_NEEDED; if(length > ABS(ALMOST_ZERO)) { @@ -1193,12 +1198,12 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, } - // calculate force of structural springs - if(s->type != BENDING) + // calculate force of structural + shear springs + if(s->type != CLOTH_SPRING_TYPE_BENDING) { if(length > L) // only on elonglation { - s->flags |= CSPRING_FLAG_NEEDED; + s->flags |= CLOTH_SPRING_FLAG_NEEDED; k = clmd->sim_parms.structural; @@ -1219,7 +1224,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, { if(length < L) { - s->flags |= CSPRING_FLAG_NEEDED; + s->flags |= CLOTH_SPRING_FLAG_NEEDED; k = clmd->sim_parms.bending; @@ -1231,6 +1236,27 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, } } +DO_INLINE void cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) +{ + if(s->flags & CLOTH_SPRING_FLAG_NEEDED) + { + if(s->type != CLOTH_SPRING_TYPE_BENDING) + { + sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, s->dfdv); + sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv); + add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); + } + + VECADD(lF[s->ij], lF[s->ij], s->f); + VECSUB(lF[s->kl], lF[s->kl], s->f); + + sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx); + sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, s->dfdx); + + add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, s->dfdx); + } +} + DO_INLINE void calculateTriangleNormal(float to[3], lfVector *X, MFace mface) { float v1[3], v2[3]; @@ -1239,6 +1265,7 @@ DO_INLINE void calculateTriangleNormal(float to[3], lfVector *X, MFace mface) VECSUB(v2, X[mface.v3], X[mface.v1]); cross_fvector(to, v1, v2); } + DO_INLINE void calculatQuadNormal(float to[3], lfVector *X, MFace mface) { float temp = CalcNormFloat4(X[mface.v1],X[mface.v2],X[mface.v3],X[mface.v4],to); @@ -1280,12 +1307,12 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec float gravity[3]; float tm2[3][3] = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}}; ClothVertex *verts = cloth->verts; - ClothSpring *springs = cloth->springs; MFace *mfaces = cloth->mfaces; float wind_normalized[3]; unsigned int numverts = cloth->numverts; float auxvect[3], velgoal[3], tvect[3]; float kd, ks; + LinkNode *search = cloth->springs; VECCOPY(gravity, clmd->sim_parms.gravity); @@ -1301,7 +1328,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec submul_lfvectorS(lF, lV, spring_air, numverts); /* do goal stuff */ - if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { for(i = 0; i < numverts; i++) { @@ -1350,53 +1377,25 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec } } - /* calculate and apply spring forces */ -#pragma omp parallel private(i) -{ -#pragma omp for nowait - for(i = 0; i < cloth->numsprings/2; i++) + // calculate spring forces + search = cloth->springs; + while(search) { // only handle active springs - // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) - // { - cloth_calc_spring_force(clmd, &springs[i], lF, lX, lV, dFdV, dFdX); - // } + // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)){} + cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); + + search = search->next; } -#pragma omp for nowait - for(i = cloth->numsprings/2; i < cloth->numsprings; i++) - { - // only handle active springs - // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) - // { - cloth_calc_spring_force(clmd, &springs[i], lF, lX, lV, dFdV, dFdX); - // } - } -} // pragma omp parallel - for(i = 0; i < cloth->numsprings; i++) + // apply spring forces + search = cloth->springs; + while(search) { // only handle active springs - // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) - { - ClothSpring *s = &springs[i]; - if(s->flags & CSPRING_FLAG_NEEDED) - { - if(s->type != BENDING) - { - sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, s->dfdv); - sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv); - add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); - } - - VECADD(lF[s->ij], lF[s->ij], s->f); - VECSUB(lF[s->kl], lF[s->kl], s->f); - - sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx); - sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, s->dfdx); - - add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, s->dfdx); - } - } + // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) + cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); + search = search->next; } } @@ -1442,7 +1441,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase Implicit_Data *id = cloth->implicit; int result = 0; - if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) /* do goal stuff */ + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { for(i = 0; i < numverts; i++) { @@ -1465,66 +1464,74 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); - // collisions - // itstart(); - - // update verts to current positions - for(i = 0; i < numverts; i++) - { - if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) /* do goal stuff */ - { - if(verts [i].goal >= SOFTGOALSNAP) + if(clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + { + // collisions + // itstart(); + + // update verts to current positions + for(i = 0; i < numverts; i++) + { + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { - float tvect[3] = {.0,.0,.0}; - // VECSUB(tvect, id->Xnew[i], verts[i].xold); - mul_fvector_S(tvect, id->V[i], step+dt); - VECADD(tvect, tvect, verts[i].xold); - VECCOPY(id->Xnew[i], tvect); + if(verts [i].goal >= SOFTGOALSNAP) + { + float tvect[3] = {.0,.0,.0}; + // VECSUB(tvect, id->Xnew[i], verts[i].xold); + mul_fvector_S(tvect, id->V[i], step+dt); + VECADD(tvect, tvect, verts[i].xold); + VECCOPY(id->Xnew[i], tvect); + } + } + + VECCOPY(verts[i].tx, id->Xnew[i]); + + VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + VECCOPY(verts[i].v, verts[i].tv); + } + + // call collision function + result = cloth_bvh_objcollision(clmd, step + dt, dt); + + // copy corrected positions back to simulation + for(i = 0; i < numverts; i++) + { + if(result) + { + // VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + VECCOPY(verts[i].txold, verts[i].tx); + + VECCOPY(id->Xnew[i], verts[i].tx); + + VECCOPY(id->Vnew[i], verts[i].tv); + VecMulf(id->Vnew[i], 1.0f / dt); + } + else + { + VECCOPY(verts[i].txold, id->Xnew[i]); + } } - VECCOPY(verts[i].tx, id->Xnew[i]); + // X = Xnew; + cp_lfvector(id->X, id->Xnew, numverts); - VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); - VECCOPY(verts[i].v, verts[i].tv); - } - - // call collision function - result = cloth_bvh_objcollision(clmd, step + dt, dt); - - // copy corrected positions back to simulation - for(i = 0; i < numverts; i++) - { + // if there were collisions, advance the velocity from v_n+1/2 to v_n+1 if(result) { - // VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + // V = Vnew; + cp_lfvector(id->V, id->Vnew, numverts); - VECCOPY(verts[i].txold, verts[i].tx); - - VECCOPY(id->Xnew[i], verts[i].tx); - - VECCOPY(id->Vnew[i], verts[i].tv); - VecMulf(id->Vnew[i], 1.0f / dt); - } - else - { - VECCOPY(verts[i].txold, id->Xnew[i]); + // calculate + cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); } } - - // X = Xnew; - cp_lfvector(id->X, id->Xnew, numverts); - - // if there were collisions, advance the velocity from v_n+1/2 to v_n+1 - if(result) + else { - // V = Vnew; - cp_lfvector(id->V, id->Vnew, numverts); - - // calculate - cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); - simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); + // X = Xnew; + cp_lfvector(id->X, id->Xnew, numverts); } // itend(); @@ -1540,7 +1547,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase for(i = 0; i < numverts; i++) { - if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { if(verts [i].goal < SOFTGOALSNAP) { diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 7ce5e6928ea..b487f9a3b26 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -547,7 +547,7 @@ BVH *bvh_build (ClothModifierData *clmd, float epsilon) Tree *tree=NULL; LinkNode *nlink = NULL; EdgeHash *edgehash = NULL; - ClothSpring *springs = NULL; + LinkNode *springs = NULL; unsigned int numsprings = 0; MFace *mface = NULL; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 5ba3df9a720..c1f097e8447 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4907,7 +4907,7 @@ static void clothModifier_updateDepgraph( ClothModifierData *coll_clmd = (ClothModifierData *)modifiers_findByType(ob1, eModifierType_Cloth); if(coll_clmd) { - if (coll_clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ) + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) { DagNode *curNode = dag_get_node(forest, ob1); dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA); @@ -4915,8 +4915,7 @@ static void clothModifier_updateDepgraph( } } } - } - + } } CustomDataMask clothModifier_requiredDataMask(ModifierData *md) @@ -4925,7 +4924,7 @@ CustomDataMask clothModifier_requiredDataMask(ModifierData *md) CustomDataMask dataMask = 0; /* ask for vertexgroups if we need them */ - if(clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) if (clmd->sim_parms.vgroup_mass > 0) dataMask |= (1 << CD_MDEFORMVERT); @@ -4944,7 +4943,7 @@ static void clothModifier_freeData(ModifierData *md) if (clmd) { - clmd->sim_parms.flags &= ~CSIMSETT_FLAG_CCACHE_PROTECT; + clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; cloth_free_modifier (clmd); } } diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 6e986ae0067..7f5527466e4 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -40,7 +40,8 @@ * They will assume the position they had prior to pinFrame until unpinFrame * is reached. */ -typedef struct ClothVertex { +typedef struct ClothVertex +{ int flags; /* General flags per vertex. */ float v [3]; /* The velocity of the point. */ float xconst [3]; /* constrained position */ @@ -53,23 +54,26 @@ typedef struct ClothVertex { float goal; /* goal, from SB */ float impulse[3]; /* used in collision.c */ unsigned int impulse_count; /* same as above */ -} ClothVertex; +} +ClothVertex; /** * The definition of a spring. */ -typedef struct ClothSpring { +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 */ - int type; + int matrix_index; /* needed for implicit solver (fast lookup) */ + int type; /* types defined in BKE_cloth.h ("springType") */ int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ float dfdx[3][3]; float dfdv[3][3]; float f[3]; -} ClothSpring; +} +ClothSpring; @@ -84,10 +88,11 @@ typedef struct ClothSpring { * as in stepsPerFrame comapred to the time step in the paper, I've used * variables with different names to minimize confusion. **/ -typedef struct SimulationSettings { +typedef struct SimulationSettings +{ short vgroup_mass; /* optional vertexgroup name for assigning weight. */ short pad; - float mingoal; /* see SB */ + 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. */ @@ -99,11 +104,11 @@ typedef struct SimulationSettings { float structural; /* Structural spring stiffness. */ float shear; /* Shear spring stiffness. */ float bending; /* Flexion spring stiffness. */ - float sim_time; + float sim_time; int flags; /* flags, see CSIMSETT_FLAGS enum above. */ short solver_type; /* which solver should be used? */ short pad2; - float maxgoal; /* see SB */ + float 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; @@ -114,17 +119,22 @@ typedef struct SimulationSettings { int maxspringlen; /* in percent!; if tearing enabled, a spring will get cut */ int lastframe; /* frame on which simulation stops */ int firstframe; /* frame on which simulation starts */ -} SimulationSettings; +} +SimulationSettings; -typedef struct CollisionSettings { +typedef struct CollisionSettings +{ float epsilon; /* The radius of a particle in the cloth. */ float self_friction; /* Fiction/damping with self contact. */ float friction; /* Friction/damping applied on contact with other object.*/ short collision_type; /* which collision system is used. */ short loop_count; /* How many iterations for the collision loop. */ struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */ -} CollisionSettings; + int flags; /* collision flags defined in BKE_cloth.h */ + int pad; +} +CollisionSettings; /** @@ -137,21 +147,20 @@ typedef struct CollisionSettings { * 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 ClothSpring *springs; /* The springs connecting the mesh. */ - unsigned int numverts; /* The number of verts == m * n. */ - unsigned int numsprings; /* The count of springs. */ - unsigned char *facemarks; - char old_solver_type; /* Needed to allow call to free if solver changes. */ - char old_collision_type; /* Needed to allow call to free if collision changes.*/ - short pad7; +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; - int pad2; - int pad4; + unsigned char old_solver_type; + unsigned char pad2; + short pad3; void *tree; /* collision tree for this cloth object */ struct MFace *mfaces; void *implicit; /* our implicit solver connects to this pointer */ -} Cloth; +} +Cloth; #endif diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index c0925f4eae1..10d4d544e86 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3111,9 +3111,9 @@ static void object_panel_cloth(Object *ob) if(clmd) { - but = uiDefButBitI(block, TOG, CSIMSETT_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object", 170,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); + but = uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object", 170,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); - if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) + if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { Cloth *cloth = clmd->clothObject; int defCount; @@ -3149,8 +3149,8 @@ static void object_panel_cloth(Object *ob) /* GOAL STUFF */ uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CSIMSETT_FLAG_GOAL, REDRAWVIEW3D, "Use Goal", 10,70,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); - if (clmd->sim_parms.flags & CSIMSETT_FLAG_GOAL) + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Use Goal", 10,70,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); + if (clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { if(ob->type==OB_MESH) { @@ -3228,7 +3228,7 @@ static void object_panel_cloth_II(Object *ob) clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) + if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { Cloth *cloth = clmd->clothObject; char str[128]; @@ -3266,7 +3266,7 @@ static void object_panel_cloth_II(Object *ob) { uiDefBut(block, LABEL, 0, "No frames cached.", 10,120,290,20, NULL, 0.0, 0, 0, 0, ""); } - uiDefButBitI(block, TOG, CSIMSETT_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,50,145,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,50,145,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); uiBlockEndAlign(block); } } @@ -3283,7 +3283,7 @@ static void object_panel_cloth_III(Object *ob) clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - if (!(clmd->sim_parms.flags & CSIMSETT_FLAG_COLLOBJ)) + if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { Cloth *cloth = clmd->clothObject; char str[128]; @@ -3295,9 +3295,15 @@ static void object_panel_cloth_III(Object *ob) uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); uiBlockBeginAlign(block); - // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ - uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,10,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); - uiDefBut(block, LABEL, 0, "",160,10,150,20, NULL, 0.0, 0, 0, 0, ""); + uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,70,130,20, &clmd->coll_parms.flags, 0, 0, 0, 0, "Enable collisions with this object"); + if (clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + { + // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ + uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,30,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); + uiDefBut(block, LABEL, 0, "",160,30,150,20, NULL, 0.0, 0, 0, 0, ""); + } + else + uiDefBut(block, LABEL, 0, "",140,10,170,20, NULL, 0.0, 0, 0, 0, ""); uiBlockEndAlign(block); } } From 8dbc71020c9217af659874240d730ce58305bad6 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 21 Oct 2007 16:38:13 +0000 Subject: [PATCH 028/101] Disabled Cloth collision detection because of almost complete rewrite/seperation of the collision system like we discussed on the sprint. You can enable position caching/collision object now then enableing it as an deflection object. Problem: Some GUI glitch in the modifier stack, please help :) --- source/blender/blenkernel/BKE_cloth.h | 64 +--- source/blender/blenkernel/intern/cloth.c | 25 +- source/blender/blenkernel/intern/collision.c | 365 +++++++++---------- source/blender/blenkernel/intern/implicit.c | 2 +- source/blender/blenkernel/intern/kdop.c | 185 ++++------ source/blender/blenkernel/intern/modifier.c | 122 ++++++- source/blender/makesdna/DNA_cloth_types.h | 1 - source/blender/makesdna/DNA_modifier_types.h | 12 + source/blender/src/buttons_editing.c | 24 +- source/blender/src/buttons_object.c | 24 +- source/blender/src/transform_generics.c | 8 +- 11 files changed, 426 insertions(+), 406 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 692692dbf5a..1c5310c10d1 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -124,68 +124,8 @@ void implicit_set_positions ( ClothModifierData *clmd ); // from cloth.c, needed for modifier.c void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float ( *vertexCos ) [3], int numverts ); -// used in collision.c -typedef struct Tree -{ - struct Tree *nodes[4]; // 4 children --> quad-tree - struct Tree *parent; - struct Tree *nextLeaf; - struct Tree *prevLeaf; - float bv[26]; // Bounding volume of all nodes / we have 7 axes on a 14-DOP - unsigned int tri_index; // this saves the index of the face - int count_nodes; // how many nodes are used - int traversed; // how many nodes already traversed until this level? - int isleaf; -} -Tree; - -typedef struct Tree TreeNode; - -typedef struct BVH -{ - unsigned int numfaces; - unsigned int numverts; - ClothVertex *verts; // just a pointer to the original datastructure - MFace *mfaces; // just a pointer to the original datastructure - struct LinkNode *tree; - TreeNode *root; // TODO: saving the root --> is this really needed? YES! - TreeNode *leaf_tree; /* Tail of the leaf linked list. */ - TreeNode *leaf_root; /* Head of the leaf linked list. */ - float epsilon; /* epslion is used for inflation of the k-dop */ - int flags; /* bvhFlags */ -} -BVH; - -typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 ); - - -///////////////////////////////////////////////// -// collision.c //////////////////////////////////////////////// -// needed for implicit.c -void bvh_collision_response ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 ); -int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ); - -//////////////////////////////////////////////// - - -///////////////////////////////////////////////// -// kdop.c -//////////////////////////////////////////////// - -// needed for cloth.c -void bvh_free ( BVH * bvh ); -BVH *bvh_build ( ClothModifierData *clmd, float epsilon ); -LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr ); - -// needed for collision.c -int bvh_traverse ( ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response ); -void bvh_update ( ClothModifierData * clmd, BVH * bvh, int moving ); - -//////////////////////////////////////////////// - - ///////////////////////////////////////////////// // cloth.c @@ -200,7 +140,7 @@ void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int tot /* 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 ); +// typedef void ( *CM_COLLISION_OBJ ) ( ClothModifierData *clmd, int step, CM_COLLISION_RESPONSE collision_response ); /* This enum provides the IDs for our solvers. */ @@ -239,6 +179,7 @@ typedef struct Frame Frame; /* used for collisions in collision.c */ +/* typedef struct CollPair { unsigned int face1; // cloth face @@ -253,6 +194,7 @@ typedef struct CollPair unsigned int pointsb[4]; } CollPair; +*/ /* used for collisions in collision.c */ typedef struct EdgeCollPair diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index eb7454ccd42..d83c7bcb7f0 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -65,6 +65,7 @@ #include "BKE_mesh.h" #include "BKE_object.h" #include "BKE_cloth.h" +#include "BKE_collisions.h" #include "BKE_modifier.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" @@ -845,11 +846,11 @@ void cloth_free_modifier ( ClothModifierData *clmd ) cloth->springs = NULL; cloth->numsprings = 0; - +/* // free BVH collision tree if ( cloth->tree ) bvh_free ( ( BVH * ) cloth->tree ); - +*/ // we save our faces for collision objects if ( cloth->mfaces ) MEM_freeN ( cloth->mfaces ); @@ -1011,7 +1012,7 @@ static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMes verts->impulse_count = 0; VECCOPY ( verts->impulse, tnull ); } - clmd->clothObject->tree = bvh_build ( clmd,clmd->coll_parms.epsilon ); + // clmd->clothObject->tree = bvh_build ( dm, clmd->coll_parms.epsilon ); } @@ -1020,20 +1021,6 @@ static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMes } } -/* -helper function to get proper spring length -when object is rescaled -*/ -float cloth_globallen ( float *v1,float *v2,Object *ob ) -{ - float p1[3],p2[3]; - VECCOPY ( p1,v1 ); - Mat4MulVecfl ( ob->obmat, p1 ); - VECCOPY ( p2,v2 ); - Mat4MulVecfl ( ob->obmat, p2 ); - return VecLenf ( p1,p2 ); -} - // only meshes supported at the moment static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ) { @@ -1082,7 +1069,7 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh return 0; } - mvert = CDDM_get_verts ( dm ); + mvert = dm->getVertArray ( dm ); // CDDM_get_verts ( dm ); verts = clmd->clothObject->verts; /* set initial values */ @@ -1116,7 +1103,7 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh if ( solvers [clmd->sim_parms.solver_type].init ) solvers [clmd->sim_parms.solver_type].init ( ob, clmd ); - clmd->clothObject->tree = bvh_build ( clmd, clmd->coll_parms.epsilon ); + // clmd->clothObject->tree = bvh_build ( dm, clmd->coll_parms.epsilon ); cloth_cache_set_frame ( clmd, 1 ); } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index a5a382f7624..41823b0ad39 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -49,6 +49,7 @@ #include "BLI_arithb.h" #include "BLI_edgehash.h" #include "BLI_linklist.h" +#include "BKE_collisions.h" #include "BKE_curve.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" @@ -217,7 +218,7 @@ int gsl_poly_solve_quadratic (float a, float b, float c, float *x0, float *x1) * page 4, left column */ -int cloth_get_collision_time(float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3]) +int collisions_get_collision_time(float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3]) { int num_sols = 0; @@ -318,7 +319,7 @@ int cloth_get_collision_time(float a[3], float b[3], float c[3], float d[3], flo } // w3 is not perfect -void cloth_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) +void collisions_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) { double tempV1[3], tempV2[3], tempV4[3]; double a,b,c,d,e,f; @@ -372,8 +373,9 @@ DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal VecMulf(to, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); } -int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) +int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) { + /* unsigned int i = 0; int result = 0; LinkNode *search = NULL; @@ -386,20 +388,20 @@ int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData * cloth1 = clmd->clothObject; cloth2 = coll_clmd->clothObject; - search = clmd->coll_parms.collision_list; + // search = clmd->coll_parms.collision_list; while(search) { collpair = search->link; // compute barycentric coordinates for both collision points - cloth_compute_barycentric(collpair->pa, + collisions_compute_barycentric(collpair->pa, cloth1->verts[collpair->ap1].txold, cloth1->verts[collpair->ap2].txold, cloth1->verts[collpair->ap3].txold, &w1, &w2, &w3); - cloth_compute_barycentric(collpair->pb, + collisions_compute_barycentric(collpair->pb, cloth2->verts[collpair->bp1].txold, cloth2->verts[collpair->bp2].txold, cloth2->verts[collpair->bp3].txold, @@ -442,12 +444,6 @@ int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData * // printf("friction applied: %f\n", magtangent); // TODO check original code - /* - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,tangential); - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv,tangential); - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv,tangential); - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential); - */ } @@ -455,6 +451,7 @@ int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData * // printf("impulse: %f\n", impulse); + // face A VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); cloth1->verts[collpair->ap1].impulse_count++; @@ -464,63 +461,50 @@ int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData * VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); cloth1->verts[collpair->ap3].impulse_count++; - result = 1; + // face B + VECADDMUL(cloth2->verts[collpair->bp1].impulse, collpair->normal, u1 * impulse); + cloth2->verts[collpair->bp1].impulse_count++; - /* - if (overlap > ALMOST_ZERO) { - double I_mag = overlap * 0.1; - - impulse = -I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - - VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); - cloth1->verts[collpair->ap1].impulse_count++; - - VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); - cloth1->verts[collpair->ap2].impulse_count++; + VECADDMUL(cloth2->verts[collpair->bp2].impulse, collpair->normal, u2 * impulse); + cloth2->verts[collpair->bp2].impulse_count++; - VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); - cloth1->verts[collpair->ap3].impulse_count++; - } - */ + VECADDMUL(cloth2->verts[collpair->bp3].impulse, collpair->normal, u3 * impulse); + cloth2->verts[collpair->bp3].impulse_count++; + + + result = 1; // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case // Apply the impulse and increase impulse counters. - - /* - // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent); - VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); - // VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); - magtangent = Normalize(vrel_t_pre); - VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent)); - - VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre); - */ - - + } search = search->next; } - + return result; + */ + return 0; } -int cloth_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) + +int collisions_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) { } -int cloth_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) +int collisions_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) { } void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) { + /* CollPair *collpair = NULL; Cloth *cloth1=NULL, *cloth2=NULL; MFace *face1=NULL, *face2=NULL; @@ -618,11 +602,11 @@ void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clm // collpair->face1 = tree1->tri_index; // collpair->face2 = tree2->tri_index; - VECCOPY(collpair->normal, collpair->vector); - Normalize(collpair->normal); + // VECCOPY(collpair->normal, collpair->vector); + // Normalize(collpair->normal); + + // collpair->distance = distance; - collpair->distance = distance; - BLI_linklist_append(&clmd->coll_parms.collision_list, collpair); } else { @@ -634,9 +618,10 @@ void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clm MEM_freeN(collpair); } } + */ } -int cloth_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) +int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) { Cloth *cloth1, *cloth2; ClothVertex *verts1, *verts2; @@ -667,7 +652,7 @@ int cloth_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_cl return 0; } -void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +void collisions_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) { EdgeCollPair edgecollpair; Cloth *cloth1=NULL, *cloth2=NULL; @@ -773,7 +758,7 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co } - if(!cloth_are_edges_adjacent(clmd, coll_clmd, &edgecollpair)) + if(!collisions_are_edges_adjacent(clmd, coll_clmd, &edgecollpair)) { VECSUB(a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold); VECSUB(b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v); @@ -782,7 +767,7 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co VECSUB(e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold); VECSUB(f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v); - numsolutions = cloth_get_collision_time(a, b, c, d, e, f, solution); + numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution); for (k = 0; k < numsolutions; k++) { @@ -802,8 +787,9 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co } } -void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +void collisions_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) { + /* CollPair collpair; Cloth *cloth1=NULL, *cloth2=NULL; MFace *face1=NULL, *face2=NULL; @@ -872,7 +858,7 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold); VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v); - numsolutions = cloth_get_collision_time(a, b, c, d, e, f, solution); + numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution); for (k = 0; k < numsolutions; k++) { @@ -894,19 +880,22 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col } } + */ } -void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +void collisions_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) { + /* // TODO: check for adjacent - cloth_collision_moving_edges(clmd, coll_clmd, tree1, tree2); + collisions_collision_moving_edges(clmd, coll_clmd, tree1, tree2); - cloth_collision_moving_tris(clmd, coll_clmd, tree1, tree2); - cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); + collisions_collision_moving_tris(clmd, coll_clmd, tree1, tree2); + collisions_collision_moving_tris(coll_clmd, clmd, tree2, tree1); + */ } // move collision objects forward in time and update static bounding boxes -void cloth_update_collision_objects(float step) +void collisions_update_collision_objects(float step) { Base *base=NULL; ClothModifierData *coll_clmd=NULL; @@ -943,15 +932,15 @@ void cloth_update_collision_objects(float step) } // update BVH of collision object - bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING + // bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING } else - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); } } } -// CLOTH_MAX_THRESHOLD defines how much collision rounds/loops should be taken +// collisions_MAX_THRESHOLD defines how much collision rounds/loops should be taken #define CLOTH_MAX_THRESHOLD 10 // cloth - object collisions @@ -961,12 +950,13 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) ClothModifierData *coll_clmd=NULL; Cloth *cloth=NULL; Object *coll_ob=NULL; - BVH *cloth_bvh=NULL; + BVH *collisions_bvh=NULL; unsigned int i=0, j = 0, numfaces = 0, numverts = 0; unsigned int result = 0, ic = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; float tnull[3] = {0,0,0}; int ret = 0; + LinkNode *collision_list = NULL; if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) { @@ -974,7 +964,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) } cloth = clmd->clothObject; verts = cloth->verts; - cloth_bvh = (BVH *) cloth->tree; + collisions_bvh = (BVH *) cloth->tree; numfaces = clmd->clothObject->numfaces; numverts = clmd->clothObject->numverts; @@ -983,16 +973,15 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) //////////////////////////////////////////////////////////// // update cloth bvh - bvh_update(clmd, cloth_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function) + // bvh_update(clmd, collisions_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function) // update collision objects - cloth_update_collision_objects(step); + collisions_update_collision_objects(step); do { result = 0; ic = 0; - clmd->coll_parms.collision_list = NULL; // check all collision objects for (base = G.scene->base.first; base; base = base->next) @@ -1010,71 +999,57 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { BVH *coll_bvh = coll_clmd->clothObject->tree; - bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static); + // fill collision list + bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list); + + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence + { + result = 0; + + // result += collisions_collision_response_static_tris(clmd, coll_clmd, collision_list, 0); + + // result += collisions_collision_response_static_tris(coll_clmd, clmd, collision_list, 1); + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } + } + } + + // free collision list + if(collision_list) + { + LinkNode *search = collision_list; + while(search) + { + CollisionPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(collision_list,NULL); + + collision_list = NULL; + } } else - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); } } - // process all collisions (calculate impulses, TODO: also repulses if distance too short) - result = 1; - for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence - { - result = 0; - - // handle all collision objects - for (base = G.scene->base.first; base; base = base->next) - { - - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - if (!coll_clmd) - continue; - - // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) - { - if (coll_clmd->clothObject) - result += cloth_collision_response_static(clmd, coll_clmd); - else - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } - } - - // apply impulses in parallel - ic=0; - for(i = 0; i < numverts; i++) - { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if(verts[i].impulse_count) - { - VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); - VECCOPY(verts[i].impulse, tnull); - verts[i].impulse_count = 0; - - ic++; - ret++; - } - } - } - - // free collision list - if(clmd->coll_parms.collision_list) - { - LinkNode *search = clmd->coll_parms.collision_list; - while(search) - { - CollPair *coll_pair = search->link; - - MEM_freeN(coll_pair); - search = search->next; - } - BLI_linklist_free(clmd->coll_parms.collision_list,NULL); - - clmd->coll_parms.collision_list = NULL; - } - printf("ic: %d\n", ic); rounds++; } @@ -1100,7 +1075,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) // update cloth bvh - bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING + // bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING // update moving bvh for collision object once for (base = G.scene->base.first; base; base = base->next) @@ -1119,7 +1094,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { BVH *coll_bvh = coll_clmd->clothObject->tree; - bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING + // bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING } } @@ -1128,7 +1103,6 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { result = 0; ic = 0; - clmd->coll_parms.collision_list = NULL; // check all collision objects for (base = G.scene->base.first; base; base = base->next) @@ -1146,83 +1120,72 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { BVH *coll_bvh = coll_clmd->clothObject->tree; - bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving); + bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list); + + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence + { + result = 0; + + // handle all collision objects + + /* + if (coll_clmd->clothObject) + result += collisions_collision_response_moving_tris(clmd, coll_clmd); + else + printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + */ + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } + } + } + + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + + // update cloth bvh + // bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING + + + // free collision list + if(collision_list) + { + LinkNode *search = collision_list; + while(search) + { + CollisionPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(collision_list,NULL); + + collision_list = NULL; + } } else - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); } } - - // process all collisions (calculate impulses, TODO: also repulses if distance too short) - result = 1; - for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence - { - result = 0; - // handle all collision objects - for (base = G.scene->base.first; base; base = base->next) - { - - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - - if (!coll_clmd) - continue; - - // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) - { - if (coll_clmd->clothObject) - result += cloth_collision_response_moving_tris(clmd, coll_clmd); - else - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } - } - - // apply impulses in parallel - ic=0; - for(i = 0; i < numverts; i++) - { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if(verts[i].impulse_count) - { - VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); - VECCOPY(verts[i].impulse, tnull); - verts[i].impulse_count = 0; - - ic++; - ret++; - } - } - } - - - // verts come from clmd - for(i = 0; i < numverts; i++) - { - VECADD(verts[i].tx, verts[i].txold, verts[i].tv); - } - - // update cloth bvh - bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING - - - // free collision list - if(clmd->coll_parms.collision_list) - { - LinkNode *search = clmd->coll_parms.collision_list; - while(search) - { - CollPair *coll_pair = search->link; - - MEM_freeN(coll_pair); - search = search->next; - } - BLI_linklist_free(clmd->coll_parms.collision_list,NULL); - - clmd->coll_parms.collision_list = NULL; - } - printf("ic: %d\n", ic); rounds++; } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 1ee4475a6cc..2ce00d0e38c 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1492,7 +1492,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase } // call collision function - result = cloth_bvh_objcollision(clmd, step + dt, dt); + result = 0; // cloth_bvh_objcollision(clmd, step + dt, dt); // copy corrected positions back to simulation for(i = 0; i < numverts; i++) diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index b487f9a3b26..8b2540c7d8a 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -38,7 +38,6 @@ #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" @@ -59,7 +58,7 @@ #include "BKE_key.h" #include "BKE_mesh.h" #include "BKE_object.h" -#include "BKE_cloth.h" +#include "BKE_collisions.h" #include "BKE_modifier.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" @@ -165,13 +164,13 @@ static int size_threshold = 16; /* * Common methods for all algorithms */ -DO_INLINE void bvh_exchange(Tree **a, int i, int j) +void bvh_exchange(Tree **a, int i, int j) { Tree *t=a[i]; a[i]=a[j]; a[j]=t; } -DO_INLINE int floor_lg(int a) +int floor_lg(int a) { return (int)(floor(log(a)/log(2))); } @@ -294,7 +293,7 @@ static void bvh_introsort_loop (Tree **a, int lo, int hi, int depth_limit, int a } } -DO_INLINE void bvh_sort(Tree **a0, int begin, int end, int axis) +void bvh_sort(Tree **a0, int begin, int end, int axis) { if (begin < end) { @@ -303,7 +302,7 @@ DO_INLINE void bvh_sort(Tree **a0, int begin, int end, int axis) bvh_insertionsort(a, begin, end, axis); } } -DO_INLINE void bvh_sort_along_axis(Tree **face_list, int start, int end, int axis) +void bvh_sort_along_axis(Tree **face_list, int start, int end, int axis) { bvh_sort(face_list, start, end, axis); } @@ -330,7 +329,7 @@ void bvh_free(BVH * bvh) BLI_linklist_free(bvh->tree,NULL); bvh->tree = NULL; - + MEM_freeN(bvh); bvh = NULL; } @@ -338,7 +337,7 @@ void bvh_free(BVH * bvh) // 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) +int bvh_largest_axis(float *bv) { float middle_point[3]; @@ -362,7 +361,7 @@ DO_INLINE int bvh_largest_axis(float *bv) } // 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, Tree **tri, int numfaces, float *bv) +void bvh_calc_DOP_hull_from_faces(BVH * bvh, Tree **tri, int numfaces, float *bv) { float newmin,newmax; int i, j; @@ -386,9 +385,9 @@ DO_INLINE void bvh_calc_DOP_hull_from_faces(BVH * bvh, Tree **tri, int numfaces, } } -DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, Tree **tri, int numfaces, float *bv) +void bvh_calc_DOP_hull_static(BVH * bvh, Tree **tri, int numfaces, float *bv) { - ClothVertex *tempMVert = bvh->verts; + MVert *tempMVert = bvh->xold; MFace *tempMFace = bvh->mfaces; float *tempBV = bv; float newminmax; @@ -415,7 +414,7 @@ DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, Tree **tri, int numfaces, flo // for all Axes. for (i = KDOP_START; i < KDOP_END; i++) { - newminmax = INPR(tempMVert[temp].txold, KDOP_AXES[i]); + newminmax = INPR(tempMVert[temp].co, KDOP_AXES[i]); if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0)) tempBV[(2 * i)] = newminmax; if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0)) @@ -425,9 +424,10 @@ DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, Tree **tri, int numfaces, flo } } -DO_INLINE void bvh_calc_DOP_hull_moving(BVH * bvh, Tree **tri, int numfaces, float *bv) +void bvh_calc_DOP_hull_moving(BVH * bvh, Tree **tri, int numfaces, float *bv) { - ClothVertex *tempMVert = bvh->verts; + MVert *tempMVert = bvh->xold; + MVert *tempMVert2 = bvh->x; MFace *tempMFace = bvh->mfaces; float *tempBV = bv; float newminmax; @@ -454,13 +454,13 @@ DO_INLINE void bvh_calc_DOP_hull_moving(BVH * bvh, Tree **tri, int numfaces, flo // for all Axes. for (i = KDOP_START; i < KDOP_END; i++) { - newminmax = INPR(tempMVert[temp].txold, KDOP_AXES[i]); + newminmax = INPR(tempMVert[temp].co, KDOP_AXES[i]); if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0)) tempBV[(2 * i)] = newminmax; if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0)) tempBV[(2 * i) + 1] = newminmax; - newminmax = INPR(tempMVert[temp].tx, KDOP_AXES[i]); + newminmax = INPR(tempMVert2[temp].co, KDOP_AXES[i]); if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0)) tempBV[(2 * i)] = newminmax; if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0)) @@ -538,25 +538,18 @@ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsign return; } -BVH *bvh_build (ClothModifierData *clmd, float epsilon) +BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xold, unsigned int numverts, float epsilon) { unsigned int i = 0, j = 0, k = 0; Tree **face_list=NULL; BVH *bvh=NULL; - Cloth *cloth = NULL; Tree *tree=NULL; LinkNode *nlink = NULL; EdgeHash *edgehash = NULL; - LinkNode *springs = NULL; unsigned int numsprings = 0; MFace *mface = NULL; - if(!clmd) - return NULL; - - cloth = clmd->clothObject; - - if(!cloth) + if(!dm) return NULL; bvh = MEM_callocN(sizeof(BVH), "BVH"); @@ -566,20 +559,18 @@ BVH *bvh_build (ClothModifierData *clmd, float epsilon) return NULL; } - springs = cloth->springs; - numsprings = cloth->numsprings; - bvh->flags = 0; bvh->leaf_tree = NULL; bvh->leaf_root = NULL; bvh->tree = NULL; bvh->epsilon = epsilon; - bvh->numfaces = cloth->numfaces; - mface = bvh->mfaces = cloth->mfaces; + bvh->numfaces = dm->getNumFaces(dm); + mface = bvh->mfaces = dm->getFaceArray(dm); - bvh->numverts = cloth->numverts; - bvh->verts = cloth->verts; + bvh->numverts = numverts; + bvh->x = x; + bvh->xold = xold; tree = (Tree *)MEM_callocN(sizeof(Tree), "Tree"); // TODO: check succesfull alloc BLI_linklist_append(&bvh->tree, tree); @@ -610,21 +601,6 @@ BVH *bvh_build (ClothModifierData *clmd, float epsilon) } else { - // create spring tearing hash - /* - edgehash = BLI_edgehash_new(); - if(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) - for(i = 0; i < numsprings; i++) - { - if((springs[i].flags & CSPRING_FLAG_DEACTIVATE) - &&(!BLI_edgehash_haskey(edgehash, springs[i].ij, springs[i].kl))) - { - BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL); - BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL); - } - } - */ - // create face boxes face_list = MEM_callocN (bvh->numfaces * sizeof (Tree *), "Tree"); if (face_list == NULL) @@ -637,50 +613,43 @@ BVH *bvh_build (ClothModifierData *clmd, float epsilon) // create face boxes for(i = 0, k = 0; i < bvh->numfaces; i++) { - LinkNode *tnlink; - /* - if((!BLI_edgehash_haskey(edgehash, mface[i].v1, mface[i].v2)) - &&(!BLI_edgehash_haskey(edgehash, mface[i].v2, mface[i].v3)) - &&(!BLI_edgehash_haskey(edgehash, mface[i].v3, mface[i].v4)) - &&(!BLI_edgehash_haskey(edgehash, mface[i].v4, mface[i].v1))) - */ + LinkNode *tnlink = NULL; + + tree = (Tree *)MEM_callocN(sizeof(Tree), "Tree"); + // 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) { - tree = (Tree *)MEM_callocN(sizeof(Tree), "Tree"); - // 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; + 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 @@ -699,7 +668,7 @@ BVH *bvh_build (ClothModifierData *clmd, float epsilon) } // bvh_overlap - is it possbile for 2 bv's to collide ? -DO_INLINE int bvh_overlap(float *bv1, float *bv2) +int bvh_overlap(float *bv1, float *bv2) { int i = 0; for (i = KDOP_START; i < KDOP_END; i++) @@ -725,18 +694,10 @@ DO_INLINE int bvh_overlap(float *bv1, float *bv2) * every other triangle that doesn't require any realloc, but uses * much memory */ -int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response) +int bvh_traverse(Tree * tree1, Tree * tree2, LinkNode *collision_list) { - int i = 0, ret=0; - - /* - // Shouldn't be possible - if(!tree1 || !tree2) - { - printf("Error: no tree there\n"); - return 0; -} - */ + int i = 0, ret = 0; + if (bvh_overlap(tree1->bv, tree2->bv)) { // Check if this node in the first tree is a leaf @@ -745,10 +706,14 @@ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * // Check if this node in the second tree a leaf if (tree2->isleaf) { - // Provide the collision response. + // save potential colliding triangles + CollisionPair *collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); + + collpair->indexA = tree1->tri_index; + collpair->indexB = tree2->tri_index; + + BLI_linklist_append(&collision_list, collpair); - if(collision_response) - collision_response (clmd, coll_clmd, tree1, tree2); return 1; } else @@ -757,7 +722,7 @@ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree2->nodes[i] && bvh_traverse (clmd, coll_clmd, tree1, tree2->nodes[i], step, collision_response)) + if (tree2->nodes[i] && bvh_traverse (tree1, tree2->nodes[i], collision_list)) ret = 1; } } @@ -768,7 +733,7 @@ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree1->nodes [i] && bvh_traverse (clmd, coll_clmd, tree1->nodes[i], tree2, step, collision_response)) + if (tree1->nodes [i] && bvh_traverse (tree1->nodes[i], tree2, collision_list)) ret = 1; } } @@ -809,12 +774,18 @@ void bvh_join(Tree * tree) } // update static bvh -void bvh_update(ClothModifierData *clmd, BVH * bvh, int moving) +// needs new positions in bvh->x, bvh->xold +void bvh_update(DerivedMesh *dm, BVH * bvh, int moving) { TreeNode *leaf, *parent; int traversecheck = 1; // if this is zero we don't go further unsigned int j = 0; + if(bvh->numfaces != dm->getNumFaces(dm)) + return; + + bvh->mfaces = dm->getFaceArray(dm); + for (leaf = bvh->leaf_root; leaf; leaf = leaf->nextLeaf) { traversecheck = 1; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index bb6297361fe..59bd4b8253d 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -72,6 +72,7 @@ #include "BKE_main.h" #include "BKE_anim.h" #include "BKE_bad_level_calls.h" +#include "BKE_collisions.h" #include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_utildefines.h" @@ -4920,7 +4921,7 @@ static void clothModifier_updateDepgraph( CustomDataMask clothModifier_requiredDataMask(ModifierData *md) { - ClothModifierData *clmd = (HookModifierData *)md; + ClothModifierData *clmd = (ClothModifierData *)md; CustomDataMask dataMask = 0; /* ask for vertexgroups if we need them */ @@ -4948,6 +4949,113 @@ static void clothModifier_freeData(ModifierData *md) } } +/* Collision */ + +static void collisionModifier_initData(ModifierData *md) +{ + CollisionModifierData *collmd = (CollisionModifierData*) md; + + collmd->x = NULL; + collmd->xold = 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->xold) + MEM_freeN(collmd->xold); + + collmd->x = NULL; + collmd->xold = NULL; + collmd->time = -1; + collmd->numverts = 0; + collmd->tree = NULL; + } +} + +static void collisionModifier_deformVerts( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) +{ + CollisionModifierData *collmd = (CollisionModifierData*) md; + DerivedMesh *dm = NULL; + MVert *mvert = 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(dm) + { + CDDM_apply_vert_coords(dm, vertexCos); + CDDM_calc_normals(dm); + + + current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); + + if(current_time > collmd->time) + { + numverts = dm->getNumVerts ( dm ); + + // check if mesh has changed + if(collmd->x && (numverts != collmd->numverts)) + collisionModifier_freeData(collmd); + + if(collmd->time == -1) // first time + { + collmd->x = dm->dupVertArray(dm); + collmd->xold = dm->dupVertArray(dm); + collmd->numverts = numverts; + + // TODO: epsilon + // create bounding box hierarchy + collmd->tree = bvh_build(dm, collmd->x, collmd->xold, numverts, 0.01); + } + else if(numverts == collmd->numverts) + { + // put positions to old positions + tempVert = collmd->xold; + collmd->xold = collmd->x; + collmd->x = tempVert; + + memcpy(collmd->x, dm->getVertArray(dm), numverts*sizeof(MVert)); + + for ( i = 0; i < numverts; i++ ) + { + // we save global positions + Mat4MulVecfl ( ob->obmat, collmd->x[i].co ); + } + + bvh_update(dm, collmd->tree, 0); // recalc static bounding boxes + } + + collmd->time = current_time; + } + } + + if(dm) + dm->release(dm); +} + +static int collisionModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + /* Boolean */ static void booleanModifier_copyData(ModifierData *md, ModifierData *target) @@ -5247,6 +5355,16 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) // mti->copyData = clothModifier_copyData; mti->deformVerts = clothModifier_deformVerts; mti->updateDepgraph = clothModifier_updateDepgraph; + + mti = INIT_TYPE(Collision); + mti->type = eModifierTypeType_OnlyDeform; + mti->initData = collisionModifier_initData; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_RequiresOriginalData; + mti->dependsOnTime = collisionModifier_dependsOnTime; + mti->freeData = collisionModifier_freeData; + mti->deformVerts = collisionModifier_deformVerts; + // mti->copyData = collisionModifier_copyData; mti = INIT_TYPE(Boolean); mti->type = eModifierTypeType_Nonconstructive; @@ -5449,7 +5567,7 @@ int modifiers_isSoftbodyEnabled(Object *ob) return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -ModifierData * modifiers_isClothEnabled(Object *ob) +ModifierData *modifiers_isClothEnabled(Object *ob) { ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 7f5527466e4..27f7431a9cf 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -130,7 +130,6 @@ typedef struct CollisionSettings 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 */ int pad; } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 4c9fbdcc7b7..e6e73ea7d07 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -31,6 +31,7 @@ typedef enum ModifierType { eModifierType_Smooth, eModifierType_Cast, eModifierType_Cloth, + eModifierType_Collision, NUM_MODIFIER_TYPES } ModifierType; @@ -346,6 +347,17 @@ typedef struct ClothModifierData { CollisionSettings coll_parms; /* definition is in DNA_cloth_types.h */ } ClothModifierData; +typedef struct CollisionModifierData { + ModifierData modifier; + + struct MVert *x; + struct MVert *xold; + + unsigned int numverts; + float time; + void *tree; /* collision tree for this cloth object */ +} CollisionModifierData; + typedef enum { eBooleanModifierOp_Intersect, eBooleanModifierOp_Union, diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 194241c4380..13aae388106 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -950,7 +950,9 @@ static uiBlock *modifiers_add_menu(void *ob_v) ModifierTypeInfo *mti = modifierType_getInfo(i); /* Only allow adding through appropriate other interfaces */ - if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_Cloth)) continue; + if(ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue; + + if(ELEM(i, eModifierType_Cloth, eModifierType_Collision)) continue; if((mti->flags&eModifierTypeFlag_AcceptsCVs) || (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) { @@ -1483,7 +1485,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiBlockSetCol(block, TH_AUTO); /* open/close icon */ - if (!isVirtual) { + if (!isVirtual && md->type!=eModifierType_Collision) { uiBlockSetEmboss(block, UI_EMBOSSN); uiDefIconButBitI(block, ICONTOG, eModifierMode_Expanded, B_MODIFIER_REDRAW, VICON_DISCLOSURE_TRI_RIGHT, x-10, y-2, 20, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Modifier"); } @@ -1500,8 +1502,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiBlockBeginAlign(block); uiDefBut(block, TEX, B_MODIFIER_REDRAW, "", x+10, y-1, buttonWidth-60, 19, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name"); - /* Softbody not allowed in this situation, enforce! */ - if (md->type!=eModifierType_Softbody || !(ob->pd && ob->pd->deflect)) { + /* Softbody not allowed in this situation, enforce! */ + if ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) { uiDefIconButBitI(block, TOG, eModifierMode_Render, B_MODIFIER_RECALC, ICON_SCENE, x+10+buttonWidth-60, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering"); uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_MODIFIER_RECALC, VICON_VIEW3D, x+10+buttonWidth-40, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display"); if (mti->flags&eModifierTypeFlag_SupportsEditmode) { @@ -1540,9 +1542,13 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiButSetFunc(but, modifiers_moveDown, ob, md); uiBlockSetEmboss(block, UI_EMBOSSN); - - but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier"); - uiButSetFunc(but, modifiers_del, ob, md); + + // deletion over the deflection panel + if(md->type!=eModifierType_Collision) + { + but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier"); + uiButSetFunc(but, modifiers_del, ob, md); + } uiBlockSetCol(block, TH_AUTO); } @@ -1603,6 +1609,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco height = 26; } else if (md->type==eModifierType_Cloth) { height = 26; + } else if (md->type==eModifierType_Collision) { + height = 19; } else if (md->type==eModifierType_Boolean) { height = 48; } else if (md->type==eModifierType_Array) { @@ -1614,7 +1622,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco y -= 18; - if (!isVirtual) { + if (!isVirtual && (md->type!=eModifierType_Collision)) { uiBlockBeginAlign(block); but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack"); uiButSetFunc(but, modifiers_applyModifier, ob, md); diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 10d4d544e86..3b232f49001 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2741,10 +2741,29 @@ void do_effects_panels(unsigned short event) } +/* Panel for collision */ +static void object_collision__enabletoggle(void *ob_v, void *arg2) +{ + Object *ob = ob_v; + ModifierData *md = modifiers_findByType(ob, eModifierType_Collision); + + if (!md) { + md = modifier_new(eModifierType_Collision); + BLI_addhead(&ob->modifiers, md); + } + else { + BLI_remlink(&ob->modifiers, md); + modifier_free(md); + } + + allqueue(REDRAWBUTSEDIT, 0); +} + /* Panel for particle interaction settings */ static void object_panel_fields(Object *ob) { uiBlock *block; + uiBut *but; block= uiNewBlock(&curarea->uiblocks, "object_panel_fields", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "Fields and Deflection", "Physics", 0, 0, 318, 204)==0) return; @@ -2804,7 +2823,8 @@ static void object_panel_fields(Object *ob) /* only meshes collide now */ if(ob->type==OB_MESH) { - uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision"); + but = uiDefButBitS(block, TOG, 1, B_REDR, "Deflection/Collision",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Make object collision object for dynamics"); + uiButSetFunc(but, object_collision__enabletoggle, ob, NULL); if(pd->deflect) { uiDefBut(block, LABEL, 0, "Particles", 160,140,150,20, NULL, 0.0, 0, 0, 0, ""); @@ -3129,7 +3149,7 @@ static void object_panel_cloth(Object *ob) uiBlockBeginAlign(block); uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility"); - uiDefButI(block, NUM, B_CLOTH_RENEW, "Steps per Frame:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); + uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=>better=>slower)"); uiBlockEndAlign(block); uiBlockBeginAlign(block); uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Spring damping"); diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index 9031ce48707..9f45bd7aaa0 100644 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -426,8 +426,8 @@ void recalcData(TransInfo *t) if(modifiers_isSoftbodyEnabled(base->object)) { base->object->softflag |= OB_SB_REDO; } - else if(modifiers_isClothEnabled(ob)) { - cloth_free_modifier(modifiers_isClothEnabled(ob)); + else if((clmd = (ClothModifierData *)modifiers_isClothEnabled(ob))) { + cloth_free_modifier(clmd); } } @@ -470,8 +470,8 @@ void recalcData(TransInfo *t) if(modifiers_isSoftbodyEnabled(ob)) { ob->softflag |= OB_SB_REDO; } - else if(modifiers_isClothEnabled(ob)) { - cloth_free_modifier(modifiers_isClothEnabled(ob)); + else if((clmd = (ClothModifierData *)modifiers_isClothEnabled(ob))) { + cloth_free_modifier(clmd); } } From c8fe3c95a344d401ec3cb3d0be132be00a49a79c Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 21 Oct 2007 16:39:07 +0000 Subject: [PATCH 029/101] Forgot some new file for seperated collisions --- source/blender/blenkernel/BKE_collisions.h | 103 +++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 source/blender/blenkernel/BKE_collisions.h diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h new file mode 100644 index 00000000000..edd86f0f5f6 --- /dev/null +++ b/source/blender/blenkernel/BKE_collisions.h @@ -0,0 +1,103 @@ +/** + * 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 +#include +#include +/* types */ +#include "BLI_linklist.h" +#include "BKE_DerivedMesh.h" +#include "BKE_object.h" +#include "BKE_DerivedMesh.h" + +// used in kdop.c and collision.c +typedef struct Tree +{ + struct Tree *nodes[4]; // 4 children --> quad-tree + struct Tree *parent; + struct Tree *nextLeaf; + struct Tree *prevLeaf; + float bv[26]; // Bounding volume of all nodes / we have 7 axes on a 14-DOP + unsigned int tri_index; // this saves the index of the face + int count_nodes; // how many nodes are used + int traversed; // how many nodes already traversed until this level? + int isleaf; +} +Tree; + +typedef struct Tree TreeNode; + +typedef struct BVH +{ + unsigned int numfaces; + unsigned int numverts; + MVert *x; // position of verts at time n + MVert *xold; // position of verts at time n-1 + MFace *mfaces; // just a pointer to the original datastructure + struct LinkNode *tree; + TreeNode *root; // TODO: saving the root --> is this really needed? YES! + TreeNode *leaf_tree; /* Tail of the leaf linked list. */ + TreeNode *leaf_root; /* Head of the leaf linked list. */ + float epsilon; /* epslion is used for inflation of the k-dop */ + int flags; /* bvhFlags */ +} +BVH; + +/* used for collisions in kdop.c and also collision.c*/ +typedef struct CollisionPair +{ + unsigned int indexA, indexB; +} +CollisionPair; + + +///////////////////////////////////////////////// +// forward declarations +///////////////////////////////////////////////// + +void bvh_free ( BVH *bvh ); +BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xold, unsigned int numverts, float epsilon); + +int bvh_traverse(Tree *tree1, Tree *tree2, LinkNode *collision_list); +void bvh_update(DerivedMesh *dm, BVH * bvh, int moving); + +LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr ); + + +///////////////////////////////////////////////// + +#endif + From 5bd2f5b08e006cb0f0fd281723ece3c6939b84d5 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 21 Oct 2007 16:53:25 +0000 Subject: [PATCH 030/101] Fixed read/writing of blendfiles with collision modifier (saving not supported itm), also changed naming --- source/blender/blenkernel/BKE_collisions.h | 4 ++-- source/blender/blenkernel/intern/kdop.c | 12 +++++------ source/blender/blenkernel/intern/modifier.c | 22 ++++++++++---------- source/blender/blenloader/intern/readfile.c | 9 ++++++++ source/blender/makesdna/DNA_modifier_types.h | 2 +- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h index edd86f0f5f6..7c9ced262a8 100644 --- a/source/blender/blenkernel/BKE_collisions.h +++ b/source/blender/blenkernel/BKE_collisions.h @@ -64,8 +64,8 @@ typedef struct BVH { unsigned int numfaces; unsigned int numverts; - MVert *x; // position of verts at time n - MVert *xold; // position of verts at time n-1 + MVert *xnew; // position of verts at time n + MVert *x; // position of verts at time n-1 MFace *mfaces; // just a pointer to the original datastructure struct LinkNode *tree; TreeNode *root; // TODO: saving the root --> is this really needed? YES! diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 8b2540c7d8a..1e17ee4f03e 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -387,7 +387,7 @@ void bvh_calc_DOP_hull_from_faces(BVH * bvh, Tree **tri, int numfaces, float *bv void bvh_calc_DOP_hull_static(BVH * bvh, Tree **tri, int numfaces, float *bv) { - MVert *tempMVert = bvh->xold; + MVert *tempMVert = bvh->x; MFace *tempMFace = bvh->mfaces; float *tempBV = bv; float newminmax; @@ -426,8 +426,8 @@ void bvh_calc_DOP_hull_static(BVH * bvh, Tree **tri, int numfaces, float *bv) void bvh_calc_DOP_hull_moving(BVH * bvh, Tree **tri, int numfaces, float *bv) { - MVert *tempMVert = bvh->xold; - MVert *tempMVert2 = bvh->x; + MVert *tempMVert = bvh->x; + MVert *tempMVert2 = bvh->xnew; MFace *tempMFace = bvh->mfaces; float *tempBV = bv; float newminmax; @@ -538,7 +538,7 @@ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsign return; } -BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xold, unsigned int numverts, float epsilon) +BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xnew, unsigned int numverts, float epsilon) { unsigned int i = 0, j = 0, k = 0; Tree **face_list=NULL; @@ -569,8 +569,8 @@ BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xold, unsigned int numverts, f mface = bvh->mfaces = dm->getFaceArray(dm); bvh->numverts = numverts; + bvh->xnew = xnew; bvh->x = x; - bvh->xold = xold; tree = (Tree *)MEM_callocN(sizeof(Tree), "Tree"); // TODO: check succesfull alloc BLI_linklist_append(&bvh->tree, tree); @@ -774,7 +774,7 @@ void bvh_join(Tree * tree) } // update static bvh -// needs new positions in bvh->x, bvh->xold +// needs new positions in bvh->x, bvh->xnew void bvh_update(DerivedMesh *dm, BVH * bvh, int moving) { TreeNode *leaf, *parent; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 59bd4b8253d..cb7fccd11c1 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4956,7 +4956,7 @@ static void collisionModifier_initData(ModifierData *md) CollisionModifierData *collmd = (CollisionModifierData*) md; collmd->x = NULL; - collmd->xold = NULL; + collmd->xnew = NULL; collmd->time = -1; collmd->numverts = 0; collmd->tree = NULL; @@ -4972,11 +4972,11 @@ static void collisionModifier_freeData(ModifierData *md) bvh_free(collmd->tree); if(collmd->x) MEM_freeN(collmd->x); - if(collmd->xold) - MEM_freeN(collmd->xold); + if(collmd->xnew) + MEM_freeN(collmd->xnew); collmd->x = NULL; - collmd->xold = NULL; + collmd->xnew = NULL; collmd->time = -1; collmd->numverts = 0; collmd->tree = NULL; @@ -5018,26 +5018,26 @@ static void collisionModifier_deformVerts( if(collmd->time == -1) // first time { collmd->x = dm->dupVertArray(dm); - collmd->xold = dm->dupVertArray(dm); + collmd->xnew = dm->dupVertArray(dm); collmd->numverts = numverts; // TODO: epsilon // create bounding box hierarchy - collmd->tree = bvh_build(dm, collmd->x, collmd->xold, numverts, 0.01); + collmd->tree = bvh_build(dm, collmd->x, collmd->xnew, numverts, 0.01); } else if(numverts == collmd->numverts) { // put positions to old positions - tempVert = collmd->xold; - collmd->xold = collmd->x; - collmd->x = tempVert; + tempVert = collmd->x; + collmd->x = collmd->xnew; + collmd->xnew = tempVert; - memcpy(collmd->x, dm->getVertArray(dm), numverts*sizeof(MVert)); + memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); for ( i = 0; i < numverts; i++ ) { // we save global positions - Mat4MulVecfl ( ob->obmat, collmd->x[i].co ); + Mat4MulVecfl ( ob->obmat, collmd->xnew[i].co ); } bvh_update(dm, collmd->tree, 0); // recalc static bounding boxes diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 83bae60df30..99f0885b435 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2888,6 +2888,15 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) printf ("direct_link_modifiers: read cloth baked_data.\n"); } } + else if (md->type==eModifierType_Collision) { + CollisionModifierData *collmd = (CollisionModifierData*) md; + + collmd->x = NULL; + collmd->xnew = NULL; + collmd->time = -1; + collmd->numverts = 0; + collmd->tree = NULL; + } else if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index e6e73ea7d07..81e27afbac4 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -351,7 +351,7 @@ typedef struct CollisionModifierData { ModifierData modifier; struct MVert *x; - struct MVert *xold; + struct MVert *xnew; unsigned int numverts; float time; From dfd9c71b56bf7b45f7764ca4a6968724bb243387 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 21 Oct 2007 17:20:31 +0000 Subject: [PATCH 031/101] Code comments add to collision interface --- source/blender/blenkernel/BKE_collisions.h | 7 +- source/blender/blenkernel/intern/cloth.c | 123 +-------------------- source/blender/src/buttons_object.c | 2 +- 3 files changed, 9 insertions(+), 123 deletions(-) diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h index 7c9ced262a8..0536a72d74b 100644 --- a/source/blender/blenkernel/BKE_collisions.h +++ b/source/blender/blenkernel/BKE_collisions.h @@ -88,10 +88,15 @@ CollisionPair; // forward declarations ///////////////////////////////////////////////// -void bvh_free ( BVH *bvh ); +// builds bounding volume hierarchy BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xold, unsigned int numverts, float epsilon); +// frees the same +void bvh_free ( BVH *bvh ); +// checks two bounding volume hierarchies for potential collisions and returns some list with those int bvh_traverse(Tree *tree1, Tree *tree2, LinkNode *collision_list); + +// update bounding volumes, needs updated positions in bvh->x void bvh_update(DerivedMesh *dm, BVH * bvh, int moving); LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr ); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index d83c7bcb7f0..dce36f543ee 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -621,8 +621,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, Frame *frame = NULL; LinkNode *search = NULL; float deltaTime = current_time - clmd->sim_parms.sim_time; - - + // only be active during a specific period: // that's "first frame" and "last frame" on GUI if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) ) @@ -671,59 +670,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame; clmd->sim_parms.sim_time = current_time; - - // check if cloth object was some collision object before and needs freeing now - if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) && ( clmd->clothObject != NULL ) && ( clmd->clothObject->old_solver_type == 255 ) ) - { - // temporary set CSIMSETT_FLAG_COLLOBJ flag for proper freeing - clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; - cloth_free_modifier ( clmd ); - clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_COLLOBJ; - } - - // This is for collisions objects: check special case CSIMSETT_FLAG_COLLOBJ - if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) - { - // save next position + time - if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) ) - { - if ( !collobj_from_object ( ob, clmd, dm, vertexCos, framenr ) ) - { - clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; - cloth_free_modifier ( clmd ); - return; - } - - if ( clmd->clothObject == NULL ) - return; - - cloth = clmd->clothObject; - } - - // Save old position - clmd->sim_parms.sim_time_old = clmd->sim_parms.sim_time; - clmd->sim_parms.sim_time = current_time; - - verts = cloth->verts; - - for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) - { - // Save the previous position. - VECCOPY ( verts->xold, verts->x ); - VECCOPY ( verts->txold, verts->x ); - - // Get the current position. - VECCOPY ( verts->x, vertexCos[i] ); - Mat4MulVecfl ( ob->obmat, verts->x ); - - // Compute the vertices "velocity". - // (no dt correction here because of float error) - VECSUB ( verts->v, verts->x, verts->xold ); - } - - return; - } - + if ( deltaTime == 1.0f ) { if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) ) @@ -955,72 +902,6 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short } } -// only meshes supported at the moment -/* collision objects */ -static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ) -{ - unsigned int i; - MVert *mvert = NULL; - ClothVertex *verts = NULL; - float tnull[3] = {0,0,0}; - - /* If we have a clothObject, free it. */ - if ( clmd->clothObject != NULL ) - cloth_free_modifier ( clmd ); - - /* Allocate a new cloth object. */ - clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" ); - if ( clmd->clothObject ) - { - clmd->clothObject->old_solver_type = 255; - // clmd->clothObject->old_collision_type = 255; - } - else if ( clmd->clothObject == NULL ) - { - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject." ); - return 0; - } - - switch ( ob->type ) - { - case OB_MESH: - - // mesh input objects need DerivedMesh - if ( !dm ) - return 0; - - cloth_from_mesh ( ob, clmd, dm ); - - if ( clmd->clothObject != NULL ) - { - if ( !dm ) return 0; - if ( !dm->getNumVerts ( dm ) || !dm->getNumFaces ( dm ) ) return 0; - - mvert = dm->getVertArray ( dm ); - verts = clmd->clothObject->verts; - numverts = clmd->clothObject->numverts = dm->getNumVerts ( dm ); - - for ( i = 0; i < numverts; i++, verts++ ) - { - VECCOPY ( verts->x, mvert[i].co ); - Mat4MulVecfl ( ob->obmat, verts->x ); - verts->flags = 0; - VECCOPY ( verts->xold, verts->x ); - VECCOPY ( verts->txold, verts->x ); - VECCOPY ( verts->tx, verts->x ); - VecMulf ( verts->v, 0.0f ); - verts->impulse_count = 0; - VECCOPY ( verts->impulse, tnull ); - } - // clmd->clothObject->tree = bvh_build ( dm, clmd->coll_parms.epsilon ); - - } - - return 1; - default: return 0; // TODO - we do not support changing meshes - } -} - // only meshes supported at the moment static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ) { diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 3b232f49001..8bca629eeac 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3131,7 +3131,7 @@ static void object_panel_cloth(Object *ob) if(clmd) { - but = uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object", 170,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); + // but = uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object", 170,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { From 5a6ffd8441a092906bc445f7084d585624a7367b Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 22 Oct 2007 22:50:32 +0000 Subject: [PATCH 032/101] WIP commit, (just in case my HD breaks down). Don't expect anything to work. Code crashes and sim doesn't work ;) --- source/blender/blenkernel/BKE_cloth.h | 4 +- source/blender/blenkernel/BKE_collisions.h | 29 +- source/blender/blenkernel/BKE_modifier.h | 2 +- source/blender/blenkernel/intern/cloth.c | 143 +-- source/blender/blenkernel/intern/collision.c | 859 +------------------ source/blender/blenkernel/intern/implicit.c | 839 ++++++++++++++++++ source/blender/blenkernel/intern/kdop.c | 171 ++-- source/blender/blenkernel/intern/modifier.c | 80 +- source/blender/blenloader/intern/readfile.c | 3 +- source/blender/makesdna/DNA_cloth_types.h | 8 +- source/blender/makesdna/DNA_modifier_types.h | 8 +- source/blender/makesdna/DNA_object_force.h | 1 - source/blender/src/editobject.c | 1 + 13 files changed, 1125 insertions(+), 1023 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 1c5310c10d1..19851321b30 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -122,7 +122,7 @@ void cloth_free_modifier ( ClothModifierData *clmd ); void implicit_set_positions ( ClothModifierData *clmd ); // from cloth.c, needed for modifier.c -void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float ( *vertexCos ) [3], int numverts ); +DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm); //////////////////////////////////////////////// @@ -132,9 +132,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, fl //////////////////////////////////////////////// void cloth_free_modifier ( ClothModifierData *clmd ); void cloth_init ( ClothModifierData *clmd ); -void cloth_deform_verts ( struct Object *ob, float framenr, float ( *vertexCos ) [3], int numVerts, void *derivedData, ClothModifierData *clmd ); void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int totface ); - //////////////////////////////////////////////// diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h index 0536a72d74b..8c7933f3434 100644 --- a/source/blender/blenkernel/BKE_collisions.h +++ b/source/blender/blenkernel/BKE_collisions.h @@ -44,21 +44,21 @@ #include "BKE_DerivedMesh.h" // used in kdop.c and collision.c -typedef struct Tree +typedef struct CollisionTree { - struct Tree *nodes[4]; // 4 children --> quad-tree - struct Tree *parent; - struct Tree *nextLeaf; - struct Tree *prevLeaf; + 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; } -Tree; +CollisionTree; -typedef struct Tree TreeNode; +typedef struct CollisionTree TreeNode; typedef struct BVH { @@ -79,7 +79,7 @@ BVH; /* used for collisions in kdop.c and also collision.c*/ typedef struct CollisionPair { - unsigned int indexA, indexB; + int point_indexA[4], point_indexB[4]; } CollisionPair; @@ -89,18 +89,21 @@ CollisionPair; ///////////////////////////////////////////////// // builds bounding volume hierarchy -BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xold, unsigned int numverts, float epsilon); +BVH *bvh_build (MFace *mfaces, unsigned int numfaces, MVert *x, MVert *xnew, unsigned int numverts, float epsilon); // frees the same void bvh_free ( BVH *bvh ); // checks two bounding volume hierarchies for potential collisions and returns some list with those -int bvh_traverse(Tree *tree1, Tree *tree2, LinkNode *collision_list); +int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision_list); // update bounding volumes, needs updated positions in bvh->x -void bvh_update(DerivedMesh *dm, BVH * bvh, int moving); +void bvh_update(BVH * bvh, int moving); -LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr ); +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); ///////////////////////////////////////////////// diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 365381f5cdd..644c3dd32f4 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -277,7 +277,7 @@ int modifiers_getCageIndex(struct Object *ob, int *lastPossibleCageIndex_r); int modifiers_isSoftbodyEnabled(struct Object *ob); -struct ModifierData *modifiers_isClothEnabled(struct Object *ob); +struct ClothModifierData *modifiers_isClothEnabled(Object *ob); struct Object *modifiers_isDeformedByArmature(struct Object *ob); struct Object *modifiers_isDeformedByLattice(struct Object *ob); int modifiers_usesArmature(struct Object *ob, struct bArmature *arm); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index dce36f543ee..4c4bac7bbf9 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -120,10 +120,9 @@ static CM_SOLVER_DEF solvers [] = /* ********** cloth engine ******* */ /* Prototypes for internal functions. */ -static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ); +static void cloth_to_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); -static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ); -static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ); +static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ); static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ); @@ -603,69 +602,63 @@ void cloth_cache_free ( ClothModifierData *clmd, float time ) * cloth_deform_verts - simulates one step, framenr is in frames. * **/ -void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, - float ( *vertexCos ) [3], int numverts ) +DerivedMesh *clothModifier_do(ClothModifierData *clmd, + Object *ob, DerivedMesh *dm) { unsigned int i; - unsigned int numedges = -1; - unsigned int numfaces = -1; - MVert *mvert = NULL; - MEdge *medge = NULL; - MFace *mface = NULL; - DerivedMesh *result = NULL, *result2 = NULL; + DerivedMesh *result = NULL; Cloth *cloth = clmd->clothObject; unsigned int framenr = ( float ) G.scene->r.cfra; float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); - ListBase *effectors = NULL; - ClothVertex *newframe= NULL, *verts; + ListBase *effectors = NULL; + ClothVertex *verts = NULL; Frame *frame = NULL; LinkNode *search = NULL; float deltaTime = current_time - clmd->sim_parms.sim_time; + MVert *mverts = NULL; + + result = CDDM_copy(dm); // only be active during a specific period: // that's "first frame" and "last frame" on GUI - if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) ) + if ( clmd->clothObject ) { - if ( clmd->clothObject ) + if ( clmd->sim_parms.cache ) { - if ( clmd->sim_parms.cache ) + if ( current_time < clmd->sim_parms.firstframe ) { - if ( current_time < clmd->sim_parms.firstframe ) + int frametime = cloth_cache_first_frame ( clmd ); + if ( cloth_cache_search_frame ( clmd, frametime ) ) { - int frametime = cloth_cache_first_frame ( clmd ); - if ( cloth_cache_search_frame ( clmd, frametime ) ) - { - cloth_cache_get_frame ( clmd, frametime ); - cloth_to_object ( ob, clmd, vertexCos, numverts ); - } - return; - } - else if ( current_time > clmd->sim_parms.lastframe ) - { - int frametime = cloth_cache_last_frame ( clmd ); - if ( cloth_cache_search_frame ( clmd, frametime ) ) - { - cloth_cache_get_frame ( clmd, frametime ); - cloth_to_object ( ob, clmd, vertexCos, numverts ); - } - return; - } - else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed - { - if ( cloth_cache_search_frame ( clmd, framenr ) ) - { - cloth_cache_get_frame ( clmd, framenr ); - cloth_to_object ( ob, clmd, vertexCos, numverts ); - } - clmd->sim_parms.sim_time = current_time; - return; + cloth_cache_get_frame ( clmd, frametime ); + cloth_to_object ( ob, clmd, result ); } + return; + } + else if ( current_time > clmd->sim_parms.lastframe ) + { + int frametime = cloth_cache_last_frame ( clmd ); + if ( cloth_cache_search_frame ( clmd, frametime ) ) + { + cloth_cache_get_frame ( clmd, frametime ); + cloth_to_object ( ob, clmd, result ); + } + return; + } + else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed + { + if ( cloth_cache_search_frame ( clmd, framenr ) ) + { + cloth_cache_get_frame ( clmd, framenr ); + cloth_to_object ( ob, clmd, result ); + } + clmd->sim_parms.sim_time = current_time; + return; } - } + } - - + // unused in the moment, calculated seperately in implicit.c clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame; @@ -673,9 +666,9 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, if ( deltaTime == 1.0f ) { - if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) ) + if ( ( clmd->clothObject == NULL ) || ( dm->getNumVerts(dm) != clmd->clothObject->numverts ) ) { - if ( !cloth_from_object ( ob, clmd, dm, vertexCos, numverts ) ) + if ( !cloth_from_object ( ob, clmd, dm ) ) return; if ( clmd->clothObject == NULL ) @@ -692,6 +685,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, if ( !cloth_cache_search_frame ( clmd, framenr ) ) { verts = cloth->verts; + mverts = dm->getVertArray(dm); // Force any pinned verts to their constrained location. for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) @@ -699,9 +693,8 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, // Save the previous position. VECCOPY ( verts->xold, verts->xconst ); VECCOPY ( verts->txold, verts->x ); - // Get the current position. - VECCOPY ( verts->xconst, vertexCos[i] ); + VECCOPY ( verts->xconst, mverts[i].co ); Mat4MulVecfl ( ob->obmat, verts->xconst ); } @@ -723,7 +716,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, } // Copy the result back to the object. - cloth_to_object ( ob, clmd, vertexCos, numverts ); + cloth_to_object ( ob, clmd, result ); // bvh_free(clmd->clothObject->tree); // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); @@ -737,11 +730,12 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, if ( cloth_cache_search_frame ( clmd, framenr ) ) { cloth_cache_get_frame ( clmd, framenr ); - cloth_to_object ( ob, clmd, vertexCos, numverts ); + cloth_to_object ( ob, clmd, result ); } } } - + + return result; } /* frees all */ @@ -771,6 +765,14 @@ void cloth_free_modifier ( ClothModifierData *clmd ) // Free the verts. if ( cloth->verts != NULL ) MEM_freeN ( cloth->verts ); + + // Free the verts. + if ( cloth->x != NULL ) + MEM_freeN ( cloth->x ); + + // Free the verts. + if ( cloth->xnew != NULL ) + MEM_freeN ( cloth->xnew ); cloth->verts = NULL; cloth->numverts = 0; @@ -823,22 +825,24 @@ void cloth_free_modifier ( ClothModifierData *clmd ) * * This function is a modified version of the softbody.c:softbody_to_object() function. **/ -static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ) +static void cloth_to_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) { ClothVertex *verts = NULL; unsigned int i = 0; + MVert *mvert = NULL; if ( clmd->clothObject ) { verts = clmd->clothObject->verts; + mvert = dm->getVertArray(dm); /* inverse matrix is not uptodate... */ Mat4Invert ( ob->imat, ob->obmat ); - for ( i = 0; i < numverts; i++, verts++ ) + for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) { - VECCOPY ( vertexCos[i], verts->x ); - Mat4MulVecfl ( ob->imat, vertexCos[i] ); /* softbody is in global coords */ + VECCOPY ( mvert[i].co, verts->x ); + Mat4MulVecfl ( ob->imat, mvert[i].co ); /* softbody is in global coords */ } } } @@ -903,7 +907,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short } // only meshes supported at the moment -static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ) +static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) { unsigned int i = 0; // dm->getNumVerts(dm); @@ -954,7 +958,7 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh verts = clmd->clothObject->verts; /* set initial values */ - for ( i = 0; i < numverts; i++, verts++ ) + for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) { VECCOPY ( verts->x, mvert[i].co ); Mat4MulVecfl ( ob->obmat, verts->x ); @@ -1021,6 +1025,22 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh * modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." ); return; } + + clmd->clothObject->x = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_x" ); + if ( clmd->clothObject->x == NULL ) + { + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->x." ); + return; + } + + clmd->clothObject->xnew = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_xnew" ); + if ( clmd->clothObject->xnew == NULL ) + { + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xnew." ); + return; + } // save face information clmd->clothObject->numfaces = numfaces; @@ -1067,7 +1087,10 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in cloth->numsprings++; BLI_linklist_append ( &cloth->springs, spring ); + + return 1; } + return 0; } int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 41823b0ad39..f4b0ce7312b 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -72,6 +72,22 @@ #include "Bullet-C-Api.h" +// step is limited from 0 (frame start position) to 1 (frame end position) +void collision_move_object(CollisionModifierData *collmd, float step) +{ + float tv[3] = {0,0,0}; + unsigned int i = 0; + MVert *tempVert = collmd->current_x; + collmd->current_x = collmd->current_xnew; + collmd->current_xnew = tempVert; + + for ( i = 0; i < collmd->numverts; i++ ) + { + VECSUB(tv, collmd->xnew[i].co, collmd->x[i].co); + VECADDS(collmd->current_xnew[i].co, collmd->x[i].co, tv, step); + } +} + /** * gsl_poly_solve_cubic - @@ -362,846 +378,3 @@ DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], floa VECADDMUL(to, v3, w3); } -// unused in the moment, has some bug in -DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal[3], double normalVelocity, - double frictionConstant, double delta_V_n) -{ - float vrel_t_pre[3]; - float vrel_t[3]; - VECSUBS(vrel_t_pre, vrel, normal, normalVelocity); - VECCOPY(to, vrel_t_pre); - VecMulf(to, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); -} - -int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) -{ - /* - unsigned int i = 0; - int result = 0; - LinkNode *search = NULL; - CollPair *collpair = NULL; - Cloth *cloth1, *cloth2; - float w1, w2, w3, u1, u2, u3; - float v1[3], v2[3], relativeVelocity[3]; - float magrelVel; - - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - // search = clmd->coll_parms.collision_list; - - while(search) - { - collpair = search->link; - - // compute barycentric coordinates for both collision points - collisions_compute_barycentric(collpair->pa, - cloth1->verts[collpair->ap1].txold, - cloth1->verts[collpair->ap2].txold, - cloth1->verts[collpair->ap3].txold, - &w1, &w2, &w3); - - collisions_compute_barycentric(collpair->pb, - cloth2->verts[collpair->bp1].txold, - cloth2->verts[collpair->bp2].txold, - cloth2->verts[collpair->bp3].txold, - &u1, &u2, &u3); - - // Calculate relative "velocity". - interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3); - - interpolateOnTriangle(v2, cloth2->verts[collpair->bp1].tv, cloth2->verts[collpair->bp2].tv, cloth2->verts[collpair->bp3].tv, u1, u2, u3); - - VECSUB(relativeVelocity, v1, v2); - - // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). - magrelVel = INPR(relativeVelocity, collpair->normal); - - // printf("magrelVel: %f\n", magrelVel); - - // Calculate masses of points. - - // If v_n_mag < 0 the edges are approaching each other. - if(magrelVel < -ALMOST_ZERO) - { - // Calculate Impulse magnitude to stop all motion in normal direction. - // const double I_mag = v_n_mag / (1/m1 + 1/m2); - float magnitude_i = magrelVel / 2.0f; // TODO implement masses - float tangential[3], magtangent, magnormal, collvel[3]; - float vrel_t_pre[3]; - float vrel_t[3]; - double impulse; - float epsilon = clmd->coll_parms.epsilon; - float overlap = (epsilon + ALMOST_ZERO-collpair->distance); - - // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); - - // magtangent = INPR(tangential, tangential); - - // Apply friction impulse. - if (magtangent < -ALMOST_ZERO) - { - - // printf("friction applied: %f\n", magtangent); - // TODO check original code - } - - - impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - - // printf("impulse: %f\n", impulse); - - // face A - VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); - cloth1->verts[collpair->ap1].impulse_count++; - - VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); - cloth1->verts[collpair->ap2].impulse_count++; - - VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); - cloth1->verts[collpair->ap3].impulse_count++; - - // face B - VECADDMUL(cloth2->verts[collpair->bp1].impulse, collpair->normal, u1 * impulse); - cloth2->verts[collpair->bp1].impulse_count++; - - VECADDMUL(cloth2->verts[collpair->bp2].impulse, collpair->normal, u2 * impulse); - cloth2->verts[collpair->bp2].impulse_count++; - - VECADDMUL(cloth2->verts[collpair->bp3].impulse, collpair->normal, u3 * impulse); - cloth2->verts[collpair->bp3].impulse_count++; - - - result = 1; - - // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case - - // Apply the impulse and increase impulse counters. - - - } - - search = search->next; - } - - - return result; - */ - return 0; -} - - -int collisions_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) -{ - -} - - -int collisions_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) -{ - -} - -void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) -{ - /* - CollPair *collpair = NULL; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; - double distance = 0; - float epsilon = clmd->coll_parms.epsilon; - unsigned int i = 0; - - for(i = 0; i < 4; i++) - { - collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); - - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(cloth2->mfaces[tree2->tri_index]); - - // check all possible pairs of triangles - if(i == 0) - { - collpair->ap1 = face1->v1; - collpair->ap2 = face1->v2; - collpair->ap3 = face1->v3; - - collpair->bp1 = face2->v1; - collpair->bp2 = face2->v2; - collpair->bp3 = face2->v3; - - } - - if(i == 1) - { - if(face1->v4) - { - collpair->ap1 = face1->v3; - collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; - - collpair->bp1 = face2->v1; - collpair->bp2 = face2->v2; - collpair->bp3 = face2->v3; - } - else - i++; - } - - if(i == 2) - { - if(face2->v4) - { - collpair->ap1 = face1->v1; - collpair->ap2 = face1->v2; - collpair->ap3 = face1->v3; - - collpair->bp1 = face2->v3; - collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; - } - else - i+=2; - } - - if(i == 3) - { - if((face1->v4)&&(face2->v4)) - { - collpair->ap1 = face1->v3; - collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; - - collpair->bp1 = face2->v3; - collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; - } - else - i++; - } - - // calc SIPcode (?) - - if(i < 4) - { - // calc distance + normal - distance = plNearestPoints( - verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, collpair->pa,collpair->pb,collpair->vector); - - if (distance <= (epsilon + ALMOST_ZERO)) - { - // printf("dist: %f\n", (float)distance); - - // collpair->face1 = tree1->tri_index; - // collpair->face2 = tree2->tri_index; - - // VECCOPY(collpair->normal, collpair->vector); - // Normalize(collpair->normal); - - // collpair->distance = distance; - - } - else - { - MEM_freeN(collpair); - } - } - else - { - MEM_freeN(collpair); - } - } - */ -} - -int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) -{ - Cloth *cloth1, *cloth2; - ClothVertex *verts1, *verts2; - float temp[3]; - - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - - VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - - VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - - VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - - return 0; -} - -void collisions_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) -{ - EdgeCollPair edgecollpair; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; - double distance = 0; - float epsilon = clmd->coll_parms.epsilon; - unsigned int i = 0, j = 0, k = 0; - int numsolutions = 0; - float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; - - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(cloth2->mfaces[tree2->tri_index]); - - for( i = 0; i < 5; i++) - { - if(i == 0) - { - edgecollpair.p11 = face1->v1; - edgecollpair.p12 = face1->v2; - } - else if(i == 1) - { - edgecollpair.p11 = face1->v2; - edgecollpair.p12 = face1->v3; - } - else if(i == 2) - { - if(face1->v4) - { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v4; - } - else - { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v1; - i+=5; // get out of here after this edge pair is handled - } - } - else if(i == 3) - { - if(face1->v4) - { - edgecollpair.p11 = face1->v4; - edgecollpair.p12 = face1->v1; - } - else - continue; - } - else - { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v1; - } - - - for( j = 0; j < 5; j++) - { - if(j == 0) - { - edgecollpair.p21 = face2->v1; - edgecollpair.p22 = face2->v2; - } - else if(j == 1) - { - edgecollpair.p21 = face2->v2; - edgecollpair.p22 = face2->v3; - } - else if(j == 2) - { - if(face2->v4) - { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v4; - } - else - { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v1; - } - } - else if(j == 3) - { - if(face2->v4) - { - edgecollpair.p21 = face2->v4; - edgecollpair.p22 = face2->v1; - } - else - continue; - } - else - { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v1; - } - - - if(!collisions_are_edges_adjacent(clmd, coll_clmd, &edgecollpair)) - { - VECSUB(a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold); - VECSUB(b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v); - VECSUB(c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold); - VECSUB(d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v); - VECSUB(e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold); - VECSUB(f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v); - - numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution); - - for (k = 0; k < numsolutions; k++) - { - if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) - { - float out_collisionTime = solution[k]; - - // TODO: check for collisions - - // TODO: put into (edge) collision list - - printf("Moving edge found!\n"); - } - } - } - } - } -} - -void collisions_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) -{ - /* - CollPair collpair; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; - double distance = 0; - float epsilon = clmd->coll_parms.epsilon; - unsigned int i = 0, j = 0, k = 0; - int numsolutions = 0; - float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; - - for(i = 0; i < 2; i++) - { - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(cloth2->mfaces[tree2->tri_index]); - - // check all possible pairs of triangles - if(i == 0) - { - collpair.ap1 = face1->v1; - collpair.ap2 = face1->v2; - collpair.ap3 = face1->v3; - - collpair.pointsb[0] = face2->v1; - collpair.pointsb[1] = face2->v2; - collpair.pointsb[2] = face2->v3; - collpair.pointsb[3] = face2->v4; - } - - if(i == 1) - { - if(face1->v4) - { - collpair.ap1 = face1->v3; - collpair.ap2 = face1->v4; - collpair.ap3 = face1->v1; - - collpair.pointsb[0] = face2->v1; - collpair.pointsb[1] = face2->v2; - collpair.pointsb[2] = face2->v3; - collpair.pointsb[3] = face2->v4; - } - else - i++; - } - - // calc SIPcode (?) - - if(i < 2) - { - VECSUB(a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold); - VECSUB(b, verts1[collpair.ap2].v, verts1[collpair.ap1].v); - VECSUB(c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold); - VECSUB(d, verts1[collpair.ap3].v, verts1[collpair.ap1].v); - - for(j = 0; j < 4; j++) - { - if((j==3) && !(face2->v4)) - break; - - VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold); - VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v); - - numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution); - - for (k = 0; k < numsolutions; k++) - { - if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) - { - float out_collisionTime = solution[k]; - - // TODO: check for collisions - - // TODO: put into (point-face) collision list - - printf("Moving found!\n"); - - } - } - - // TODO: check borders for collisions - } - - } - } - */ -} - -void collisions_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) -{ - /* - // TODO: check for adjacent - collisions_collision_moving_edges(clmd, coll_clmd, tree1, tree2); - - collisions_collision_moving_tris(clmd, coll_clmd, tree1, tree2); - collisions_collision_moving_tris(coll_clmd, clmd, tree2, tree1); - */ -} - -// move collision objects forward in time and update static bounding boxes -void collisions_update_collision_objects(float step) -{ - Base *base=NULL; - ClothModifierData *coll_clmd=NULL; - Object *coll_ob=NULL; - unsigned int i=0; - - // search all objects for collision object - for (base = G.scene->base.first; base; base = base->next) - { - - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - if (!coll_clmd) - continue; - - // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) - { - if (coll_clmd->clothObject && coll_clmd->clothObject->tree) - { - Cloth *coll_cloth = coll_clmd->clothObject; - BVH *coll_bvh = coll_clmd->clothObject->tree; - unsigned int coll_numverts = coll_cloth->numverts; - - // update position of collision object - for(i = 0; i < coll_numverts; i++) - { - VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx); - - VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step); - - // no dt here because of float rounding errors - VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold); - } - - // update BVH of collision object - // bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING - } - else - printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } - } -} - -// collisions_MAX_THRESHOLD defines how much collision rounds/loops should be taken -#define CLOTH_MAX_THRESHOLD 10 - -// cloth - object collisions -int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) -{ - Base *base=NULL; - ClothModifierData *coll_clmd=NULL; - Cloth *cloth=NULL; - Object *coll_ob=NULL; - BVH *collisions_bvh=NULL; - unsigned int i=0, j = 0, numfaces = 0, numverts = 0; - unsigned int result = 0, ic = 0, rounds = 0; // result counts applied collisions; ic is for debug output; - ClothVertex *verts = NULL; - float tnull[3] = {0,0,0}; - int ret = 0; - LinkNode *collision_list = NULL; - - if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) - { - return 0; - } - cloth = clmd->clothObject; - verts = cloth->verts; - collisions_bvh = (BVH *) cloth->tree; - numfaces = clmd->clothObject->numfaces; - numverts = clmd->clothObject->numverts; - - //////////////////////////////////////////////////////////// - // static collisions - //////////////////////////////////////////////////////////// - - // update cloth bvh - // bvh_update(clmd, collisions_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function) - - // update collision objects - collisions_update_collision_objects(step); - - do - { - result = 0; - ic = 0; - - // check all collision objects - for (base = G.scene->base.first; base; base = base->next) - { - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - - if (!coll_clmd) - continue; - - // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) - { - if (coll_clmd->clothObject && coll_clmd->clothObject->tree) - { - BVH *coll_bvh = coll_clmd->clothObject->tree; - - // fill collision list - bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list); - - // process all collisions (calculate impulses, TODO: also repulses if distance too short) - result = 1; - for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence - { - result = 0; - - // result += collisions_collision_response_static_tris(clmd, coll_clmd, collision_list, 0); - - // result += collisions_collision_response_static_tris(coll_clmd, clmd, collision_list, 1); - - // apply impulses in parallel - ic=0; - for(i = 0; i < numverts; i++) - { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if(verts[i].impulse_count) - { - VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); - VECCOPY(verts[i].impulse, tnull); - verts[i].impulse_count = 0; - - ic++; - ret++; - } - } - } - - // free collision list - if(collision_list) - { - LinkNode *search = collision_list; - while(search) - { - CollisionPair *coll_pair = search->link; - - MEM_freeN(coll_pair); - search = search->next; - } - BLI_linklist_free(collision_list,NULL); - - collision_list = NULL; - } - } - else - printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } - } - - printf("ic: %d\n", ic); - rounds++; - } - while(result && (CLOTH_MAX_THRESHOLD>rounds)); - - printf("\n"); - - //////////////////////////////////////////////////////////// - // update positions - // this is needed for bvh_calc_DOP_hull_moving() [kdop.c] - //////////////////////////////////////////////////////////// - - // verts come from clmd - for(i = 0; i < numverts; i++) - { - VECADD(verts[i].tx, verts[i].txold, verts[i].tv); - } - //////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////// - // moving collisions - //////////////////////////////////////////////////////////// - - - // update cloth bvh - // bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING - - // update moving bvh for collision object once - for (base = G.scene->base.first; base; base = base->next) - { - - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - if (!coll_clmd) - continue; - - if(!coll_clmd->clothObject) - continue; - - // if collision object go on - if (coll_clmd->clothObject && coll_clmd->clothObject->tree) - { - BVH *coll_bvh = coll_clmd->clothObject->tree; - - // bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING - } - } - - - do - { - result = 0; - ic = 0; - - // check all collision objects - for (base = G.scene->base.first; base; base = base->next) - { - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - - if (!coll_clmd) - continue; - - // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) - { - if (coll_clmd->clothObject && coll_clmd->clothObject->tree) - { - BVH *coll_bvh = coll_clmd->clothObject->tree; - - bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list); - - // process all collisions (calculate impulses, TODO: also repulses if distance too short) - result = 1; - for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence - { - result = 0; - - // handle all collision objects - - /* - if (coll_clmd->clothObject) - result += collisions_collision_response_moving_tris(clmd, coll_clmd); - else - printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - */ - - // apply impulses in parallel - ic=0; - for(i = 0; i < numverts; i++) - { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if(verts[i].impulse_count) - { - VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); - VECCOPY(verts[i].impulse, tnull); - verts[i].impulse_count = 0; - - ic++; - ret++; - } - } - } - - - // verts come from clmd - for(i = 0; i < numverts; i++) - { - VECADD(verts[i].tx, verts[i].txold, verts[i].tv); - } - - // update cloth bvh - // bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING - - - // free collision list - if(collision_list) - { - LinkNode *search = collision_list; - while(search) - { - CollisionPair *coll_pair = search->link; - - MEM_freeN(coll_pair); - search = search->next; - } - BLI_linklist_free(collision_list,NULL); - - collision_list = NULL; - } - } - else - printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } - } - - printf("ic: %d\n", ic); - rounds++; - } - while(result && (CLOTH_MAX_THRESHOLD>rounds)); - - - //////////////////////////////////////////////////////////// - // update positions + velocities - //////////////////////////////////////////////////////////// - - // verts come from clmd - for(i = 0; i < numverts; i++) - { - VECADD(verts[i].tx, verts[i].txold, verts[i].tv); - } - //////////////////////////////////////////////////////////// - - return MIN2(ret, 1); -} diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 2ce00d0e38c..f61e2d22f1c 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -49,6 +49,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BLI_threads.h" +#include "BKE_collisions.h" #include "BKE_curve.h" #include "BKE_displist.h" #include "BKE_effect.h" @@ -1585,3 +1586,841 @@ void implicit_set_positions (ClothModifierData *clmd) VECCOPY(id->V[i], verts[i].v); } } + + +int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + /* + unsigned int i = 0; + int result = 0; + LinkNode *search = NULL; + CollPair *collpair = NULL; + Cloth *cloth1, *cloth2; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + // search = clmd->coll_parms.collision_list; + + while(search) + { + collpair = search->link; + + // compute barycentric coordinates for both collision points + collisions_compute_barycentric(collpair->pa, + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3); + + collisions_compute_barycentric(collpair->pb, + cloth2->verts[collpair->bp1].txold, + cloth2->verts[collpair->bp2].txold, + cloth2->verts[collpair->bp3].txold, + &u1, &u2, &u3); + + // Calculate relative "velocity". + interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3); + + interpolateOnTriangle(v2, cloth2->verts[collpair->bp1].tv, cloth2->verts[collpair->bp2].tv, cloth2->verts[collpair->bp3].tv, u1, u2, u3); + + VECSUB(relativeVelocity, v1, v2); + + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). + magrelVel = INPR(relativeVelocity, collpair->normal); + + // printf("magrelVel: %f\n", magrelVel); + + // Calculate masses of points. + + // If v_n_mag < 0 the edges are approaching each other. + if(magrelVel < -ALMOST_ZERO) + { + // Calculate Impulse magnitude to stop all motion in normal direction. + // const double I_mag = v_n_mag / (1/m1 + 1/m2); + float magnitude_i = magrelVel / 2.0f; // TODO implement masses + float tangential[3], magtangent, magnormal, collvel[3]; + float vrel_t_pre[3]; + float vrel_t[3]; + double impulse; + float epsilon = clmd->coll_parms.epsilon; + float overlap = (epsilon + ALMOST_ZERO-collpair->distance); + + // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); + + // magtangent = INPR(tangential, tangential); + + // Apply friction impulse. + if (magtangent < -ALMOST_ZERO) + { + + // printf("friction applied: %f\n", magtangent); + // TODO check original code +} + + + impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + // printf("impulse: %f\n", impulse); + + // face A + VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); + cloth1->verts[collpair->ap1].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); + cloth1->verts[collpair->ap2].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); + cloth1->verts[collpair->ap3].impulse_count++; + + // face B + VECADDMUL(cloth2->verts[collpair->bp1].impulse, collpair->normal, u1 * impulse); + cloth2->verts[collpair->bp1].impulse_count++; + + VECADDMUL(cloth2->verts[collpair->bp2].impulse, collpair->normal, u2 * impulse); + cloth2->verts[collpair->bp2].impulse_count++; + + VECADDMUL(cloth2->verts[collpair->bp3].impulse, collpair->normal, u3 * impulse); + cloth2->verts[collpair->bp3].impulse_count++; + + + result = 1; + + // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case + + // Apply the impulse and increase impulse counters. + + +} + + search = search->next; +} + + + return result; + */ + return 0; +} + + +int collisions_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + +} + + +int collisions_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + +} + +void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) +{ + /* + CollPair *collpair = NULL; + Cloth *cloth1=NULL, *cloth2=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL, *verts2=NULL; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0; + + for(i = 0; i < 4; i++) + { + collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + // check all possible pairs of triangles + if(i == 0) + { + collpair->ap1 = face1->v1; + collpair->ap2 = face1->v2; + collpair->ap3 = face1->v3; + + collpair->bp1 = face2->v1; + collpair->bp2 = face2->v2; + collpair->bp3 = face2->v3; + +} + + if(i == 1) + { + if(face1->v4) + { + collpair->ap1 = face1->v3; + collpair->ap2 = face1->v4; + collpair->ap3 = face1->v1; + + collpair->bp1 = face2->v1; + collpair->bp2 = face2->v2; + collpair->bp3 = face2->v3; +} + else + i++; +} + + if(i == 2) + { + if(face2->v4) + { + collpair->ap1 = face1->v1; + collpair->ap2 = face1->v2; + collpair->ap3 = face1->v3; + + collpair->bp1 = face2->v3; + collpair->bp2 = face2->v4; + collpair->bp3 = face2->v1; +} + else + i+=2; +} + + if(i == 3) + { + if((face1->v4)&&(face2->v4)) + { + collpair->ap1 = face1->v3; + collpair->ap2 = face1->v4; + collpair->ap3 = face1->v1; + + collpair->bp1 = face2->v3; + collpair->bp2 = face2->v4; + collpair->bp3 = face2->v1; +} + else + i++; +} + + // calc SIPcode (?) + + if(i < 4) + { + // calc distance + normal + distance = plNearestPoints( + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, collpair->pa,collpair->pb,collpair->vector); + + if (distance <= (epsilon + ALMOST_ZERO)) + { + // printf("dist: %f\n", (float)distance); + + // collpair->face1 = tree1->tri_index; + // collpair->face2 = tree2->tri_index; + + // VECCOPY(collpair->normal, collpair->vector); + // Normalize(collpair->normal); + + // collpair->distance = distance; + +} + else + { + MEM_freeN(collpair); +} +} + else + { + MEM_freeN(collpair); +} +} + */ +} + +int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) +{ + Cloth *cloth1, *cloth2; + ClothVertex *verts1, *verts2; + float temp[3]; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + return 0; +} + + +void collisions_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) +{ + /* + EdgeCollPair edgecollpair; + Cloth *cloth1=NULL, *cloth2=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL, *verts2=NULL; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0, j = 0, k = 0; + int numsolutions = 0; + float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + for( i = 0; i < 5; i++) + { + if(i == 0) + { + edgecollpair.p11 = face1->v1; + edgecollpair.p12 = face1->v2; +} + else if(i == 1) + { + edgecollpair.p11 = face1->v2; + edgecollpair.p12 = face1->v3; +} + else if(i == 2) + { + if(face1->v4) + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v4; +} + else + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v1; + i+=5; // get out of here after this edge pair is handled +} +} + else if(i == 3) + { + if(face1->v4) + { + edgecollpair.p11 = face1->v4; + edgecollpair.p12 = face1->v1; +} + else + continue; +} + else + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v1; +} + + + for( j = 0; j < 5; j++) + { + if(j == 0) + { + edgecollpair.p21 = face2->v1; + edgecollpair.p22 = face2->v2; +} + else if(j == 1) + { + edgecollpair.p21 = face2->v2; + edgecollpair.p22 = face2->v3; +} + else if(j == 2) + { + if(face2->v4) + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v4; +} + else + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v1; +} +} + else if(j == 3) + { + if(face2->v4) + { + edgecollpair.p21 = face2->v4; + edgecollpair.p22 = face2->v1; +} + else + continue; +} + else + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v1; +} + + + if(!collisions_are_edges_adjacent(clmd, coll_clmd, &edgecollpair)) + { + VECSUB(a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold); + VECSUB(b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v); + VECSUB(c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold); + VECSUB(d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v); + VECSUB(e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold); + VECSUB(f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v); + + numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution); + + for (k = 0; k < numsolutions; k++) + { + if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) + { + float out_collisionTime = solution[k]; + + // TODO: check for collisions + + // TODO: put into (edge) collision list + + printf("Moving edge found!\n"); +} +} +} +} +} + */ +} + +void collisions_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) +{ + /* + CollPair collpair; + Cloth *cloth1=NULL, *cloth2=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL, *verts2=NULL; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0, j = 0, k = 0; + int numsolutions = 0; + float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; + + for(i = 0; i < 2; i++) + { + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + // check all possible pairs of triangles + if(i == 0) + { + collpair.ap1 = face1->v1; + collpair.ap2 = face1->v2; + collpair.ap3 = face1->v3; + + collpair.pointsb[0] = face2->v1; + collpair.pointsb[1] = face2->v2; + collpair.pointsb[2] = face2->v3; + collpair.pointsb[3] = face2->v4; +} + + if(i == 1) + { + if(face1->v4) + { + collpair.ap1 = face1->v3; + collpair.ap2 = face1->v4; + collpair.ap3 = face1->v1; + + collpair.pointsb[0] = face2->v1; + collpair.pointsb[1] = face2->v2; + collpair.pointsb[2] = face2->v3; + collpair.pointsb[3] = face2->v4; +} + else + i++; +} + + // calc SIPcode (?) + + if(i < 2) + { + VECSUB(a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold); + VECSUB(b, verts1[collpair.ap2].v, verts1[collpair.ap1].v); + VECSUB(c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold); + VECSUB(d, verts1[collpair.ap3].v, verts1[collpair.ap1].v); + + for(j = 0; j < 4; j++) + { + if((j==3) && !(face2->v4)) + break; + + VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold); + VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v); + + numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution); + + for (k = 0; k < numsolutions; k++) + { + if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) + { + float out_collisionTime = solution[k]; + + // TODO: check for collisions + + // TODO: put into (point-face) collision list + + printf("Moving found!\n"); + +} +} + + // TODO: check borders for collisions +} + +} +} + */ +} + + +// move collision objects forward in time and update static bounding boxes +void collisions_update_collision_objects(float step) +{ + Base *base=NULL; + ClothModifierData *coll_clmd=NULL; + Object *coll_ob=NULL; + unsigned int i=0; + + // search all objects for collision object + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + Cloth *coll_cloth = coll_clmd->clothObject; + BVH *coll_bvh = coll_clmd->clothObject->tree; + unsigned int coll_numverts = coll_cloth->numverts; + + // update position of collision object + for(i = 0; i < coll_numverts; i++) + { + VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx); + + VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step); + + // no dt here because of float rounding errors + VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold); + } + + // update BVH of collision object + // bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING + } + else + printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } +} + + +void collisions_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) +{ + /* + // TODO: check for adjacent + collisions_collision_moving_edges(clmd, coll_clmd, tree1, tree2); + + collisions_collision_moving_tris(clmd, coll_clmd, tree1, tree2); + collisions_collision_moving_tris(coll_clmd, clmd, tree2, tree1); + */ +} + +// cloth - object collisions +int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) +{ + /* + Base *base=NULL; + ClothModifierData *coll_clmd=NULL; + Cloth *cloth=NULL; + Object *coll_ob=NULL; + BVH *collisions_bvh=NULL; + unsigned int i=0, j = 0, numfaces = 0, numverts = 0; + unsigned int result = 0, ic = 0, rounds = 0; // result counts applied collisions; ic is for debug output; + ClothVertex *verts = NULL; + float tnull[3] = {0,0,0}; + int ret = 0; + LinkNode *collision_list = NULL; + + if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) + { + return 0; + } + cloth = clmd->clothObject; + verts = cloth->verts; + collisions_bvh = (BVH *) cloth->tree; + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + + //////////////////////////////////////////////////////////// + // static collisions + //////////////////////////////////////////////////////////// + + // update cloth bvh + // bvh_update(clmd, collisions_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function) + + // update collision objects + collisions_update_collision_objects(step); + + do + { + result = 0; + ic = 0; + + // check all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + BVH *coll_bvh = coll_clmd->clothObject->tree; + + // fill collision list + bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list); + + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence + { + result = 0; + + // result += collisions_collision_response_static_tris(clmd, coll_clmd, collision_list, 0); + + // result += collisions_collision_response_static_tris(coll_clmd, clmd, collision_list, 1); + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } + } + } + + // free collision list + if(collision_list) + { + LinkNode *search = collision_list; + while(search) + { + CollisionPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(collision_list,NULL); + + collision_list = NULL; + } + } + else + printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + printf("ic: %d\n", ic); + rounds++; + } + while(result && (10>rounds));// CLOTH_MAX_THRESHOLD + + printf("\n"); + + //////////////////////////////////////////////////////////// + // update positions + // this is needed for bvh_calc_DOP_hull_moving() [kdop.c] + //////////////////////////////////////////////////////////// + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // moving collisions + //////////////////////////////////////////////////////////// + + + // update cloth bvh + // bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING + + // update moving bvh for collision object once + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + if(!coll_clmd->clothObject) + continue; + + // if collision object go on + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + BVH *coll_bvh = coll_clmd->clothObject->tree; + + // bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING + } + } + + + do + { + result = 0; + ic = 0; + + // check all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + BVH *coll_bvh = coll_clmd->clothObject->tree; + + bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list); + + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence + { + result = 0; + + // handle all collision objects + + + if (coll_clmd->clothObject) + result += collisions_collision_response_moving_tris(clmd, coll_clmd); + else + printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } + } + } + + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + + // update cloth bvh + // bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING + + + // free collision list + if(collision_list) + { + LinkNode *search = collision_list; + while(search) + { + CollisionPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(collision_list,NULL); + + collision_list = NULL; + } + } + else + printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + printf("ic: %d\n", ic); + rounds++; + } + while(result && (10>rounds)); // CLOTH_MAX_THRESHOLD + + + //////////////////////////////////////////////////////////// + // update positions + velocities + //////////////////////////////////////////////////////////// + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + //////////////////////////////////////////////////////////// + + return MIN2(ret, 1); + */ +} \ No newline at end of file diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 1e17ee4f03e..5ad08587266 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -164,9 +164,9 @@ static int size_threshold = 16; /* * Common methods for all algorithms */ -void bvh_exchange(Tree **a, int i, int j) +void bvh_exchange(CollisionTree **a, int i, int j) { - Tree *t=a[i]; + CollisionTree *t=a[i]; a[i]=a[j]; a[j]=t; } @@ -178,10 +178,10 @@ int floor_lg(int a) /* * Insertion sort algorithm */ -static void bvh_insertionsort(Tree **a, int lo, int hi, int axis) +static void bvh_insertionsort(CollisionTree **a, int lo, int hi, int axis) { int i,j; - Tree *t; + CollisionTree *t; for (i=lo; i < hi; i++) { j=i; @@ -195,7 +195,7 @@ static void bvh_insertionsort(Tree **a, int lo, int hi, int axis) } } -static int bvh_partition(Tree **a, int lo, int hi, Tree * x, int axis) +static int bvh_partition(CollisionTree **a, int lo, int hi, CollisionTree *x, int axis) { int i=lo, j=hi; while (1) @@ -213,9 +213,9 @@ static int bvh_partition(Tree **a, int lo, int hi, Tree * x, int axis) /* * Heapsort algorithm */ -static void bvh_downheap(Tree **a, int i, int n, int lo, int axis) +static void bvh_downheap(CollisionTree **a, int i, int n, int lo, int axis) { - Tree * d = a[lo+i-1]; + CollisionTree *d = a[lo+i-1]; int child; while (i<=n/2) { @@ -231,7 +231,7 @@ static void bvh_downheap(Tree **a, int i, int n, int lo, int axis) a[lo+i-1] = d; } -static void bvh_heapsort(Tree **a, int lo, int hi, int axis) +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) @@ -245,7 +245,7 @@ static void bvh_heapsort(Tree **a, int lo, int hi, int axis) } } -static Tree *bvh_medianof3(Tree **a, int lo, int mid, int hi, int axis) // returns Sortable +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]) { @@ -275,7 +275,7 @@ static Tree *bvh_medianof3(Tree **a, int lo, int mid, int hi, int axis) // retur /* * Quicksort algorithm modified for Introsort */ -static void bvh_introsort_loop (Tree **a, int lo, int hi, int depth_limit, int axis) +static void bvh_introsort_loop (CollisionTree **a, int lo, int hi, int depth_limit, int axis) { int p; @@ -293,16 +293,16 @@ static void bvh_introsort_loop (Tree **a, int lo, int hi, int depth_limit, int a } } -void bvh_sort(Tree **a0, int begin, int end, int axis) +void bvh_sort(CollisionTree **a0, int begin, int end, int axis) { if (begin < end) { - Tree **a=a0; + CollisionTree **a=a0; bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis); bvh_insertionsort(a, begin, end, axis); } } -void bvh_sort_along_axis(Tree **face_list, int start, int end, int axis) +void bvh_sort_along_axis(CollisionTree **face_list, int start, int end, int axis) { bvh_sort(face_list, start, end, axis); } @@ -310,7 +310,7 @@ void bvh_sort_along_axis(Tree **face_list, int start, int end, int axis) void bvh_free(BVH * bvh) { LinkNode *search = NULL; - Tree *tree = NULL; + CollisionTree *tree = NULL; if (bvh) { @@ -361,7 +361,7 @@ int bvh_largest_axis(float *bv) } // depends on the fact that the BVH's for each face is already build -void bvh_calc_DOP_hull_from_faces(BVH * bvh, Tree **tri, int numfaces, float *bv) +void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces, float *bv) { float newmin,newmax; int i, j; @@ -385,32 +385,22 @@ void bvh_calc_DOP_hull_from_faces(BVH * bvh, Tree **tri, int numfaces, float *bv } } -void bvh_calc_DOP_hull_static(BVH * bvh, Tree **tri, int numfaces, float *bv) +void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv) { MVert *tempMVert = bvh->x; - 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. + // 1 up to 4 vertices per leaf. for (k = 0; k < 4; k++) { - int temp = 0; - // If this is a triangle. - if (k == 3 && !tempMFace->v4) + int temp = tri[j]->point_index[k]; + + if(temp < 0) 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++) { @@ -424,33 +414,23 @@ void bvh_calc_DOP_hull_static(BVH * bvh, Tree **tri, int numfaces, float *bv) } } -void bvh_calc_DOP_hull_moving(BVH * bvh, Tree **tri, int numfaces, float *bv) +void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv) { MVert *tempMVert = bvh->x; MVert *tempMVert2 = bvh->xnew; - 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) + int temp = tri[j]->point_index[k]; + + if(temp < 0) 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++) { @@ -470,10 +450,10 @@ void bvh_calc_DOP_hull_moving(BVH * bvh, Tree **tri, int numfaces, float *bv) } } -static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink) +static void bvh_div_env_node(BVH * bvh, TreeNode *tree, CollisionTree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink) { int i = 0; - Tree *newtree = NULL; + CollisionTree *newtree = NULL; int laxis = 0, max_nodes=4; unsigned int tstart, tend; LinkNode *nlink1 = nlink; @@ -512,7 +492,7 @@ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsign // Build tree until 4 node left. if ((tend-tstart + 1 ) > 1) { - newtree = (Tree *)MEM_callocN(sizeof(Tree), "Tree"); + 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; @@ -530,7 +510,7 @@ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsign } else // ok, we have 1 left for this node { - Tree *tnode = face_list[tstart]; + CollisionTree *tnode = face_list[tstart]; tree->nodes[i] = tnode; tree->nodes[i]->parent = tree; } @@ -538,19 +518,16 @@ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, Tree **face_list, unsign return; } -BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xnew, unsigned int numverts, float epsilon) +// mfaces is allowed to be null +// just vertexes are used if mfaces=NULL +BVH *bvh_build (MFace *mfaces, unsigned int numfaces, MVert *x, MVert *xnew, unsigned int numverts, float epsilon) { - unsigned int i = 0, j = 0, k = 0; - Tree **face_list=NULL; + unsigned int i = 0, j = 0; + CollisionTree **face_list=NULL; BVH *bvh=NULL; - Tree *tree=NULL; + CollisionTree *tree=NULL; LinkNode *nlink = NULL; - EdgeHash *edgehash = NULL; - unsigned int numsprings = 0; MFace *mface = NULL; - - if(!dm) - return NULL; bvh = MEM_callocN(sizeof(BVH), "BVH"); if (bvh == NULL) @@ -565,13 +542,19 @@ BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xnew, unsigned int numverts, f bvh->tree = NULL; bvh->epsilon = epsilon; - bvh->numfaces = dm->getNumFaces(dm); - mface = bvh->mfaces = dm->getFaceArray(dm); + bvh->numfaces = numfaces; + mface = bvh->mfaces = mfaces; + + // we have no faces, we save seperate points + if(!bvh->mfaces) + { + bvh->numfaces = numverts; + } bvh->numverts = numverts; bvh->xnew = xnew; bvh->x = x; - tree = (Tree *)MEM_callocN(sizeof(Tree), "Tree"); + tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree"); // TODO: check succesfull alloc BLI_linklist_append(&bvh->tree, tree); @@ -590,7 +573,25 @@ BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xnew, unsigned int numverts, f if(bvh->numfaces<=1) { - bvh->root->tri_index = 0; // Why that? --> only one face there + // Why that? --> only one face there + if(bvh->mfaces) + { + bvh->root->point_index[0] = mfaces[0].v1; + bvh->root->point_index[1] = mfaces[0].v2; + bvh->root->point_index[2] = mfaces[0].v3; + if(mfaces[0].v4) + bvh->root->point_index[3] = mfaces[0].v4; + else + bvh->root->point_index[3] = -1; + } + else + { + bvh->root->point_index[0] = 0; + bvh->root->point_index[1] = -1; + bvh->root->point_index[2] = -1; + bvh->root->point_index[3] = -1; + } + bvh->root->isleaf = 1; bvh->root->traversed = 0; bvh->root->count_nodes = 0; @@ -602,7 +603,7 @@ BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xnew, unsigned int numverts, f else { // create face boxes - face_list = MEM_callocN (bvh->numfaces * sizeof (Tree *), "Tree"); + face_list = MEM_callocN (bvh->numfaces * sizeof (CollisionTree *), "CollisionTree"); if (face_list == NULL) { printf("bvh_build: Out of memory for face_list.\n"); @@ -611,17 +612,35 @@ BVH *bvh_build (DerivedMesh *dm, MVert *x, MVert *xnew, unsigned int numverts, f } // create face boxes - for(i = 0, k = 0; i < bvh->numfaces; i++) + for(i = 0; i < bvh->numfaces; i++) { LinkNode *tnlink = NULL; - tree = (Tree *)MEM_callocN(sizeof(Tree), "Tree"); + 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; + + if(bvh->mfaces) + { + bvh->root->point_index[0] = mfaces[i].v1; + bvh->root->point_index[1] = mfaces[i].v2; + bvh->root->point_index[2] = mfaces[i].v3; + if(mfaces[i].v4) + bvh->root->point_index[3] = mfaces[i].v4; + else + bvh->root->point_index[3] = -1; + } + else + { + bvh->root->point_index[0] = i; + bvh->root->point_index[1] = -1; + bvh->root->point_index[2] = -1; + bvh->root->point_index[3] = -1; + } + tree->isleaf = 1; tree->nextLeaf = NULL; tree->prevLeaf = bvh->leaf_tree; @@ -694,7 +713,7 @@ int bvh_overlap(float *bv1, float *bv2) * every other triangle that doesn't require any realloc, but uses * much memory */ -int bvh_traverse(Tree * tree1, Tree * tree2, LinkNode *collision_list) +int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision_list) { int i = 0, ret = 0; @@ -709,8 +728,11 @@ int bvh_traverse(Tree * tree1, Tree * tree2, LinkNode *collision_list) // save potential colliding triangles CollisionPair *collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); - collpair->indexA = tree1->tri_index; - collpair->indexB = tree2->tri_index; + VECCOPY(collpair->point_indexA, tree1->point_index); + collpair->point_indexA[3] = tree1->point_index[3]; + + VECCOPY(collpair->point_indexB, tree2->point_index); + collpair->point_indexB[3] = tree2->point_index[3]; BLI_linklist_append(&collision_list, collpair); @@ -744,7 +766,7 @@ int bvh_traverse(Tree * tree1, Tree * tree2, LinkNode *collision_list) // bottom up update of bvh tree: // join the 4 children here -void bvh_join(Tree * tree) +void bvh_join(CollisionTree *tree) { int i = 0, j = 0; if (!tree) @@ -775,17 +797,12 @@ void bvh_join(Tree * tree) // update static bvh // needs new positions in bvh->x, bvh->xnew -void bvh_update(DerivedMesh *dm, BVH * bvh, int moving) +void bvh_update(BVH * bvh, int moving) { TreeNode *leaf, *parent; int traversecheck = 1; // if this is zero we don't go further unsigned int j = 0; - if(bvh->numfaces != dm->getNumFaces(dm)) - return; - - bvh->mfaces = dm->getFaceArray(dm); - for (leaf = bvh->leaf_root; leaf; leaf = leaf->nextLeaf) { traversecheck = 1; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index cb7fccd11c1..42faf2b2c3f 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4866,7 +4866,7 @@ static void clothModifier_initData(ModifierData *md) ClothModifierData *clmd = (ClothModifierData*) md; cloth_init (clmd); } - +/* static void clothModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) @@ -4889,6 +4889,22 @@ static void clothModifier_deformVerts( if(dm) dm->release(dm); } +*/ + +static DerivedMesh *clothModifier_applyModifier( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) +{ + DerivedMesh *result = NULL; + + ClothModifierData *clmd = (ClothModifierData*) md; + + result = clothModifier_do(clmd, ob, derivedData); + + CDDM_calc_normals(result); + + return derivedData; +} static void clothModifier_updateDepgraph( ModifierData *md, DagForest *forest, Object *ob, @@ -4957,6 +4973,8 @@ static void collisionModifier_initData(ModifierData *md) collmd->x = NULL; collmd->xnew = NULL; + collmd->current_x = NULL; + collmd->current_xnew = NULL; collmd->time = -1; collmd->numverts = 0; collmd->tree = NULL; @@ -4974,22 +4992,32 @@ static void collisionModifier_freeData(ModifierData *md) MEM_freeN(collmd->x); if(collmd->xnew) MEM_freeN(collmd->xnew); + if(collmd->current_x) + MEM_freeN(collmd->current_x); + if(collmd->current_xnew) + MEM_freeN(collmd->current_xnew); collmd->x = NULL; collmd->xnew = NULL; + collmd->current_x = NULL; + collmd->current_xnew = NULL; collmd->time = -1; collmd->numverts = 0; collmd->tree = NULL; } } +static int collisionModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + static void collisionModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { CollisionModifierData *collmd = (CollisionModifierData*) md; DerivedMesh *dm = NULL; - MVert *mvert = NULL; float current_time = 0; unsigned int numverts = 0, i = 0; MVert *tempVert = NULL; @@ -4999,6 +5027,12 @@ static void collisionModifier_deformVerts( 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); @@ -5013,17 +5047,26 @@ static void collisionModifier_deformVerts( // check if mesh has changed if(collmd->x && (numverts != collmd->numverts)) - collisionModifier_freeData(collmd); + collisionModifier_freeData((ModifierData *)collmd); if(collmd->time == -1) // first time { - collmd->x = dm->dupVertArray(dm); - collmd->xnew = dm->dupVertArray(dm); + collmd->x = dm->dupVertArray(dm); // frame start position + + for ( i = 0; i < numverts; i++ ) + { + // we save global positions + Mat4MulVecfl ( ob->obmat, collmd->x[i].co ); + } + + collmd->xnew = MEM_dupallocN(collmd->x); // frame end position + collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame + collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame collmd->numverts = numverts; // TODO: epsilon // create bounding box hierarchy - collmd->tree = bvh_build(dm, collmd->x, collmd->xnew, numverts, 0.01); + collmd->tree = bvh_build(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->current_x, collmd->current_xnew, numverts, ob->pd->pdef_sbift); } else if(numverts == collmd->numverts) { @@ -5040,7 +5083,10 @@ static void collisionModifier_deformVerts( Mat4MulVecfl ( ob->obmat, collmd->xnew[i].co ); } - bvh_update(dm, collmd->tree, 0); // recalc static bounding boxes + memcpy(collmd->current_xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); + memcpy(collmd->current_x, dm->getVertArray(dm), numverts*sizeof(MVert)); + + bvh_update(collmd->tree, 0); // recalc static bounding boxes } collmd->time = current_time; @@ -5051,11 +5097,6 @@ static void collisionModifier_deformVerts( dm->release(dm); } -static int collisionModifier_dependsOnTime(ModifierData *md) -{ - return 1; -} - /* Boolean */ static void booleanModifier_copyData(ModifierData *md, ModifierData *target) @@ -5342,10 +5383,10 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->deformVerts = softbodyModifier_deformVerts; mti = INIT_TYPE(Cloth); - mti->type = eModifierTypeType_OnlyDeform; + mti->type = eModifierTypeType_Nonconstructive; mti->initData = clothModifier_initData; - mti->flags = eModifierTypeFlag_AcceptsCVs; - // | eModifierTypeFlag_RequiresOriginalData; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_RequiresOriginalData; // | eModifierTypeFlag_SupportsMapping // | eModifierTypeFlag_SupportsEditmode // | eModifierTypeFlag_EnableInEditmode; @@ -5353,7 +5394,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->freeData = clothModifier_freeData; mti->requiredDataMask = clothModifier_requiredDataMask; // mti->copyData = clothModifier_copyData; - mti->deformVerts = clothModifier_deformVerts; + // mti->deformVerts = clothModifier_deformVerts; + mti->applyModifier = clothModifier_applyModifier; mti->updateDepgraph = clothModifier_updateDepgraph; mti = INIT_TYPE(Collision); @@ -5567,11 +5609,11 @@ int modifiers_isSoftbodyEnabled(Object *ob) return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -ModifierData *modifiers_isClothEnabled(Object *ob) +ClothModifierData *modifiers_isClothEnabled(Object *ob) { - ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - return md; + return clmd; } LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 99f0885b435..56f1c817a50 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2893,6 +2893,8 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) collmd->x = NULL; collmd->xnew = NULL; + collmd->current_x = NULL; + collmd->current_xnew = NULL; collmd->time = -1; collmd->numverts = 0; collmd->tree = NULL; @@ -3009,7 +3011,6 @@ static void direct_link_object(FileData *fd, Object *ob) sb->bpoint= NULL; // init pointers so it gets rebuilt nicely sb->bspring= NULL; sb->scratch= NULL; - sb->keys= newdataadr(fd, sb->keys); test_pointer_array(fd, (void **)&sb->keys); diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 27f7431a9cf..b4592e4d724 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -156,9 +156,13 @@ typedef struct Cloth unsigned char old_solver_type; unsigned char pad2; short pad3; - void *tree; /* collision tree for this cloth object */ + struct CollisionTree *tree; /* collision tree for this cloth object */ struct MFace *mfaces; - void *implicit; /* our implicit solver connects to this pointer */ + struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ + struct MVert *x; + struct MVert *xnew; + struct MVert *current_x; + struct MVert *current_xnew; } Cloth; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 81e27afbac4..b25c3e79921 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -350,12 +350,14 @@ typedef struct ClothModifierData { typedef struct CollisionModifierData { ModifierData modifier; - struct MVert *x; - struct MVert *xnew; + struct MVert *x; /* position at the beginning of the frame */ + struct MVert *xnew; /* position at the end of the frame */ + struct MVert *current_xnew; /* new position at the actual inter-frame step */ + struct MVert *current_x; /* position at the actual inter-frame step */ unsigned int numverts; float time; - void *tree; /* collision tree for this cloth object */ + struct BVH *tree; /* collision tree for this cloth object */ } CollisionModifierData; typedef enum { diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index a821e209ef0..062989d0754 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -113,7 +113,6 @@ typedef struct SoftBody { ; struct SBScratch *scratch; /* scratch pad/cache on live time not saved in file */ - } SoftBody; /* pd->forcefield: Effector Fields types */ diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 8f35e64b79f..a68338e132b 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -99,6 +99,7 @@ #include "BKE_customdata.h" #include "BKE_blender.h" #include "BKE_booleanops.h" +#include "BKE_cloth.h" #include "BKE_curve.h" #include "BKE_displist.h" #include "BKE_depsgraph.h" From 8bca9e5977c61833250c49ecb46f26b3e6b8eba7 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 23 Oct 2007 22:38:07 +0000 Subject: [PATCH 033/101] Another WIP commit. Building up bounding volume API --- source/blender/blenkernel/BKE_collisions.h | 5 +- source/blender/blenkernel/intern/kdop.c | 94 ++++++++++++++------- source/blender/blenkernel/intern/modifier.c | 5 +- source/blender/src/buttons_object.c | 41 ++++----- 4 files changed, 85 insertions(+), 60 deletions(-) diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h index 8c7933f3434..0a79bb46262 100644 --- a/source/blender/blenkernel/BKE_collisions.h +++ b/source/blender/blenkernel/BKE_collisions.h @@ -89,7 +89,8 @@ CollisionPair; ///////////////////////////////////////////////// // builds bounding volume hierarchy -BVH *bvh_build (MFace *mfaces, unsigned int numfaces, MVert *x, MVert *xnew, unsigned int numverts, float epsilon); +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 ); @@ -97,7 +98,7 @@ void bvh_free ( BVH *bvh ); int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision_list); // update bounding volumes, needs updated positions in bvh->x -void bvh_update(BVH * bvh, int moving); +void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving); LinkNode *BLI_linklist_append_fast (LinkNode **listp, void *ptr); diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 5ad08587266..f2a1e895751 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -330,6 +330,11 @@ void bvh_free(BVH * bvh) BLI_linklist_free(bvh->tree,NULL); bvh->tree = NULL; + if(bvh->x) + MEM_freeN(bvh->x); + if(bvh->xnew) + MEM_freeN(bvh->xnew); + MEM_freeN(bvh); bvh = NULL; } @@ -520,44 +525,14 @@ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, CollisionTree **face_lis // mfaces is allowed to be null // just vertexes are used if mfaces=NULL -BVH *bvh_build (MFace *mfaces, unsigned int numfaces, MVert *x, MVert *xnew, unsigned int numverts, float epsilon) +BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces) { unsigned int i = 0, j = 0; CollisionTree **face_list=NULL; - BVH *bvh=NULL; CollisionTree *tree=NULL; LinkNode *nlink = NULL; MFace *mface = NULL; - bvh = MEM_callocN(sizeof(BVH), "BVH"); - if (bvh == NULL) - { - printf("bvh: Out of memory.\n"); - return NULL; - } - - bvh->flags = 0; - bvh->leaf_tree = NULL; - bvh->leaf_root = NULL; - bvh->tree = NULL; - - bvh->epsilon = epsilon; - bvh->numfaces = numfaces; - mface = bvh->mfaces = mfaces; - - // we have no faces, we save seperate points - if(!bvh->mfaces) - { - bvh->numfaces = numverts; - } - - bvh->numverts = numverts; - bvh->xnew = xnew; - bvh->x = x; - tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree"); - // TODO: check succesfull alloc - BLI_linklist_append(&bvh->tree, tree); - nlink = bvh->tree; if (tree == NULL) @@ -686,6 +661,46 @@ BVH *bvh_build (MFace *mfaces, unsigned int numfaces, MVert *x, MVert *xnew, uns return bvh; } +BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon) +{ + unsigned int i = 0, j = 0; + CollisionTree **face_list=NULL; + BVH *bvh=NULL; + CollisionTree *tree=NULL; + LinkNode *nlink = NULL; + MFace *mface = NULL; + + bvh = MEM_callocN(sizeof(BVH), "BVH"); + if (bvh == NULL) + { + printf("bvh: Out of memory.\n"); + return NULL; + } + + bvh->flags = 0; + bvh->leaf_tree = NULL; + bvh->leaf_root = NULL; + bvh->tree = NULL; + + bvh->epsilon = epsilon; + bvh->numfaces = numfaces; + + // we have no faces, we save seperate points + if(!mfaces) + { + bvh->numfaces = numverts; + } + + bvh->numverts = numverts; + bvh->xnew = MEM_dupallocN(x); + bvh->x = MEM_dupallocN(x); + tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree"); + // TODO: check succesfull alloc + BLI_linklist_append(&bvh->tree, tree); + + return bvh_build(bvh, mfaces, numfaces); +} + // bvh_overlap - is it possbile for 2 bv's to collide ? int bvh_overlap(float *bv1, float *bv2) { @@ -850,3 +865,20 @@ void bvh_update(BVH * bvh, int moving) } } +void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving) +{ + if(!bvh) + return; + + if(numverts!=bvh->numverts) + return; + + if(x) + memcpy(bvh->x, x, sizeof(MVert) * numverts); + + if(xnew) + memcpy(bvh->xnew, xnew, sizeof(MVert) * numverts); + + bvh_update(bvh, moving); +} + diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 42faf2b2c3f..e9ec26e56ec 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5066,7 +5066,7 @@ static void collisionModifier_deformVerts( // TODO: epsilon // create bounding box hierarchy - collmd->tree = bvh_build(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->current_x, collmd->current_xnew, numverts, ob->pd->pdef_sbift); + collmd->tree = bvh_build_from_mvert(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->current_x, numverts, ob->pd->pdef_sbift); } else if(numverts == collmd->numverts) { @@ -5086,7 +5086,8 @@ static void collisionModifier_deformVerts( memcpy(collmd->current_xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); memcpy(collmd->current_x, dm->getVertArray(dm), numverts*sizeof(MVert)); - bvh_update(collmd->tree, 0); // recalc static bounding boxes + // recalc static bounding boxes + bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0); } collmd->time = current_time; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 0e227f7efbc..c264d684d77 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3268,38 +3268,29 @@ static void object_panel_cloth_II(Object *ob) static void object_panel_cloth_III(Object *ob) { uiBlock *block; - static int val; - uiBut *but; ClothModifierData *clmd = NULL; clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) - { - if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) - { - Cloth *cloth = clmd->clothObject; - char str[128]; - - block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_III", UI_EMBOSS, UI_HELV, curarea->win); - uiNewPanelTabbed("Cloth", "Physics"); - if(uiNewPanel(curarea, block, "Cloth Collisions", "Physics", 651, 0, 318, 204)==0) return; + { + block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_III", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Cloth", "Physics"); + if(uiNewPanel(curarea, block, "Cloth Collisions", "Physics", 651, 0, 318, 204)==0) return; + + uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,70,130,20, &clmd->coll_parms.flags, 0, 0, 0, 0, "Enable collisions with this object"); - if (clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) - { - // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ - uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,30,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); - uiDefBut(block, LABEL, 0, "",160,30,150,20, NULL, 0.0, 0, 0, 0, ""); - } - else - uiDefBut(block, LABEL, 0, "",140,10,170,20, NULL, 0.0, 0, 0, 0, ""); - uiBlockEndAlign(block); + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,70,130,20, &clmd->coll_parms.flags, 0, 0, 0, 0, "Enable collisions with this object"); + if (clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + { + // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ + uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,30,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); + uiDefBut(block, LABEL, 0, "",160,30,150,20, NULL, 0.0, 0, 0, 0, ""); } + else + uiDefBut(block, LABEL, 0, "",140,10,170,20, NULL, 0.0, 0, 0, 0, ""); + uiBlockEndAlign(block); } - // uiBlockEndAlign(block); } From 916cd17778ef306c283adcdffe872c9503358ee0 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 24 Oct 2007 17:13:13 +0000 Subject: [PATCH 034/101] Fixed some bugs in bounding volumes, still some crasher in new cloth modifier --- source/blender/blenkernel/intern/cloth.c | 9 ++++++--- source/blender/blenkernel/intern/kdop.c | 16 ++++++++-------- source/blender/blenkernel/intern/modifier.c | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 4c4bac7bbf9..5ea913788e7 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -699,11 +699,11 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, } tstart(); - +/* // Call the solver. if ( solvers [clmd->sim_parms.solver_type].solver ) solvers [clmd->sim_parms.solver_type].solver ( ob, framenr, clmd, effectors ); - +*/ tend(); printf ( "Cloth simulation time: %f\n", ( float ) tval() ); @@ -735,7 +735,10 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, } } - return result; + if(result) + return result; + else + return dm; } /* frees all */ diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index f2a1e895751..32bab0b4935 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -531,16 +531,9 @@ BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces) CollisionTree **face_list=NULL; CollisionTree *tree=NULL; LinkNode *nlink = NULL; - MFace *mface = NULL; nlink = bvh->tree; - if (tree == NULL) - { - printf("bvh_build: Out of memory for nodes.\n"); - bvh_free(bvh); - return NULL; - } bvh->root = bvh->tree->link; bvh->root->isleaf = 0; bvh->root->parent = NULL; @@ -695,7 +688,14 @@ BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsig bvh->xnew = MEM_dupallocN(x); bvh->x = MEM_dupallocN(x); tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree"); - // TODO: check succesfull alloc + + if (tree == NULL) + { + printf("bvh_build: Out of memory for nodes.\n"); + bvh_free(bvh); + return NULL; + } + BLI_linklist_append(&bvh->tree, tree); return bvh_build(bvh, mfaces, numfaces); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index e9ec26e56ec..4b65381c3b7 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4903,7 +4903,7 @@ static DerivedMesh *clothModifier_applyModifier( CDDM_calc_normals(result); - return derivedData; + return result; } static void clothModifier_updateDepgraph( From f310214cc5a40b20cc9189b60cbd726f9368d99d Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 25 Oct 2007 21:17:55 +0000 Subject: [PATCH 035/101] reverted part of cloth.c and modifier.c back to old code before switch to use "deform_only" modifier (not tested, needs cleanup but compiles) --- source/blender/blenkernel/intern/cloth.c | 686 ++++++++++---------- source/blender/blenkernel/intern/modifier.c | 17 +- 2 files changed, 344 insertions(+), 359 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 5ea913788e7..4692ee5fa3f 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -120,13 +120,12 @@ static CM_SOLVER_DEF solvers [] = /* ********** cloth engine ******* */ /* Prototypes for internal functions. */ -static void cloth_to_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); -static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); -static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); +static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd); +static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr); +static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr); +static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr); int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ); -static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ); - - +static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup); /****************************************************************************** * * External interface called by modifier.c clothModifier functions. @@ -136,9 +135,9 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short * cloth_init - creates a new cloth simulation. * * 1. create object -* 2. fill object with standard values or with the GUI settings if given +* 2. fill object with standard values or with the GUI settings if given */ -void cloth_init ( ClothModifierData *clmd ) +void cloth_init (ClothModifierData *clmd) { /* Initialize our new data structure to reasonable values. */ clmd->sim_parms.gravity [0] = 0.0; @@ -153,17 +152,14 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms.stepsPerFrame = 5; clmd->sim_parms.sim_time = 1.0; clmd->sim_parms.flags = CLOTH_SIMSETTINGS_FLAG_RESET; - clmd->sim_parms.solver_type = 0; + clmd->sim_parms.solver_type = 0; clmd->sim_parms.preroll = 0; clmd->sim_parms.maxspringlen = 10; - clmd->sim_parms.firstframe = 1; - clmd->sim_parms.lastframe = 250; clmd->coll_parms.self_friction = 5.0; clmd->coll_parms.friction = 10.0; clmd->coll_parms.loop_count = 1; clmd->coll_parms.epsilon = 0.01f; - clmd->coll_parms.flags = 0; - + /* These defaults are copied from softbody.c's * softbody_calc_forces() function. */ @@ -181,17 +177,17 @@ void cloth_init ( ClothModifierData *clmd ) } // unused in the moment, cloth needs quads from mesh -DerivedMesh *CDDM_convert_to_triangle ( DerivedMesh *dm ) +DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) { DerivedMesh *result = NULL; int i; - int numverts = dm->getNumVerts ( dm ); - int numedges = dm->getNumEdges ( dm ); - int numfaces = dm->getNumFaces ( dm ); + int numverts = dm->getNumVerts(dm); + int numedges = dm->getNumEdges(dm); + int numfaces = dm->getNumFaces(dm); - MVert *mvert = CDDM_get_verts ( dm ); - MEdge *medge = CDDM_get_edges ( dm ); - MFace *mface = CDDM_get_faces ( dm ); + MVert *mvert = CDDM_get_verts(dm); + MEdge *medge = CDDM_get_edges(dm); + MFace *mface = CDDM_get_faces(dm); MVert *mvert2; MFace *mface2; @@ -203,36 +199,36 @@ DerivedMesh *CDDM_convert_to_triangle ( DerivedMesh *dm ) float vec1[3], vec2[3], vec3[3], vec4[3], vec5[3]; float mag1=0, mag2=0; - for ( i = 0; i < numfaces; i++ ) + for(i = 0; i < numfaces; i++) { - if ( mface[i].v4 ) + if(mface[i].v4) numquads++; else - numtris++; + numtris++; } - result = CDDM_from_template ( dm, numverts, 0, numtris + 2*numquads ); + result = CDDM_from_template(dm, numverts, 0, numtris + 2*numquads); - if ( !result ) + if(!result) return NULL; // do verts - mvert2 = CDDM_get_verts ( result ); - for ( a=0; av1 = mface[a].v2; mf->v2 = mface[a].v3; @@ -260,9 +256,9 @@ DerivedMesh *CDDM_convert_to_triangle ( DerivedMesh *dm ) mf->v4 = 0; mf->flag |= ME_SMOOTH; - test_index_face ( mf, NULL, 0, 3 ); + test_index_face(mf, NULL, 0, 3); - if ( mface[a].v4 ) + if(mface[a].v4) { MFace *mf2; @@ -275,7 +271,7 @@ DerivedMesh *CDDM_convert_to_triangle ( DerivedMesh *dm ) *mf2 = *inMF; */ - if ( random==1 ) + if(random==1) { mf2->v1 = mface[a].v1; mf2->v2 = mface[a].v2; @@ -290,31 +286,32 @@ DerivedMesh *CDDM_convert_to_triangle ( DerivedMesh *dm ) mf2->v4 = 0; mf2->flag |= ME_SMOOTH; - test_index_face ( mf2, NULL, 0, 3 ); + test_index_face(mf2, NULL, 0, 3); } i++; } - CDDM_calc_edges ( result ); - CDDM_calc_normals ( result ); + CDDM_calc_edges(result); + CDDM_calc_normals(result); return result; } -DerivedMesh *CDDM_create_tearing ( ClothModifierData *clmd, DerivedMesh *dm ) +DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) { + /* DerivedMesh *result = NULL; unsigned int i = 0, a = 0, j=0; - int numverts = dm->getNumVerts ( dm ); - int numedges = dm->getNumEdges ( dm ); - int numfaces = dm->getNumFaces ( dm ); + int numverts = dm->getNumVerts(dm); + int numedges = dm->getNumEdges(dm); + int numfaces = dm->getNumFaces(dm); - MVert *mvert = CDDM_get_verts ( dm ); - MEdge *medge = CDDM_get_edges ( dm ); - MFace *mface = CDDM_get_faces ( dm ); + MVert *mvert = CDDM_get_verts(dm); + MEdge *medge = CDDM_get_edges(dm); + MFace *mface = CDDM_get_faces(dm); MVert *mvert2; MFace *mface2; @@ -324,79 +321,80 @@ DerivedMesh *CDDM_create_tearing ( ClothModifierData *clmd, DerivedMesh *dm ) Cloth *cloth = clmd->clothObject; ClothSpring *springs = cloth->springs; unsigned int numsprings = cloth->numsprings; - + // create spring tearing hash edgehash = BLI_edgehash_new(); - - for ( i = 0; i < numsprings; i++ ) + + for(i = 0; i < numsprings; i++) { - if ( ( springs[i].flags & CLOTH_SPRING_FLAG_DEACTIVATE ) - && ( !BLI_edgehash_haskey ( edgehash, springs[i].ij, springs[i].kl ) ) ) + if((springs[i].flags & CSPRING_FLAG_DEACTIVATE) + &&(!BLI_edgehash_haskey(edgehash, springs[i].ij, springs[i].kl))) { - BLI_edgehash_insert ( edgehash, springs[i].ij, springs[i].kl, NULL ); - BLI_edgehash_insert ( edgehash, springs[i].kl, springs[i].ij, NULL ); + BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL); + BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL); j++; } } - + // printf("found %d tears\n", j); + + result = CDDM_from_template(dm, numverts, 0, numfaces); - result = CDDM_from_template ( dm, numverts, 0, numfaces ); - - if ( !result ) + if(!result) return NULL; // do verts - mvert2 = CDDM_get_verts ( result ); - for ( a=0; av1 = mface[a].v1; mf->v2 = mface[a].v2; mf->v3 = mface[a].v3; mf->v4 = mface[a].v4; - - test_index_face ( mf, NULL, 0, 4 ); - + + test_index_face(mf, NULL, 0, 4); + i++; } } - CDDM_lower_num_faces ( result, i ); - CDDM_calc_edges ( result ); - CDDM_calc_normals ( result ); - - BLI_edgehash_free ( edgehash, NULL ); + CDDM_lower_num_faces(result, i); + CDDM_calc_edges(result); + CDDM_calc_normals(result); + + BLI_edgehash_free(edgehash, NULL); return result; + */ } @@ -600,79 +598,54 @@ void cloth_cache_free ( ClothModifierData *clmd, float time ) /** * cloth_deform_verts - simulates one step, framenr is in frames. -* +* **/ -DerivedMesh *clothModifier_do(ClothModifierData *clmd, - Object *ob, DerivedMesh *dm) +DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { unsigned int i; - DerivedMesh *result = NULL; + unsigned int numverts = -1; + unsigned int numedges = -1; + unsigned int numfaces = -1; + MVert *mvert = NULL; + MEdge *medge = NULL; + MFace *mface = NULL; + DerivedMesh *result = NULL, *result2 = NULL; Cloth *cloth = clmd->clothObject; - unsigned int framenr = ( float ) G.scene->r.cfra; - float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); - ListBase *effectors = NULL; - ClothVertex *verts = NULL; + unsigned int framenr = (float)G.scene->r.cfra; + float current_time = bsystem_time(ob, (float)G.scene->r.cfra, 0.0); + ListBase *effectors = NULL; + ClothVertex *newframe= NULL; Frame *frame = NULL; LinkNode *search = NULL; - float deltaTime = current_time - clmd->sim_parms.sim_time; - MVert *mverts = NULL; - - result = CDDM_copy(dm); - - // only be active during a specific period: - // that's "first frame" and "last frame" on GUI - if ( clmd->clothObject ) - { - if ( clmd->sim_parms.cache ) - { - if ( current_time < clmd->sim_parms.firstframe ) - { - int frametime = cloth_cache_first_frame ( clmd ); - if ( cloth_cache_search_frame ( clmd, frametime ) ) - { - cloth_cache_get_frame ( clmd, frametime ); - cloth_to_object ( ob, clmd, result ); - } - return; - } - else if ( current_time > clmd->sim_parms.lastframe ) - { - int frametime = cloth_cache_last_frame ( clmd ); - if ( cloth_cache_search_frame ( clmd, frametime ) ) - { - cloth_cache_get_frame ( clmd, frametime ); - cloth_to_object ( ob, clmd, result ); - } - return; - } - else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed - { - if ( cloth_cache_search_frame ( clmd, framenr ) ) - { - cloth_cache_get_frame ( clmd, framenr ); - cloth_to_object ( ob, clmd, result ); - } - clmd->sim_parms.sim_time = current_time; - return; - } - } + float deltaTime = current_time - clmd->sim_parms.sim_time; + clmd->sim_parms.dt = 1.0f / (clmd->sim_parms.stepsPerFrame * G.scene->r.frs_sec); + + result = CDDM_copy(dm); + + if(!result) + { + return dm; } - - // unused in the moment, calculated seperately in implicit.c - clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame; + + numverts = result->getNumVerts(result); + numedges = result->getNumEdges(result); + numfaces = result->getNumFaces(result); + mvert = CDDM_get_verts(result); + medge = CDDM_get_edges(result); + mface = CDDM_get_faces(result); clmd->sim_parms.sim_time = current_time; - if ( deltaTime == 1.0f ) + if(deltaTime == 1.0f) { - if ( ( clmd->clothObject == NULL ) || ( dm->getNumVerts(dm) != clmd->clothObject->numverts ) ) + if ((clmd->clothObject == NULL) || (numverts != clmd->clothObject->numverts) ) { - if ( !cloth_from_object ( ob, clmd, dm ) ) - return; + if(!cloth_from_object (ob, clmd, result, dm, framenr)) + return result; - if ( clmd->clothObject == NULL ) - return; + if(clmd->clothObject == NULL) + return result; cloth = clmd->clothObject; } @@ -680,47 +653,56 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, clmd->clothObject->old_solver_type = clmd->sim_parms.solver_type; // Insure we have a clmd->clothObject, in case allocation failed. - if ( clmd->clothObject != NULL ) - { - if ( !cloth_cache_search_frame ( clmd, framenr ) ) - { - verts = cloth->verts; - mverts = dm->getVertArray(dm); + if (clmd->clothObject != NULL) + { + + cloth->mfaces = mface; // update face pointer + ((BVH *)cloth->tree)->mfaces = mface; + cloth->numfaces = numfaces; + ((BVH *)cloth->tree)->numfaces = numfaces; - // Force any pinned verts to their constrained location. - for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) + if(!cloth_cache_search_frame(clmd, framenr)) + { + /* Force any pinned verts to their constrained location. */ + for (i = 0; i < clmd->clothObject->numverts; i++) { - // Save the previous position. - VECCOPY ( verts->xold, verts->xconst ); - VECCOPY ( verts->txold, verts->x ); - // Get the current position. - VECCOPY ( verts->xconst, mverts[i].co ); - Mat4MulVecfl ( ob->obmat, verts->xconst ); + /* Save the previous position. */ + VECCOPY (cloth->verts [i].xold, cloth->verts [i].xconst); + VECCOPY (cloth->verts [i].txold, cloth->verts [i].x); + + /* Get the current position. */ + VECCOPY (cloth->verts [i].xconst, mvert[i].co); + Mat4MulVecfl(ob->obmat, cloth->verts [i].xconst); + + /* Compute the vertices velocity. */ + VECSUB (cloth->verts [i].v, cloth->verts [i].x, cloth->verts [i].xold); } tstart(); -/* - // Call the solver. - if ( solvers [clmd->sim_parms.solver_type].solver ) - solvers [clmd->sim_parms.solver_type].solver ( ob, framenr, clmd, effectors ); -*/ - tend(); - printf ( "Cloth simulation time: %f\n", ( float ) tval() ); - cloth_cache_set_frame ( clmd, framenr ); + /* Call the solver. */ + + if (solvers [clmd->sim_parms.solver_type].solver) + solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors); + + tend(); + + // printf("Cloth simulation time: %f\n", (float)tval()); + + cloth_cache_set_frame(clmd, framenr); } else // just retrieve the cached frame { - cloth_cache_get_frame ( clmd, framenr ); + cloth_cache_get_frame(clmd, framenr); } // Copy the result back to the object. - cloth_to_object ( ob, clmd, result ); - + cloth_to_object (ob, result, clmd); + // bvh_free(clmd->clothObject->tree); // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); - } + } } else if ( ( deltaTime <= 0.0f ) || ( deltaTime > 1.0f ) ) @@ -729,47 +711,44 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, { if ( cloth_cache_search_frame ( clmd, framenr ) ) { - cloth_cache_get_frame ( clmd, framenr ); - cloth_to_object ( ob, clmd, result ); + cloth_cache_get_frame(clmd, framenr); + cloth_to_object (ob, result, clmd); } } } - if(result) - return result; - else - return dm; + return result; } /* frees all */ -void cloth_free_modifier ( ClothModifierData *clmd ) +void cloth_free_modifier (ClothModifierData *clmd) { Cloth *cloth = NULL; - if ( !clmd ) + if(!clmd) return; cloth = clmd->clothObject; - if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT ) ) - { - // free our frame cache, TODO: but get to first position before - cloth_cache_free ( clmd, 0 ); + // free our frame cache + cloth_cache_free(clmd, 0); - if ( cloth ) - { + /* Calls the solver and collision frees first as they + * might depend on data in clmd->clothObject. */ - // If our solver provides a free function, call it - if ( cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free ) - { - solvers [cloth->old_solver_type].free ( clmd ); - } + if (cloth) + { + // If our solver provides a free function, call it + if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free) + { + solvers [cloth->old_solver_type].free (clmd); + } + + // Free the verts. + if (cloth->verts != NULL) + MEM_freeN (cloth->verts); - // Free the verts. - if ( cloth->verts != NULL ) - MEM_freeN ( cloth->verts ); - - // Free the verts. + // Free the verts. if ( cloth->x != NULL ) MEM_freeN ( cloth->x ); @@ -777,9 +756,9 @@ void cloth_free_modifier ( ClothModifierData *clmd ) if ( cloth->xnew != NULL ) MEM_freeN ( cloth->xnew ); - cloth->verts = NULL; - cloth->numverts = 0; - + cloth->verts = NULL; + cloth->numverts = -1; + // Free the springs. if ( cloth->springs != NULL ) { @@ -796,27 +775,20 @@ void cloth_free_modifier ( ClothModifierData *clmd ) cloth->springs = NULL; } - cloth->springs = NULL; - cloth->numsprings = 0; -/* - // free BVH collision tree - if ( cloth->tree ) - bvh_free ( ( BVH * ) cloth->tree ); -*/ - // we save our faces for collision objects - if ( cloth->mfaces ) - MEM_freeN ( cloth->mfaces ); - /* - if(clmd->clothObject->facemarks) - MEM_freeN(clmd->clothObject->facemarks); - */ - MEM_freeN ( cloth ); - clmd->clothObject = NULL; - } + cloth->numsprings = -1; + + // free BVH collision tree + if(cloth->tree) + bvh_free((BVH *)cloth->tree); + + MEM_freeN (cloth); + clmd->clothObject = NULL; } + } + /****************************************************************************** * * Internal functions. @@ -828,24 +800,26 @@ void cloth_free_modifier ( ClothModifierData *clmd ) * * This function is a modified version of the softbody.c:softbody_to_object() function. **/ -static void cloth_to_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) +static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd) { ClothVertex *verts = NULL; unsigned int i = 0; - MVert *mvert = NULL; + MVert *mvert = NULL; + unsigned int numverts; - if ( clmd->clothObject ) - { + if (clmd->clothObject) { verts = clmd->clothObject->verts; - mvert = dm->getVertArray(dm); /* inverse matrix is not uptodate... */ - Mat4Invert ( ob->imat, ob->obmat ); + Mat4Invert (ob->imat, ob->obmat); - for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) + mvert = CDDM_get_verts(dm); + numverts = dm->getNumVerts(dm); + + for (i = 0; i < numverts; i++, verts++) { - VECCOPY ( mvert[i].co, verts->x ); - Mat4MulVecfl ( ob->imat, mvert[i].co ); /* softbody is in global coords */ + VECCOPY (mvert[i].co, verts->x); + Mat4MulVecfl (ob->imat, mvert[i].co); /* softbody is in global coords */ } } } @@ -855,48 +829,43 @@ static void cloth_to_object ( Object *ob, ClothModifierData *clmd, DerivedMesh * * cloth_apply_vgroup - applies a vertex group as specified by type * **/ -static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ) +static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup) { - unsigned int i = 0; - unsigned int j = 0; - MDeformVert *dvert = NULL; - Cloth *clothObj = NULL; - unsigned int numverts = dm->getNumVerts ( dm ); - float goalfac = 0; - ClothVertex *verts = NULL; + unsigned int i; + int j; + MDeformVert *dvert = NULL; + Cloth *clothObj; + unsigned int numverts = dm->getNumVerts(dm); + float goalfac; clothObj = clmd->clothObject; - if ( !dm ) - return; - - numverts = dm->getNumVerts ( dm ); - /* vgroup is 1 based, decrement so we can match the right group. */ --vgroup; - verts = clothObj->verts; - - for ( i = 0; i < numverts; i++, verts++ ) - { + for (i = 0; i < numverts; ++i) + { + /* so this will definily be below SOFTGOALSNAP */ + clothObj->verts [i].goal= 0.0f; + // LATER ON, support also mass painting here - if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - { - dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT ); - if ( dvert ) - { - for ( j = 0; j < dvert->totweight; j++ ) + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + { + dvert = dm->getVertData(dm, i, CD_MDEFORMVERT); + if(dvert) + { + for(j = 0; j < dvert->totweight; j++) { - if ( dvert->dw[j].def_nr == vgroup ) + if(dvert->dw[j].def_nr == vgroup) { - verts->goal = dvert->dw [j].weight; + clothObj->verts [i].goal = dvert->dw [j].weight; - goalfac= ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal ); - verts->goal = ( float ) pow ( verts->goal , 4.0f ); + goalfac= ABS(clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal); + clothObj->verts [i].goal = (float)pow(clothObj->verts [i].goal , 4.0f); - if ( dvert->dw [j].weight >=SOFTGOALSNAP ) + if(dvert->dw [j].weight >=SOFTGOALSNAP) { - verts->flags |= CVERT_FLAG_PINNED; + clothObj->verts[i].flags |= CVERT_FLAG_PINNED; } // TODO enable mass painting here, for the moment i let "goals" go first @@ -910,158 +879,173 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short } // only meshes supported at the moment -static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) +/* collision objects */ +static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr) { - unsigned int i = 0; - // dm->getNumVerts(dm); - MVert *mvert = NULL; // CDDM_get_verts(dm); - ClothVertex *verts = NULL; - float tnull[3] = {0,0,0}; + unsigned int i; + unsigned int numverts = dm->getNumVerts(dm); + MVert *mvert = CDDM_get_verts(dm); + switch (ob->type) + { + case OB_MESH: + cloth_from_mesh (ob, clmd, dm, framenr); + + if (clmd->clothObject != NULL) + { + + for (i = 0; i < numverts; ++i) + { + VECCOPY (clmd->clothObject->verts [i].x, mvert[i].co); + Mat4MulVecfl(ob->obmat, clmd->clothObject->verts [i].x); + clmd->clothObject->verts [i].flags = 0; + VECCOPY(clmd->clothObject->verts [i].xold, clmd->clothObject->verts [i].x); + VECCOPY(clmd->clothObject->verts [i].txold, clmd->clothObject->verts [i].x); + VECCOPY(clmd->clothObject->verts [i].tx, clmd->clothObject->verts [i].x); + VecMulf(clmd->clothObject->verts [i].v, 0.0f); + } + clmd->clothObject->tree = bvh_build(clmd, 0.001f); + + } + + return 1; + default: return 0; // TODO - we do not support changing meshes + } +} + +// only meshes supported at the moment +static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr) +{ + unsigned int i; + unsigned int numverts = dm->getNumVerts(dm); + MVert *mvert = CDDM_get_verts(dm); + /* If we have a clothObject, free it. */ - if ( clmd->clothObject != NULL ) - cloth_free_modifier ( clmd ); + if (clmd->clothObject != NULL) + cloth_free_modifier (clmd); /* Allocate a new cloth object. */ - clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" ); - if ( clmd->clothObject ) + clmd->clothObject = MEM_callocN (sizeof(Cloth), "cloth"); + if (clmd->clothObject) { - clmd->clothObject->old_solver_type = 255; - // clmd->clothObject->old_collision_type = 255; + clmd->clothObject->old_solver_type = -1; } - else if ( !clmd->clothObject ) + else if (clmd->clothObject == NULL) { - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject." ); + modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject."); return 0; } + + printf("cloth_from_object\n"); - switch ( ob->type ) + switch (ob->type) { case OB_MESH: + + cloth_from_mesh (ob, clmd, dm, framenr); - // mesh input objects need DerivedMesh - if ( !dm ) - return 0; + if (clmd->clothObject != NULL) + { + /* create springs */ + clmd->clothObject->springs = NULL; + clmd->clothObject->numsprings = -1; - cloth_from_mesh ( ob, clmd, dm ); - - if ( clmd->clothObject != NULL ) + if (!cloth_build_springs (clmd->clothObject, dm) ) { - /* create springs */ - clmd->clothObject->springs = NULL; - clmd->clothObject->numsprings = -1; + modifier_setError (&(clmd->modifier), "Can't build springs."); + return 0; + } - if ( !cloth_build_springs ( clmd->clothObject, dm ) ) - { - modifier_setError ( & ( clmd->modifier ), "Can't build springs." ); - return 0; - } + /* set initial values */ + for (i = 0; i < numverts; ++i) + { + VECCOPY (clmd->clothObject->verts [i].x, mvert[i].co); + Mat4MulVecfl(ob->obmat, clmd->clothObject->verts [i].x); - mvert = dm->getVertArray ( dm ); // CDDM_get_verts ( dm ); - verts = clmd->clothObject->verts; - - /* set initial values */ - for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) - { - VECCOPY ( verts->x, mvert[i].co ); - Mat4MulVecfl ( ob->obmat, verts->x ); - - verts->mass = clmd->sim_parms.mass; - - if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - verts->goal= clmd->sim_parms.defgoal; - else - verts->goal= 0.0f; - - verts->flags = 0; - VECCOPY ( verts->xold, verts->x ); - VECCOPY ( verts->xconst, verts->x ); - VECCOPY ( verts->txold, verts->x ); - VecMulf ( verts->v, 0.0f ); - - verts->impulse_count = 0; - VECCOPY ( verts->impulse, tnull ); - } - - // apply / set vertex groups - if ( clmd->sim_parms.vgroup_mass > 0 ) - cloth_apply_vgroup ( clmd, dm, clmd->sim_parms.vgroup_mass ); - - // init our solver - if ( solvers [clmd->sim_parms.solver_type].init ) - solvers [clmd->sim_parms.solver_type].init ( ob, clmd ); - - // clmd->clothObject->tree = bvh_build ( dm, clmd->coll_parms.epsilon ); - - cloth_cache_set_frame ( clmd, 1 ); + clmd->clothObject->verts [i].mass = clmd->sim_parms.mass; + clmd->clothObject->verts [i].goal= clmd->sim_parms.defgoal; + clmd->clothObject->verts [i].flags = 0; + VECCOPY(clmd->clothObject->verts [i].xold, clmd->clothObject->verts [i].x); + VECCOPY(clmd->clothObject->verts [i].xconst, clmd->clothObject->verts [i].x); + VECCOPY(clmd->clothObject->verts [i].txold, clmd->clothObject->verts [i].x); + VecMulf(clmd->clothObject->verts [i].v, 0.0f); } - return 1; + /* apply / set vertex groups */ + if (clmd->sim_parms.vgroup_mass > 0) + cloth_apply_vgroup (clmd, olddm, clmd->sim_parms.vgroup_mass); + + /* init our solver */ + if (solvers [clmd->sim_parms.solver_type].init) + solvers [clmd->sim_parms.solver_type].init (ob, clmd); + + clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); + + cloth_cache_set_frame(clmd, 1); + } + + return 1; case OB_LATTICE: - printf ( "Not supported: OB_LATTICE\n" ); - // lattice_to_softbody(ob); - return 1; + printf("OB_LATTICE\n"); + // lattice_to_softbody(ob); + return 1; case OB_CURVE: case OB_SURF: - printf ( "Not supported: OB_SURF| OB_CURVE\n" ); - return 1; + printf("OB_SURF| OB_CURVE\n"); + return 1; default: return 0; // TODO - we do not support changing meshes } - + return 0; } -static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) +static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr) { - unsigned int numverts = dm->getNumVerts ( dm ); - unsigned int numfaces = dm->getNumFaces ( dm ); - MFace *mface = dm->getFaceArray ( dm ); + unsigned int numverts = dm->getNumVerts(dm); + unsigned int numfaces = dm->getNumFaces(dm); + MFace *mface = CDDM_get_faces(dm); unsigned int i = 0; /* Allocate our vertices. */ clmd->clothObject->numverts = numverts; - clmd->clothObject->verts = MEM_callocN ( sizeof ( ClothVertex ) * clmd->clothObject->numverts, "clothVertex" ); - if ( clmd->clothObject->verts == NULL ) + clmd->clothObject->verts = MEM_callocN (sizeof (ClothVertex) * clmd->clothObject->numverts, "clothVertex"); + if (clmd->clothObject->verts == NULL) { - cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." ); + cloth_free_modifier (clmd); + modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts."); return; } - clmd->clothObject->x = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_x" ); - if ( clmd->clothObject->x == NULL ) + // collision objects need to cache face infos since they are needed during collision detection + // TODO: maybe cache it for cloth objects, too + if (clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) { - cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->x." ); - return; + clmd->clothObject->numfaces = numfaces; + clmd->clothObject->mfaces = MEM_callocN (sizeof (MFace) * clmd->clothObject->numfaces, "clothMFaces"); + if (clmd->clothObject->mfaces == NULL) + { + cloth_free_modifier (clmd); + modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->mfaces."); + return; + } + for(i = 0; i < numfaces; i++) + memcpy(&clmd->clothObject->mfaces[i], &mface[i], sizeof(MFace)); + } + else + { + clmd->clothObject->mfaces = mface; // update face pointer + clmd->clothObject->numfaces = numfaces; } - clmd->clothObject->xnew = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_xnew" ); - if ( clmd->clothObject->xnew == NULL ) - { - cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xnew." ); - return; - } - - // save face information - clmd->clothObject->numfaces = numfaces; - clmd->clothObject->mfaces = MEM_callocN ( sizeof ( MFace ) * clmd->clothObject->numfaces, "clothMFaces" ); - if ( clmd->clothObject->mfaces == NULL ) - { - cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->mfaces." ); - return; - } - for ( i = 0; i < numfaces; i++ ) - memcpy ( &clmd->clothObject->mfaces[i], &mface[i], sizeof ( MFace ) ); + // for SIP code + // clmd->clothObject->facemarks = MEM_callocN (sizeof (unsigned char) * clmd->clothObject->numfaces, "clothFaceMarks"); /* Free the springs since they can't be correct if the vertices * changed. */ - if ( clmd->clothObject->springs != NULL ) - MEM_freeN ( clmd->clothObject->springs ); + if (clmd->clothObject->springs != NULL) + MEM_freeN (clmd->clothObject->springs); } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 4b65381c3b7..fcb56b56a5a 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4892,18 +4892,19 @@ static void clothModifier_deformVerts( */ static DerivedMesh *clothModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) { - DerivedMesh *result = NULL; - ClothModifierData *clmd = (ClothModifierData*) md; + DerivedMesh *result=NULL; - result = clothModifier_do(clmd, ob, derivedData); + result = clothModifier_do(clmd, ob, derivedData, useRenderParams, isFinalCalc); - CDDM_calc_normals(result); - - return result; + if(result) + { + return result; + } + return derivedData; } static void clothModifier_updateDepgraph( From 096a1e87fc179936edad72ef700bdf7fd672af8b Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 25 Oct 2007 22:09:06 +0000 Subject: [PATCH 036/101] Fixed all known crashers, still have to verify a few things, and compiling works on gxx too, now --- source/blender/blenkernel/BKE_cloth.h | 2 +- source/blender/blenkernel/intern/cloth.c | 131 ++++++----------------- 2 files changed, 36 insertions(+), 97 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 19851321b30..5379f0478d3 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -122,7 +122,7 @@ void cloth_free_modifier ( ClothModifierData *clmd ); void implicit_set_positions ( ClothModifierData *clmd ); // from cloth.c, needed for modifier.c -DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm); +DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc); //////////////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 4692ee5fa3f..427b6bc6fe9 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -654,13 +654,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d // Insure we have a clmd->clothObject, in case allocation failed. if (clmd->clothObject != NULL) - { - - cloth->mfaces = mface; // update face pointer - ((BVH *)cloth->tree)->mfaces = mface; - cloth->numfaces = numfaces; - ((BVH *)cloth->tree)->numfaces = numfaces; - + { if(!cloth_cache_search_frame(clmd, framenr)) { /* Force any pinned verts to their constrained location. */ @@ -747,35 +741,39 @@ void cloth_free_modifier (ClothModifierData *clmd) // Free the verts. if (cloth->verts != NULL) MEM_freeN (cloth->verts); + + // Free the faces. + if ( cloth->mfaces != NULL ) + MEM_freeN ( cloth->mfaces ); // Free the verts. - if ( cloth->x != NULL ) - MEM_freeN ( cloth->x ); - - // Free the verts. - if ( cloth->xnew != NULL ) - MEM_freeN ( cloth->xnew ); + if ( cloth->x != NULL ) + MEM_freeN ( cloth->x ); + + // Free the verts. + if ( cloth->xnew != NULL ) + MEM_freeN ( cloth->xnew ); cloth->verts = NULL; cloth->numverts = -1; - // Free the springs. - if ( cloth->springs != NULL ) + // Free the springs. + if ( cloth->springs != NULL ) + { + LinkNode *search = cloth->springs; + while(search) { - LinkNode *search = cloth->springs; - while(search) - { - ClothSpring *spring = search->link; - - MEM_freeN ( spring ); - search = search->next; - } - BLI_linklist_free(cloth->springs, NULL); - - cloth->springs = NULL; + ClothSpring *spring = search->link; + + MEM_freeN ( spring ); + search = search->next; } + BLI_linklist_free(cloth->springs, NULL); + + cloth->springs = NULL; + } - cloth->numsprings = -1; + cloth->numsprings = -1; // free BVH collision tree if(cloth->tree) @@ -877,41 +875,6 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v } } } - -// only meshes supported at the moment -/* collision objects */ -static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr) -{ - unsigned int i; - unsigned int numverts = dm->getNumVerts(dm); - MVert *mvert = CDDM_get_verts(dm); - - switch (ob->type) - { - case OB_MESH: - cloth_from_mesh (ob, clmd, dm, framenr); - - if (clmd->clothObject != NULL) - { - - for (i = 0; i < numverts; ++i) - { - VECCOPY (clmd->clothObject->verts [i].x, mvert[i].co); - Mat4MulVecfl(ob->obmat, clmd->clothObject->verts [i].x); - clmd->clothObject->verts [i].flags = 0; - VECCOPY(clmd->clothObject->verts [i].xold, clmd->clothObject->verts [i].x); - VECCOPY(clmd->clothObject->verts [i].txold, clmd->clothObject->verts [i].x); - VECCOPY(clmd->clothObject->verts [i].tx, clmd->clothObject->verts [i].x); - VecMulf(clmd->clothObject->verts [i].v, 0.0f); - } - clmd->clothObject->tree = bvh_build(clmd, 0.001f); - - } - - return 1; - default: return 0; // TODO - we do not support changing meshes - } -} // only meshes supported at the moment static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr) @@ -928,15 +891,13 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject = MEM_callocN (sizeof(Cloth), "cloth"); if (clmd->clothObject) { - clmd->clothObject->old_solver_type = -1; + clmd->clothObject->old_solver_type = 255; } else if (clmd->clothObject == NULL) { modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject."); return 0; } - - printf("cloth_from_object\n"); switch (ob->type) { @@ -979,19 +940,11 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if (solvers [clmd->sim_parms.solver_type].init) solvers [clmd->sim_parms.solver_type].init (ob, clmd); - clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); + clmd->clothObject->tree = NULL; // bvh_build(clmd, clmd->coll_parms.epsilon); cloth_cache_set_frame(clmd, 1); } - return 1; - case OB_LATTICE: - printf("OB_LATTICE\n"); - // lattice_to_softbody(ob); - return 1; - case OB_CURVE: - case OB_SURF: - printf("OB_SURF| OB_CURVE\n"); return 1; default: return 0; // TODO - we do not support changing meshes } @@ -1017,29 +970,15 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - // collision objects need to cache face infos since they are needed during collision detection - // TODO: maybe cache it for cloth objects, too - if (clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + clmd->clothObject->numfaces = numfaces; + clmd->clothObject->mfaces = MEM_callocN (sizeof (MFace) * clmd->clothObject->numfaces, "clothMFaces"); + if (clmd->clothObject->mfaces == NULL) { - clmd->clothObject->numfaces = numfaces; - clmd->clothObject->mfaces = MEM_callocN (sizeof (MFace) * clmd->clothObject->numfaces, "clothMFaces"); - if (clmd->clothObject->mfaces == NULL) - { - cloth_free_modifier (clmd); - modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->mfaces."); - return; - } - for(i = 0; i < numfaces; i++) - memcpy(&clmd->clothObject->mfaces[i], &mface[i], sizeof(MFace)); + cloth_free_modifier (clmd); + modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->mfaces."); + return; } - else - { - clmd->clothObject->mfaces = mface; // update face pointer - clmd->clothObject->numfaces = numfaces; - } - - // for SIP code - // clmd->clothObject->facemarks = MEM_callocN (sizeof (unsigned char) * clmd->clothObject->numfaces, "clothFaceMarks"); + memcpy(clmd->clothObject->mfaces, mface, sizeof(MFace)*numfaces); /* Free the springs since they can't be correct if the vertices * changed. @@ -1133,7 +1072,7 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) BLI_linklist_append ( &cloth->springs, spring ); } } - + // shear springs for ( i = 0; i < numfaces; i++ ) { From f59a4c22150f1db3f54e1d0847881e726518fc11 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 25 Oct 2007 23:10:42 +0000 Subject: [PATCH 037/101] Fixing some goal problem --- source/blender/blenkernel/intern/cloth.c | 146 ++++++++++++++++------- 1 file changed, 106 insertions(+), 40 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 427b6bc6fe9..5c23926e907 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -623,6 +623,44 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d result = CDDM_copy(dm); + // only be active during a specific period: + // that's "first frame" and "last frame" on GUI + if ( clmd->clothObject ) + { + if ( clmd->sim_parms.cache ) + { + if ( current_time < clmd->sim_parms.firstframe ) + { + int frametime = cloth_cache_first_frame ( clmd ); + if ( cloth_cache_search_frame ( clmd, frametime ) ) + { + cloth_cache_get_frame ( clmd, frametime ); + cloth_to_object ( ob, result, clmd ); + } + return; + } + else if ( current_time > clmd->sim_parms.lastframe ) + { + int frametime = cloth_cache_last_frame ( clmd ); + if ( cloth_cache_search_frame ( clmd, frametime ) ) + { + cloth_cache_get_frame ( clmd, frametime ); + cloth_to_object ( ob, result, clmd ); + } + return; + } + else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed + { + if ( cloth_cache_search_frame ( clmd, framenr ) ) + { + cloth_cache_get_frame ( clmd, framenr ); + cloth_to_object ( ob, result, clmd ); + } + clmd->sim_parms.sim_time = current_time; + return; + } + } + if(!result) { return dm; @@ -657,19 +695,15 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d { if(!cloth_cache_search_frame(clmd, framenr)) { - /* Force any pinned verts to their constrained location. */ - for (i = 0; i < clmd->clothObject->numverts; i++) + // Force any pinned verts to their constrained location. + for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) { - /* Save the previous position. */ - VECCOPY (cloth->verts [i].xold, cloth->verts [i].xconst); - VECCOPY (cloth->verts [i].txold, cloth->verts [i].x); - - /* Get the current position. */ - VECCOPY (cloth->verts [i].xconst, mvert[i].co); - Mat4MulVecfl(ob->obmat, cloth->verts [i].xconst); - - /* Compute the vertices velocity. */ - VECSUB (cloth->verts [i].v, cloth->verts [i].x, cloth->verts [i].xold); + // Save the previous position. + VECCOPY ( verts->xold, verts->xconst ); + VECCOPY ( verts->txold, verts->x ); + // Get the current position. + VECCOPY ( verts->xconst, mverts[i].co ); + Mat4MulVecfl ( ob->obmat, verts->xconst ); } tstart(); @@ -829,41 +863,46 @@ static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *cl **/ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup) { - unsigned int i; - int j; + unsigned int i = 0; + unsigned int j = 0; MDeformVert *dvert = NULL; - Cloth *clothObj; - unsigned int numverts = dm->getNumVerts(dm); - float goalfac; + Cloth *clothObj = NULL; + unsigned int numverts = 0; + float goalfac = 0; + ClothVertex *verts = NULL; clothObj = clmd->clothObject; + if ( !dm ) + return; + + numverts = dm->getNumVerts(dm); + /* vgroup is 1 based, decrement so we can match the right group. */ --vgroup; - for (i = 0; i < numverts; ++i) - { - /* so this will definily be below SOFTGOALSNAP */ - clothObj->verts [i].goal= 0.0f; - + verts = clothObj->verts; + + for ( i = 0; i < numverts; i++, verts++ ) + { // LATER ON, support also mass painting here - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - { - dvert = dm->getVertData(dm, i, CD_MDEFORMVERT); - if(dvert) - { - for(j = 0; j < dvert->totweight; j++) + if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + { + dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT ); + if ( dvert ) + { + for ( j = 0; j < dvert->totweight; j++ ) { - if(dvert->dw[j].def_nr == vgroup) + if ( dvert->dw[j].def_nr == vgroup ) { - clothObj->verts [i].goal = dvert->dw [j].weight; + verts->goal = dvert->dw [j].weight; - goalfac= ABS(clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal); - clothObj->verts [i].goal = (float)pow(clothObj->verts [i].goal , 4.0f); + goalfac= ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal ); + verts->goal = ( float ) pow ( verts->goal , 4.0f ); - if(dvert->dw [j].weight >=SOFTGOALSNAP) + if ( dvert->dw [j].weight >=SOFTGOALSNAP ) { - clothObj->verts[i].flags |= CVERT_FLAG_PINNED; + verts->flags |= CVERT_FLAG_PINNED; } // TODO enable mass painting here, for the moment i let "goals" go first @@ -903,13 +942,17 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d { case OB_MESH: + // mesh input objects need DerivedMesh + if ( !dm ) + return 0; + cloth_from_mesh (ob, clmd, dm, framenr); - if (clmd->clothObject != NULL) - { - /* create springs */ - clmd->clothObject->springs = NULL; - clmd->clothObject->numsprings = -1; + if ( clmd->clothObject != NULL ) + { + /* create springs */ + clmd->clothObject->springs = NULL; + clmd->clothObject->numsprings = -1; if (!cloth_build_springs (clmd->clothObject, dm) ) { @@ -924,12 +967,18 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d Mat4MulVecfl(ob->obmat, clmd->clothObject->verts [i].x); clmd->clothObject->verts [i].mass = clmd->sim_parms.mass; - clmd->clothObject->verts [i].goal= clmd->sim_parms.defgoal; + if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + clmd->clothObject->verts [i].goal= clmd->sim_parms.defgoal; + else + clmd->clothObject->verts [i].goal= 0.0f; clmd->clothObject->verts [i].flags = 0; VECCOPY(clmd->clothObject->verts [i].xold, clmd->clothObject->verts [i].x); VECCOPY(clmd->clothObject->verts [i].xconst, clmd->clothObject->verts [i].x); VECCOPY(clmd->clothObject->verts [i].txold, clmd->clothObject->verts [i].x); VecMulf(clmd->clothObject->verts [i].v, 0.0f); + + clmd->clothObject->verts [i].impulse_count = 0; + VECCOPY ( clmd->clothObject->verts [i].impulse, tnull ); } /* apply / set vertex groups */ @@ -970,6 +1019,23 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } + clmd->clothObject->x = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_x" ); + if ( clmd->clothObject->x == NULL ) + { + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->x." ); + return; + } + + clmd->clothObject->xnew = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_xnew" ); + if ( clmd->clothObject->xnew == NULL ) + { + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xnew." ); + return; + } + + // save face information clmd->clothObject->numfaces = numfaces; clmd->clothObject->mfaces = MEM_callocN (sizeof (MFace) * clmd->clothObject->numfaces, "clothMFaces"); if (clmd->clothObject->mfaces == NULL) From a61fb914ecfe8ba6af4de33db6bbb89d74f67bcd Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 26 Oct 2007 10:46:40 +0000 Subject: [PATCH 038/101] Fixed compiling errors + introduced old speedup for springs again --- source/blender/blenkernel/BKE_cloth.h | 2 + source/blender/blenkernel/intern/cloth.c | 202 +++++++++++++------- source/blender/blenkernel/intern/implicit.c | 46 ++--- source/blender/makesdna/DNA_cloth_types.h | 12 +- 4 files changed, 164 insertions(+), 98 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 5379f0478d3..6b1110d6625 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -173,6 +173,8 @@ typedef struct Frame ClothSpring *springs; unsigned int numverts, numsprings; float time; /* we need float since we want to support sub-frames */ + float (*x)[3]; + float (*xold)[3]; } Frame; diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 5c23926e907..c4c32d48b82 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -123,7 +123,7 @@ static CM_SOLVER_DEF solvers [] = static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd); static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr); static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr); -static int collobj_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr); + int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ); static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup); /****************************************************************************** @@ -179,6 +179,7 @@ void cloth_init (ClothModifierData *clmd) // unused in the moment, cloth needs quads from mesh DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) { + /* DerivedMesh *result = NULL; int i; int numverts = dm->getNumVerts(dm); @@ -234,11 +235,11 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) MFace *inMF; inMF = &mface[a]; - /* - DM_copy_face_data(dm, result, a, i, 1); + + // DM_copy_face_data(dm, result, a, i, 1); - *mf = *inMF; - */ + // *mf = *inMF; + if(mface[a].v4 && random==1) { @@ -265,11 +266,11 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) i++; mf2 = &mface2[i]; - /* - DM_copy_face_data(dm, result, a, i, 1); + + // DM_copy_face_data(dm, result, a, i, 1); - *mf2 = *inMF; - */ + // *mf2 = *inMF; + if(random==1) { @@ -296,7 +297,9 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) CDDM_calc_normals(result); return result; - + */ + + return NULL; } @@ -395,6 +398,8 @@ DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) return result; */ + + return NULL; } @@ -505,6 +510,11 @@ void cloth_cache_get_frame ( ClothModifierData *clmd, float time ) } memcpy ( clmd->clothObject->verts, frame->verts, sizeof ( ClothVertex ) *frame->numverts ); + + memcpy ( clmd->clothObject->x, frame->x, sizeof ( float ) *frame->numverts * 3); + + memcpy ( clmd->clothObject->xold, frame->xold, sizeof ( float ) *frame->numverts * 3); + implicit_set_positions ( clmd ); return; @@ -519,7 +529,6 @@ void cloth_cache_get_frame ( ClothModifierData *clmd, float time ) void cloth_cache_set_frame ( ClothModifierData *clmd, float time ) { Frame *frame = NULL; - LinkNode *search = NULL; if ( clmd->clothObject ) { @@ -536,7 +545,26 @@ void cloth_cache_set_frame ( ClothModifierData *clmd, float time ) MEM_freeN ( frame ); return; } - + + frame->x = MEM_dupallocN ( clmd->clothObject->x ); + + if ( !frame->x ) + { + MEM_freeN ( frame->verts ); + MEM_freeN ( frame ); + return; + } + + frame->xold = MEM_dupallocN ( clmd->clothObject->xold ); + + if ( !frame->xold ) + { + MEM_freeN ( frame->verts ); + MEM_freeN ( frame->x ); + MEM_freeN ( frame ); + return; + } + BLI_linklist_append ( &clmd->sim_parms.cache, frame ); } @@ -570,6 +598,14 @@ void cloth_cache_free ( ClothModifierData *clmd, float time ) { MEM_freeN ( frame->verts ); } + if ( frame->x ) + { + MEM_freeN ( frame->x ); + } + if ( frame->xold ) + { + MEM_freeN ( frame->xold ); + } MEM_freeN ( frame ); lastsearch->next = search->next; @@ -609,22 +645,35 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d MVert *mvert = NULL; MEdge *medge = NULL; MFace *mface = NULL; - DerivedMesh *result = NULL, *result2 = NULL; + DerivedMesh *result = NULL; Cloth *cloth = clmd->clothObject; unsigned int framenr = (float)G.scene->r.cfra; float current_time = bsystem_time(ob, (float)G.scene->r.cfra, 0.0); - ListBase *effectors = NULL; - ClothVertex *newframe= NULL; - Frame *frame = NULL; - LinkNode *search = NULL; + ListBase *effectors = NULL; + ClothVertex *verts = NULL; float deltaTime = current_time - clmd->sim_parms.sim_time; clmd->sim_parms.dt = 1.0f / (clmd->sim_parms.stepsPerFrame * G.scene->r.frs_sec); result = CDDM_copy(dm); + + if(!result) + { + return dm; + } + + numverts = result->getNumVerts(result); + numedges = result->getNumEdges(result); + numfaces = result->getNumFaces(result); + mvert = CDDM_get_verts(result); + medge = CDDM_get_edges(result); + mface = CDDM_get_faces(result); + + clmd->sim_parms.sim_time = current_time; // only be active during a specific period: // that's "first frame" and "last frame" on GUI + /* if ( clmd->clothObject ) { if ( clmd->sim_parms.cache ) @@ -637,7 +686,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d cloth_cache_get_frame ( clmd, frametime ); cloth_to_object ( ob, result, clmd ); } - return; + return result; } else if ( current_time > clmd->sim_parms.lastframe ) { @@ -647,7 +696,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d cloth_cache_get_frame ( clmd, frametime ); cloth_to_object ( ob, result, clmd ); } - return; + return result; } else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed { @@ -657,23 +706,11 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d cloth_to_object ( ob, result, clmd ); } clmd->sim_parms.sim_time = current_time; - return; + return result; } } - - if(!result) - { - return dm; } - - numverts = result->getNumVerts(result); - numedges = result->getNumEdges(result); - numfaces = result->getNumFaces(result); - mvert = CDDM_get_verts(result); - medge = CDDM_get_edges(result); - mface = CDDM_get_faces(result); - - clmd->sim_parms.sim_time = current_time; + */ if(deltaTime == 1.0f) { @@ -695,28 +732,29 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d { if(!cloth_cache_search_frame(clmd, framenr)) { + verts = cloth->verts; + // Force any pinned verts to their constrained location. for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) { // Save the previous position. - VECCOPY ( verts->xold, verts->xconst ); - VECCOPY ( verts->txold, verts->x ); + VECCOPY ( cloth->xold[i], verts->xconst ); + VECCOPY ( cloth->current_xold[i], cloth->x[i] ); // Get the current position. - VECCOPY ( verts->xconst, mverts[i].co ); + VECCOPY ( verts->xconst, mvert[i].co ); Mat4MulVecfl ( ob->obmat, verts->xconst ); } - + tstart(); - + /* Call the solver. */ - if (solvers [clmd->sim_parms.solver_type].solver) solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors); - + tend(); - - // printf("Cloth simulation time: %f\n", (float)tval()); - + + printf("Cloth simulation time: %f\n", tval()); + cloth_cache_set_frame(clmd, framenr); } @@ -785,8 +823,16 @@ void cloth_free_modifier (ClothModifierData *clmd) MEM_freeN ( cloth->x ); // Free the verts. - if ( cloth->xnew != NULL ) - MEM_freeN ( cloth->xnew ); + if ( cloth->xold != NULL ) + MEM_freeN ( cloth->xold ); + + // Free the verts. + if ( cloth->current_x != NULL ) + MEM_freeN ( cloth->current_x ); + + // Free the verts. + if ( cloth->current_xold != NULL ) + MEM_freeN ( cloth->current_xold ); cloth->verts = NULL; cloth->numverts = -1; @@ -834,23 +880,21 @@ void cloth_free_modifier (ClothModifierData *clmd) **/ static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd) { - ClothVertex *verts = NULL; unsigned int i = 0; MVert *mvert = NULL; unsigned int numverts; + Cloth *cloth = clmd->clothObject; if (clmd->clothObject) { - verts = clmd->clothObject->verts; - /* inverse matrix is not uptodate... */ Mat4Invert (ob->imat, ob->obmat); mvert = CDDM_get_verts(dm); numverts = dm->getNumVerts(dm); - for (i = 0; i < numverts; i++, verts++) + for (i = 0; i < numverts; i++) { - VECCOPY (mvert[i].co, verts->x); + VECCOPY (mvert[i].co, cloth->x[i]); Mat4MulVecfl (ob->imat, mvert[i].co); /* softbody is in global coords */ } } @@ -921,6 +965,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d unsigned int i; unsigned int numverts = dm->getNumVerts(dm); MVert *mvert = CDDM_get_verts(dm); + float tnull[3] = {0,0,0}; /* If we have a clothObject, free it. */ if (clmd->clothObject != NULL) @@ -963,8 +1008,8 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d /* set initial values */ for (i = 0; i < numverts; ++i) { - VECCOPY (clmd->clothObject->verts [i].x, mvert[i].co); - Mat4MulVecfl(ob->obmat, clmd->clothObject->verts [i].x); + VECCOPY (clmd->clothObject->x[i], mvert[i].co); + Mat4MulVecfl(ob->obmat, clmd->clothObject->x[i]); clmd->clothObject->verts [i].mass = clmd->sim_parms.mass; if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) @@ -972,9 +1017,9 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d else clmd->clothObject->verts [i].goal= 0.0f; clmd->clothObject->verts [i].flags = 0; - VECCOPY(clmd->clothObject->verts [i].xold, clmd->clothObject->verts [i].x); - VECCOPY(clmd->clothObject->verts [i].xconst, clmd->clothObject->verts [i].x); - VECCOPY(clmd->clothObject->verts [i].txold, clmd->clothObject->verts [i].x); + VECCOPY(clmd->clothObject->xold[i], clmd->clothObject->x[i]); + VECCOPY(clmd->clothObject->verts [i].xconst, clmd->clothObject->x[i]); + VECCOPY(clmd->clothObject->current_xold[i], clmd->clothObject->x[i]); VecMulf(clmd->clothObject->verts [i].v, 0.0f); clmd->clothObject->verts [i].impulse_count = 0; @@ -991,7 +1036,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject->tree = NULL; // bvh_build(clmd, clmd->coll_parms.epsilon); - cloth_cache_set_frame(clmd, 1); + // cloth_cache_set_frame(clmd, 1); } return 1; @@ -1006,7 +1051,6 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d unsigned int numverts = dm->getNumVerts(dm); unsigned int numfaces = dm->getNumFaces(dm); MFace *mface = CDDM_get_faces(dm); - unsigned int i = 0; /* Allocate our vertices. */ @@ -1019,7 +1063,7 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - clmd->clothObject->x = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_x" ); + clmd->clothObject->x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_x" ); if ( clmd->clothObject->x == NULL ) { cloth_free_modifier ( clmd ); @@ -1027,11 +1071,27 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - clmd->clothObject->xnew = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_xnew" ); - if ( clmd->clothObject->xnew == NULL ) + clmd->clothObject->xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_xold" ); + if ( clmd->clothObject->xold == NULL ) { cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xnew." ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xold." ); + return; + } + + clmd->clothObject->current_x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_current_x" ); + if ( clmd->clothObject->current_x == NULL ) + { + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_x." ); + return; + } + + clmd->clothObject->current_xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_current_xold" ); + if ( clmd->clothObject->current_xold == NULL ) + { + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_xold." ); return; } @@ -1101,7 +1161,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) EdgeHash *edgehash = NULL; LinkNode *search = NULL, *search2 = NULL; float temp[3]; - + LinkNode *node = NULL, *node2 = NULL; + // error handling if ( numedges==0 ) return 0; @@ -1134,8 +1195,12 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; spring->flags = 0; struct_springs++; - - BLI_linklist_append ( &cloth->springs, spring ); + + if(!i) + node2 = BLI_linklist_append_fast ( &cloth->springs, spring ); + else + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; } } @@ -1154,7 +1219,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) BLI_linklist_append ( &edgelist[spring->kl], spring ); shear_springs++; - BLI_linklist_append ( &cloth->springs, spring ); + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; if ( mface[i].v4 ) { @@ -1170,7 +1236,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) BLI_linklist_append ( &edgelist[spring->kl], spring ); shear_springs++; - BLI_linklist_append ( &cloth->springs, spring ); + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; } } @@ -1204,7 +1271,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) BLI_edgehash_insert ( edgehash, spring->ij, index2, NULL ); bend_springs++; - BLI_linklist_append ( &cloth->springs, spring ); + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; } search = search->next; } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index f61e2d22f1c..e28930fa052 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -770,7 +770,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) for(i = 0; i < cloth->numverts; i++) { - VECCOPY(id->X[i], verts[i].x); + VECCOPY(id->X[i], cloth->x[i]); } return 1; @@ -1165,7 +1165,6 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float damping_force[3] = {0,0,0}; float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; Cloth *cloth = clmd->clothObject; - ClothVertex *verts = cloth->verts; VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); @@ -1336,16 +1335,16 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec if(verts [i].goal < SOFTGOALSNAP) { // current_position = xold + t * (newposition - xold) - VECSUB(tvect, verts[i].xconst, verts[i].xold); + VECSUB(tvect, verts[i].xconst, cloth->xold[i]); mul_fvector_S(tvect, tvect, time); - VECADD(tvect, tvect, verts[i].xold); + VECADD(tvect, tvect, cloth->xold[i]); VECSUB(auxvect, tvect, lX[i]); ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms.goalspring)-1.0f ; VECADDS(lF[i], lF[i], auxvect, -ks); // calulate damping forces generated by goals - VECSUB(velgoal,verts[i].xold, verts[i].xconst); + VECSUB(velgoal, cloth->xold[i], verts[i].xconst); kd = clmd->sim_parms.goalfrict * 0.01f; // friction force scale taken from SB VECSUBADDSS(lF[i], velgoal, kd, lV[i], kd); @@ -1433,7 +1432,7 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) { - unsigned int i=0, j; + unsigned int i=0; float step=0.0f, tf=1.0f; Cloth *cloth = clmd->clothObject; ClothVertex *verts = cloth->verts; @@ -1449,7 +1448,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // update velocities with constrained velocities from pinned verts if(verts [i].goal >= SOFTGOALSNAP) { - VECSUB(id->V[i], verts[i].xconst, verts[i].xold); + VECSUB(id->V[i], verts[i].xconst, cloth->xold[i]); // VecMulf(id->V[i], 1.0 / dt); } } @@ -1480,15 +1479,15 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase float tvect[3] = {.0,.0,.0}; // VECSUB(tvect, id->Xnew[i], verts[i].xold); mul_fvector_S(tvect, id->V[i], step+dt); - VECADD(tvect, tvect, verts[i].xold); + VECADD(tvect, tvect, cloth->xold[i]); VECCOPY(id->Xnew[i], tvect); } } - VECCOPY(verts[i].tx, id->Xnew[i]); + VECCOPY(cloth->current_x[i], id->Xnew[i]); - VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + VECSUB(verts[i].tv, cloth->current_x[i], cloth->current_xold[i]); VECCOPY(verts[i].v, verts[i].tv); } @@ -1502,16 +1501,16 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase { // VECADD(verts[i].tx, verts[i].txold, verts[i].tv); - VECCOPY(verts[i].txold, verts[i].tx); + VECCOPY(cloth->current_xold[i], cloth->current_x[i]); - VECCOPY(id->Xnew[i], verts[i].tx); + VECCOPY(id->Xnew[i], cloth->current_x[i]); VECCOPY(id->Vnew[i], verts[i].tv); VecMulf(id->Vnew[i], 1.0f / dt); } else { - VECCOPY(verts[i].txold, id->Xnew[i]); + VECCOPY(cloth->current_xold[i], id->Xnew[i]); } } @@ -1552,21 +1551,21 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase { if(verts [i].goal < SOFTGOALSNAP) { - VECCOPY(verts[i].txold, id->X[i]); - VECCOPY(verts[i].x, id->X[i]); + VECCOPY(cloth->current_xold[i], id->X[i]); + VECCOPY(cloth->x[i], id->X[i]); VECCOPY(verts[i].v, id->V[i]); } else { - VECCOPY(verts[i].txold, verts[i].xconst); - VECCOPY(verts[i].x, verts[i].xconst); + VECCOPY(cloth->current_xold[i], verts[i].xconst); + VECCOPY(cloth->x[i], verts[i].xconst); VECCOPY(verts[i].v, id->V[i]); } } else { - VECCOPY(verts[i].txold, id->X[i]); - VECCOPY(verts[i].x, id->X[i]); + VECCOPY(cloth->current_xold[i], id->X[i]); + VECCOPY(cloth->x[i], id->X[i]); VECCOPY(verts[i].v, id->V[i]); } } @@ -1582,7 +1581,7 @@ void implicit_set_positions (ClothModifierData *clmd) for(i = 0; i < numverts; i++) { - VECCOPY(id->X[i], verts[i].x); + VECCOPY(id->X[i], cloth->x[i]); VECCOPY(id->V[i], verts[i].v); } } @@ -1841,7 +1840,7 @@ int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *co Cloth *cloth1, *cloth2; ClothVertex *verts1, *verts2; float temp[3]; - + /* cloth1 = clmd->clothObject; cloth2 = coll_clmd->clothObject; @@ -1863,7 +1862,7 @@ int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *co VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold); if(ABS(INPR(temp, temp)) < ALMOST_ZERO) return 1; - + */ return 0; } @@ -2109,7 +2108,7 @@ void collisions_update_collision_objects(float step) ClothModifierData *coll_clmd=NULL; Object *coll_ob=NULL; unsigned int i=0; - + /* // search all objects for collision object for (base = G.scene->base.first; base; base = base->next) { @@ -2146,6 +2145,7 @@ void collisions_update_collision_objects(float step) printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); } } + */ } diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index b4592e4d724..e1b1e3ce84a 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -45,10 +45,6 @@ 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 */ @@ -159,10 +155,10 @@ typedef struct Cloth struct CollisionTree *tree; /* collision tree for this cloth object */ struct MFace *mfaces; struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ - struct MVert *x; - struct MVert *xnew; - struct MVert *current_x; - struct MVert *current_xnew; + float (*x)[3]; /* The current position of all vertices.*/ + float (*xold)[3]; /* The previous position of all vertices.*/ + float (*current_x)[3]; /* The TEMPORARY current position of all vertices.*/ + float (*current_xold)[3]; /* The TEMPORARY previous position of all vertices.*/ } Cloth; From 4f72523654b0344e8398707edb228182a807d278 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 26 Oct 2007 15:13:50 +0000 Subject: [PATCH 039/101] Weekend commit: Enabled bounding box check for cloth again, but there's a bug in it (no collisions detected) --- source/blender/blenkernel/BKE_cloth.h | 5 + source/blender/blenkernel/BKE_collisions.h | 10 +- source/blender/blenkernel/intern/cloth.c | 65 +++- source/blender/blenkernel/intern/collision.c | 8 +- source/blender/blenkernel/intern/implicit.c | 350 ++++--------------- source/blender/blenkernel/intern/kdop.c | 89 ++++- source/blender/blenkernel/intern/modifier.c | 15 +- source/blender/makesdna/DNA_cloth_types.h | 6 +- 8 files changed, 240 insertions(+), 308 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 6b1110d6625..c0327ebe6db 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -124,6 +124,9 @@ void implicit_set_positions ( ClothModifierData *clmd ); // from cloth.c, needed for modifier.c DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc); +// needed in implicit.c +int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, float dt); + //////////////////////////////////////////////// @@ -175,6 +178,8 @@ typedef struct Frame float time; /* we need float since we want to support sub-frames */ float (*x)[3]; float (*xold)[3]; + float (*v)[3]; + float (*current_xold)[3]; } Frame; diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h index 0a79bb46262..6422ad65c0b 100644 --- a/source/blender/blenkernel/BKE_collisions.h +++ b/source/blender/blenkernel/BKE_collisions.h @@ -68,9 +68,9 @@ typedef struct BVH MVert *x; // position of verts at time n-1 MFace *mfaces; // just a pointer to the original datastructure struct LinkNode *tree; - TreeNode *root; // TODO: saving the root --> is this really needed? YES! - TreeNode *leaf_tree; /* Tail of the leaf linked list. */ - TreeNode *leaf_root; /* Head of the leaf linked list. */ + 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 */ } @@ -90,6 +90,7 @@ CollisionPair; // builds bounding volume hierarchy BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon); +BVH *bvh_build_from_float3 (MFace *mfaces, unsigned int numfaces, float (*x)[3], unsigned int numverts, float epsilon); // frees the same void bvh_free ( BVH *bvh ); @@ -99,12 +100,13 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision // 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_from_float3(BVH * bvh, float (*x)[3], unsigned int numverts, float (*xnew)[3], 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); +void collision_move_object(CollisionModifierData *collmd, float step, float prevstep); ///////////////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index c4c32d48b82..bb99709b73a 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -515,6 +515,10 @@ void cloth_cache_get_frame ( ClothModifierData *clmd, float time ) memcpy ( clmd->clothObject->xold, frame->xold, sizeof ( float ) *frame->numverts * 3); + memcpy ( clmd->clothObject->v, frame->v, sizeof ( float ) *frame->numverts * 3); + + memcpy ( clmd->clothObject->current_xold, frame->current_xold, sizeof ( float ) *frame->numverts * 3); + implicit_set_positions ( clmd ); return; @@ -565,6 +569,29 @@ void cloth_cache_set_frame ( ClothModifierData *clmd, float time ) return; } + frame->v = MEM_dupallocN ( clmd->clothObject->v ); + + if ( !frame->v ) + { + MEM_freeN ( frame->verts ); + MEM_freeN ( frame->x ); + MEM_freeN ( frame->xold ); + MEM_freeN ( frame ); + return; + } + + frame->current_xold= MEM_dupallocN ( clmd->clothObject->current_xold ); + + if ( !frame->current_xold ) + { + MEM_freeN ( frame->verts ); + MEM_freeN ( frame->x ); + MEM_freeN ( frame->xold ); + MEM_freeN ( frame->v ); + MEM_freeN ( frame ); + return; + } + BLI_linklist_append ( &clmd->sim_parms.cache, frame ); } @@ -606,6 +633,14 @@ void cloth_cache_free ( ClothModifierData *clmd, float time ) { MEM_freeN ( frame->xold ); } + if ( frame->v ) + { + MEM_freeN ( frame->v ); + } + if ( frame->current_xold ) + { + MEM_freeN ( frame->current_xold ); + } MEM_freeN ( frame ); lastsearch->next = search->next; @@ -825,6 +860,10 @@ void cloth_free_modifier (ClothModifierData *clmd) // Free the verts. if ( cloth->xold != NULL ) MEM_freeN ( cloth->xold ); + + // Free the verts. + if ( cloth->v != NULL ) + MEM_freeN ( cloth->v ); // Free the verts. if ( cloth->current_x != NULL ) @@ -833,6 +872,10 @@ void cloth_free_modifier (ClothModifierData *clmd) // Free the verts. if ( cloth->current_xold != NULL ) MEM_freeN ( cloth->current_xold ); + + // Free the verts. + if ( cloth->current_v != NULL ) + MEM_freeN ( cloth->current_v ); cloth->verts = NULL; cloth->numverts = -1; @@ -991,7 +1034,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if ( !dm ) return 0; - cloth_from_mesh (ob, clmd, dm, framenr); + cloth_from_mesh (ob, clmd, dm, framenr); if ( clmd->clothObject != NULL ) { @@ -1020,7 +1063,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d VECCOPY(clmd->clothObject->xold[i], clmd->clothObject->x[i]); VECCOPY(clmd->clothObject->verts [i].xconst, clmd->clothObject->x[i]); VECCOPY(clmd->clothObject->current_xold[i], clmd->clothObject->x[i]); - VecMulf(clmd->clothObject->verts [i].v, 0.0f); + VecMulf(clmd->clothObject->v[i], 0.0f); clmd->clothObject->verts [i].impulse_count = 0; VECCOPY ( clmd->clothObject->verts [i].impulse, tnull ); @@ -1034,7 +1077,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if (solvers [clmd->sim_parms.solver_type].init) solvers [clmd->sim_parms.solver_type].init (ob, clmd); - clmd->clothObject->tree = NULL; // bvh_build(clmd, clmd->coll_parms.epsilon); + clmd->clothObject->tree = bvh_build_from_float3(CDDM_get_faces(dm), dm->getNumFaces(dm), clmd->clothObject->x, numverts, clmd->coll_parms.epsilon); // cloth_cache_set_frame(clmd, 1); } @@ -1079,6 +1122,14 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } + clmd->clothObject->v = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_v" ); + if ( clmd->clothObject->v == NULL ) + { + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->v." ); + return; + } + clmd->clothObject->current_x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_current_x" ); if ( clmd->clothObject->current_x == NULL ) { @@ -1094,6 +1145,14 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_xold." ); return; } + + clmd->clothObject->current_v = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_current_v" ); + if ( clmd->clothObject->current_v == NULL ) + { + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_v." ); + return; + } // save face information clmd->clothObject->numfaces = numfaces; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index f4b0ce7312b..6f0ac5f8c6d 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -73,17 +73,15 @@ // step is limited from 0 (frame start position) to 1 (frame end position) -void collision_move_object(CollisionModifierData *collmd, float step) +void collision_move_object(CollisionModifierData *collmd, float step, float prevstep) { float tv[3] = {0,0,0}; unsigned int i = 0; - MVert *tempVert = collmd->current_x; - collmd->current_x = collmd->current_xnew; - collmd->current_xnew = tempVert; - + for ( i = 0; i < collmd->numverts; i++ ) { VECSUB(tv, collmd->xnew[i].co, collmd->x[i].co); + VECADDS(collmd->current_x[i].co, collmd->x[i].co, tv, prevstep); VECADDS(collmd->current_xnew[i].co, collmd->x[i].co, tv, step); } } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index e28930fa052..adefcc32d52 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1164,7 +1164,6 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float bending_force[3] = {0,0,0}; float damping_force[3] = {0,0,0}; float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; - Cloth *cloth = clmd->clothObject; VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); @@ -1486,32 +1485,28 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase } VECCOPY(cloth->current_x[i], id->Xnew[i]); - - VECSUB(verts[i].tv, cloth->current_x[i], cloth->current_xold[i]); - VECCOPY(verts[i].v, verts[i].tv); + VECSUB(cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i]); + VECCOPY(cloth->v[i], cloth->current_v[i]); } - + // call collision function - result = 0; // cloth_bvh_objcollision(clmd, step + dt, dt); - + result = cloth_bvh_objcollision(clmd, step + dt, step, dt); + // copy corrected positions back to simulation - for(i = 0; i < numverts; i++) - { - if(result) - { - // VECADD(verts[i].tx, verts[i].txold, verts[i].tv); - - VECCOPY(cloth->current_xold[i], cloth->current_x[i]); - - VECCOPY(id->Xnew[i], cloth->current_x[i]); - - VECCOPY(id->Vnew[i], verts[i].tv); + memcpy(cloth->current_xold, cloth->current_x, sizeof(lfVector) * numverts); + memcpy(id->Xnew, cloth->current_x, sizeof(lfVector) * numverts); + + if(result) + { + for(i = 0; i < numverts; i++) + { + VECCOPY(id->Vnew[i], cloth->current_v[i]); VecMulf(id->Vnew[i], 1.0f / dt); } - else - { - VECCOPY(cloth->current_xold[i], id->Xnew[i]); - } + } + else + { + memcpy(cloth->current_xold, id->Xnew, sizeof(lfVector) * numverts); } // X = Xnew; @@ -1544,46 +1539,42 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase if(effectors) pdEndEffectors(effectors); } - - for(i = 0; i < numverts; i++) - { - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + { + for(i = 0; i < numverts; i++) { if(verts [i].goal < SOFTGOALSNAP) { VECCOPY(cloth->current_xold[i], id->X[i]); VECCOPY(cloth->x[i], id->X[i]); - VECCOPY(verts[i].v, id->V[i]); } else { VECCOPY(cloth->current_xold[i], verts[i].xconst); VECCOPY(cloth->x[i], verts[i].xconst); - VECCOPY(verts[i].v, id->V[i]); } } - else - { - VECCOPY(cloth->current_xold[i], id->X[i]); - VECCOPY(cloth->x[i], id->X[i]); - VECCOPY(verts[i].v, id->V[i]); - } } + else + { + memcpy(cloth->current_xold, id->X, sizeof(lfVector) * numverts); + memcpy(cloth->x, id->X, sizeof(lfVector) * numverts); + } + + memcpy(cloth->v, id->V, sizeof(lfVector) * numverts); + return 1; } void implicit_set_positions (ClothModifierData *clmd) { Cloth *cloth = clmd->clothObject; - ClothVertex *verts = cloth->verts; - unsigned int numverts = cloth->numverts, i; + unsigned int numverts = cloth->numverts; Implicit_Data *id = cloth->implicit; - for(i = 0; i < numverts; i++) - { - VECCOPY(id->X[i], cloth->x[i]); - VECCOPY(id->V[i], verts[i].v); - } + memcpy(id->X, cloth->x, sizeof(lfVector) * numverts); + memcpy(id->V, cloth->v, sizeof(lfVector) * numverts); } @@ -1707,13 +1698,13 @@ int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierD int collisions_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) { - + return 0; } int collisions_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) { - + return 0; } void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) @@ -2161,266 +2152,75 @@ void collisions_collision_moving(ClothModifierData *clmd, ClothModifierData *col } // cloth - object collisions -int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) +int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, float dt) { - /* - Base *base=NULL; - ClothModifierData *coll_clmd=NULL; - Cloth *cloth=NULL; - Object *coll_ob=NULL; - BVH *collisions_bvh=NULL; - unsigned int i=0, j = 0, numfaces = 0, numverts = 0; - unsigned int result = 0, ic = 0, rounds = 0; // result counts applied collisions; ic is for debug output; - ClothVertex *verts = NULL; - float tnull[3] = {0,0,0}; - int ret = 0; + + Base *base = NULL; + CollisionModifierData *collmd = NULL; + Cloth *cloth = NULL; + Object *ob2 = NULL; + BVH *bvh1 = NULL, *bvh2 = NULL; LinkNode *collision_list = NULL; - if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) + if (!(((Cloth *)clmd->clothObject)->tree)) { + printf("No BVH found\n"); return 0; } + cloth = clmd->clothObject; - verts = cloth->verts; - collisions_bvh = (BVH *) cloth->tree; - numfaces = clmd->clothObject->numfaces; - numverts = clmd->clothObject->numverts; + bvh1 = cloth->tree; //////////////////////////////////////////////////////////// // static collisions //////////////////////////////////////////////////////////// // update cloth bvh - // bvh_update(clmd, collisions_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function) + bvh_update_from_float3(bvh1, cloth->current_xold, cloth->numverts, cloth->current_x, 0); // 0 means STATIC, 1 means MOVING (see later in this function) - // update collision objects - collisions_update_collision_objects(step); - - do - { - result = 0; - ic = 0; - - // check all collision objects - for (base = G.scene->base.first; base; base = base->next) - { - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - - if (!coll_clmd) - continue; - - // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) - { - if (coll_clmd->clothObject && coll_clmd->clothObject->tree) - { - BVH *coll_bvh = coll_clmd->clothObject->tree; - - // fill collision list - bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list); - - // process all collisions (calculate impulses, TODO: also repulses if distance too short) - result = 1; - for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence - { - result = 0; - - // result += collisions_collision_response_static_tris(clmd, coll_clmd, collision_list, 0); - - // result += collisions_collision_response_static_tris(coll_clmd, clmd, collision_list, 1); - - // apply impulses in parallel - ic=0; - for(i = 0; i < numverts; i++) - { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if(verts[i].impulse_count) - { - VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); - VECCOPY(verts[i].impulse, tnull); - verts[i].impulse_count = 0; - - ic++; - ret++; - } - } - } - - // free collision list - if(collision_list) - { - LinkNode *search = collision_list; - while(search) - { - CollisionPair *coll_pair = search->link; - - MEM_freeN(coll_pair); - search = search->next; - } - BLI_linklist_free(collision_list,NULL); - - collision_list = NULL; - } - } - else - printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } - } - - printf("ic: %d\n", ic); - rounds++; - } - while(result && (10>rounds));// CLOTH_MAX_THRESHOLD - - printf("\n"); - - //////////////////////////////////////////////////////////// - // update positions - // this is needed for bvh_calc_DOP_hull_moving() [kdop.c] - //////////////////////////////////////////////////////////// - - // verts come from clmd - for(i = 0; i < numverts; i++) - { - VECADD(verts[i].tx, verts[i].txold, verts[i].tv); - } - //////////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////////// - // moving collisions - //////////////////////////////////////////////////////////// - - - // update cloth bvh - // bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING - - // update moving bvh for collision object once + // check all collision objects for (base = G.scene->base.first; base; base = base->next) { + ob2 = base->object; + collmd = (CollisionModifierData *) modifiers_findByType (ob2, eModifierType_Collision); - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - if (!coll_clmd) + if (!collmd) continue; - if(!coll_clmd->clothObject) - continue; - - // if collision object go on - if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + // check if there is a bounding volume hierarchy + if (collmd->tree) { - BVH *coll_bvh = coll_clmd->clothObject->tree; + int collisions = 0; - // bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING - } - } - - - do - { - result = 0; - ic = 0; - - // check all collision objects - for (base = G.scene->base.first; base; base = base->next) - { - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + bvh2 = collmd->tree; - if (!coll_clmd) - continue; + // update position + bvh of collision object + collision_move_object(collmd, step, prevstep); + bvh_update_from_mvert(collmd->tree, collmd->current_x, collmd->numverts, NULL, 0); - // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + // fill collision list + collisions = bvh_traverse(bvh1->root, bvh2->root, collision_list); + + printf("Found %d collisions.\n", collisions); + + // free collision list + if(collision_list) { - if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + LinkNode *search = collision_list; + while(search) { - BVH *coll_bvh = coll_clmd->clothObject->tree; + CollisionPair *coll_pair = search->link; - bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list); - - // process all collisions (calculate impulses, TODO: also repulses if distance too short) - result = 1; - for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence - { - result = 0; - - // handle all collision objects - - - if (coll_clmd->clothObject) - result += collisions_collision_response_moving_tris(clmd, coll_clmd); - else - printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - - - // apply impulses in parallel - ic=0; - for(i = 0; i < numverts; i++) - { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if(verts[i].impulse_count) - { - VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); - VECCOPY(verts[i].impulse, tnull); - verts[i].impulse_count = 0; - - ic++; - ret++; - } - } - } - - - // verts come from clmd - for(i = 0; i < numverts; i++) - { - VECADD(verts[i].tx, verts[i].txold, verts[i].tv); - } - - // update cloth bvh - // bvh_update(clmd, collisions_bvh, 1); // 0 means STATIC, 1 means MOVING - - - // free collision list - if(collision_list) - { - LinkNode *search = collision_list; - while(search) - { - CollisionPair *coll_pair = search->link; - - MEM_freeN(coll_pair); - search = search->next; - } - BLI_linklist_free(collision_list,NULL); - - collision_list = NULL; - } + MEM_freeN(coll_pair); + search = search->next; } - else - printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + BLI_linklist_free(collision_list,NULL); + + collision_list = NULL; } } - - printf("ic: %d\n", ic); - rounds++; } - while(result && (10>rounds)); // CLOTH_MAX_THRESHOLD - - - //////////////////////////////////////////////////////////// - // update positions + velocities - //////////////////////////////////////////////////////////// - - // verts come from clmd - for(i = 0; i < numverts; i++) - { - VECADD(verts[i].tx, verts[i].txold, verts[i].tv); - } - //////////////////////////////////////////////////////////// - return MIN2(ret, 1); - */ -} \ No newline at end of file + + return 0; +} diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 32bab0b4935..22129fcbc43 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -656,12 +656,8 @@ BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces) BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon) { - unsigned int i = 0, j = 0; - CollisionTree **face_list=NULL; - BVH *bvh=NULL; + BVH *bvh=NULL; CollisionTree *tree=NULL; - LinkNode *nlink = NULL; - MFace *mface = NULL; bvh = MEM_callocN(sizeof(BVH), "BVH"); if (bvh == NULL) @@ -701,6 +697,55 @@ BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsig return bvh_build(bvh, mfaces, numfaces); } + +BVH *bvh_build_from_float3 (MFace *mfaces, unsigned int numfaces, float (*x)[3], unsigned int numverts, float epsilon) +{ + BVH *bvh=NULL; + CollisionTree *tree=NULL; + unsigned int i = 0; + + bvh = MEM_callocN(sizeof(BVH), "BVH"); + if (bvh == NULL) + { + printf("bvh: Out of memory.\n"); + return NULL; + } + + bvh->flags = 0; + bvh->leaf_tree = NULL; + bvh->leaf_root = NULL; + bvh->tree = NULL; + + bvh->epsilon = epsilon; + bvh->numfaces = numfaces; + + // we have no faces, we save seperate points + if(!mfaces) + { + bvh->numfaces = numverts; + } + + bvh->numverts = numverts; + bvh->xnew = (MVert *)MEM_callocN(sizeof(MVert)*numverts, "BVH MVert"); + + for(i = 0; i < numverts; i++) + VECCOPY(bvh->xnew[i].co, x[i]); + + bvh->x = MEM_dupallocN(bvh->xnew); + tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree"); + + if (tree == NULL) + { + printf("bvh_build: Out of memory for nodes.\n"); + bvh_free(bvh); + return NULL; + } + + BLI_linklist_append(&bvh->tree, tree); + + return bvh_build(bvh, mfaces, numfaces); +} + // bvh_overlap - is it possbile for 2 bv's to collide ? int bvh_overlap(float *bv1, float *bv2) { @@ -730,7 +775,7 @@ int bvh_overlap(float *bv1, float *bv2) */ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision_list) { - int i = 0, ret = 0; + int i = 0, ret = 0, tempret = 0; if (bvh_overlap(tree1->bv, tree2->bv)) { @@ -759,8 +804,8 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree2->nodes[i] && bvh_traverse (tree1, tree2->nodes[i], collision_list)) - ret = 1; + if (tree2->nodes[i] && (tempret = bvh_traverse (tree1, tree2->nodes[i], collision_list))) + ret += tempret; } } } @@ -770,8 +815,8 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree1->nodes [i] && bvh_traverse (tree1->nodes[i], tree2, collision_list)) - ret = 1; + if (tree1->nodes [i] && (tempret = bvh_traverse (tree1->nodes[i], tree2, collision_list))) + ret += tempret; } } } @@ -882,3 +927,27 @@ void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xn bvh_update(bvh, moving); } +void bvh_update_from_float3(BVH * bvh, float (*x)[3], unsigned int numverts, float (*xnew)[3], int moving) +{ + unsigned int i = 0; + + if(!bvh) + return; + + if(numverts!=bvh->numverts) + return; + + if(x) + { + for(i = 0; i < numverts; i++) + VECCOPY(bvh->x[i].co, x[i]); + } + + if(xnew) + { + for(i = 0; i < numverts; i++) + VECCOPY(bvh->xnew[i].co, xnew[i]); + } + + bvh_update(bvh, moving); +} diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index fcb56b56a5a..245b2fdc9b2 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4922,14 +4922,13 @@ static void clothModifier_updateDepgraph( Object *ob1= base->object; if(ob1 != ob) { - ClothModifierData *coll_clmd = (ClothModifierData *)modifiers_findByType(ob1, eModifierType_Cloth); - if(coll_clmd) - { - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) - { - DagNode *curNode = dag_get_node(forest, ob1); - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA); - } + CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision); + if(collmd) + { + DagNode *curNode = dag_get_node(forest, ob1); + + dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA); + } } } diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index e1b1e3ce84a..2db2de7e183 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -43,9 +43,7 @@ typedef struct ClothVertex { int flags; /* General flags per vertex. */ - float v [3]; /* The velocity of the point. */ float xconst [3]; /* constrained 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 */ @@ -152,13 +150,15 @@ typedef struct Cloth unsigned char old_solver_type; unsigned char pad2; short pad3; - struct CollisionTree *tree; /* collision tree for this cloth object */ + struct BVH *tree; /* collision tree for this cloth object */ struct MFace *mfaces; struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ float (*x)[3]; /* The current position of all vertices.*/ float (*xold)[3]; /* The previous position of all vertices.*/ float (*current_x)[3]; /* The TEMPORARY current position of all vertices.*/ float (*current_xold)[3]; /* The TEMPORARY previous position of all vertices.*/ + float (*v)[3]; /* the current velocity of all vertices */ + float (*current_v)[3]; } Cloth; From 67f8ca0b66f1138636978df34664d7c5aaa9ff4b Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 28 Oct 2007 19:07:51 +0000 Subject: [PATCH 040/101] Fixed typo which resulted in jumping cloth when collisions where enabled, fixed collision list memory leak. Ready to put real collision detection/response in. --- source/blender/blenkernel/BKE_cloth.h | 3 +- source/blender/blenkernel/BKE_collisions.h | 2 +- source/blender/blenkernel/intern/implicit.c | 59 +++++++++++++-------- source/blender/blenkernel/intern/kdop.c | 33 +++++++----- 4 files changed, 61 insertions(+), 36 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index c0327ebe6db..dfb706c6d9a 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -46,9 +46,10 @@ struct MFace; struct DerivedMesh; // this is needed for inlining behaviour + #ifndef _WIN32 #define LINUX -#define DO_INLINE inline +#define DO_INLINE #else #define DO_INLINE #endif diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h index 6422ad65c0b..4271bc4fef3 100644 --- a/source/blender/blenkernel/BKE_collisions.h +++ b/source/blender/blenkernel/BKE_collisions.h @@ -96,7 +96,7 @@ BVH *bvh_build_from_float3 (MFace *mfaces, unsigned int numfaces, float (*x)[3], void bvh_free ( BVH *bvh ); // checks two bounding volume hierarchies for potential collisions and returns some list with those -int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision_list); +int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collision_list); // update bounding volumes, needs updated positions in bvh->x void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index adefcc32d52..34cba02522d 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -581,21 +581,32 @@ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (* /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */ // TODO: pragma below is wrong, correct it! - // #pragma omp parallel for shared(to,from, fLongVector) private(i) +#pragma omp parallel for shared(to,from, fLongVector) private(i) for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) { + unsigned int row = from[i].r; + unsigned int column = from[i].c; + // muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); - to[from[i].c][0] += INPR(from[i].m[0],fLongVector[from[i].r]); - to[from[i].c][1] += INPR(from[i].m[1],fLongVector[from[i].r]); - to[from[i].c][2] += INPR(from[i].m[2],fLongVector[from[i].r]); + to[column][0] += INPR(from[i].m[0],fLongVector[row]); + to[column][1] += INPR(from[i].m[1],fLongVector[row]); + to[column][2] += INPR(from[i].m[2],fLongVector[row]); + } +#pragma omp parallel for shared(to,from, fLongVector) private(i) + for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) + { + unsigned int row = from[i].r; + unsigned int column = from[i].c; // muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); - to[from[i].r][0] += INPR(from[i].m[0],fLongVector[from[i].c]); - to[from[i].r][1] += INPR(from[i].m[1],fLongVector[from[i].c]); - to[from[i].r][2] += INPR(from[i].m[2],fLongVector[from[i].c]); + to[row][0] += INPR(from[i].m[0],fLongVector[column]); + to[row][1] += INPR(from[i].m[1],fLongVector[column]); + to[row][2] += INPR(from[i].m[2],fLongVector[column]); } + + } /* SPARSE SYMMETRIC add big matrix with big matrix: A = B + C*/ DO_INLINE void add_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) @@ -1313,7 +1324,6 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec float kd, ks; LinkNode *search = cloth->springs; - VECCOPY(gravity, clmd->sim_parms.gravity); mul_fvector_S(gravity, gravity, 0.001f); /* scale gravity force */ @@ -1406,7 +1416,7 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto initdiag_bfmatrix(A, I); zero_lfvector(dV, numverts); - subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); + subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); mul_bfmatrix_lfvector(dFdXmV, dFdX, lV); @@ -1492,12 +1502,12 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // call collision function result = cloth_bvh_objcollision(clmd, step + dt, step, dt); - // copy corrected positions back to simulation - memcpy(cloth->current_xold, cloth->current_x, sizeof(lfVector) * numverts); - memcpy(id->Xnew, cloth->current_x, sizeof(lfVector) * numverts); - + // copy corrected positions back to simulation if(result) { + memcpy(cloth->current_xold, cloth->current_x, sizeof(lfVector) * numverts); + memcpy(id->Xnew, cloth->current_x, sizeof(lfVector) * numverts); + for(i = 0; i < numverts; i++) { VECCOPY(id->Vnew[i], cloth->current_v[i]); @@ -2161,6 +2171,8 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, Object *ob2 = NULL; BVH *bvh1 = NULL, *bvh2 = NULL; LinkNode *collision_list = NULL; + unsigned int i = 0; + int collisions = 0; if (!(((Cloth *)clmd->clothObject)->tree)) { @@ -2189,9 +2201,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, // check if there is a bounding volume hierarchy if (collmd->tree) - { - int collisions = 0; - + { bvh2 = collmd->tree; // update position + bvh of collision object @@ -2199,14 +2209,13 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, bvh_update_from_mvert(collmd->tree, collmd->current_x, collmd->numverts, NULL, 0); // fill collision list - collisions = bvh_traverse(bvh1->root, bvh2->root, collision_list); - - printf("Found %d collisions.\n", collisions); + collisions += bvh_traverse(bvh1->root, bvh2->root, &collision_list); // free collision list if(collision_list) { LinkNode *search = collision_list; + while(search) { CollisionPair *coll_pair = search->link; @@ -2220,7 +2229,15 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, } } } - - return 0; + ////////////////////////////////////////////// + // update velocities + positions + ////////////////////////////////////////////// + for(i = 0; i < cloth->numverts; i++) + { + VECADD(cloth->current_x[i], cloth->current_xold[i], cloth->current_v[i]); + } + ////////////////////////////////////////////// + + return collisions; } diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 22129fcbc43..f9049fbcfcb 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -414,7 +414,7 @@ void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, floa tempBV[(2 * i)] = newminmax; if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0)) tempBV[(2 * i) + 1] = newminmax; - } + } } } } @@ -593,20 +593,20 @@ BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces) if(bvh->mfaces) { - bvh->root->point_index[0] = mfaces[i].v1; - bvh->root->point_index[1] = mfaces[i].v2; - bvh->root->point_index[2] = mfaces[i].v3; + tree->point_index[0] = mfaces[i].v1; + tree->point_index[1] = mfaces[i].v2; + tree->point_index[2] = mfaces[i].v3; if(mfaces[i].v4) - bvh->root->point_index[3] = mfaces[i].v4; + tree->point_index[3] = mfaces[i].v4; else - bvh->root->point_index[3] = -1; + tree->point_index[3] = -1; } else { - bvh->root->point_index[0] = i; - bvh->root->point_index[1] = -1; - bvh->root->point_index[2] = -1; - bvh->root->point_index[3] = -1; + tree->point_index[0] = i; + tree->point_index[1] = -1; + tree->point_index[2] = -1; + tree->point_index[3] = -1; } tree->isleaf = 1; @@ -641,7 +641,7 @@ BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces) // 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) @@ -673,6 +673,7 @@ BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsig bvh->epsilon = epsilon; bvh->numfaces = numfaces; + bvh->mfaces = mfaces; // we have no faces, we save seperate points if(!mfaces) @@ -718,6 +719,7 @@ BVH *bvh_build_from_float3 (MFace *mfaces, unsigned int numfaces, float (*x)[3], bvh->epsilon = epsilon; bvh->numfaces = numfaces; + bvh->mfaces = mfaces; // we have no faces, we save seperate points if(!mfaces) @@ -729,9 +731,12 @@ BVH *bvh_build_from_float3 (MFace *mfaces, unsigned int numfaces, float (*x)[3], bvh->xnew = (MVert *)MEM_callocN(sizeof(MVert)*numverts, "BVH MVert"); for(i = 0; i < numverts; i++) + { VECCOPY(bvh->xnew[i].co, x[i]); + } bvh->x = MEM_dupallocN(bvh->xnew); + tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree"); if (tree == NULL) @@ -773,7 +778,7 @@ int bvh_overlap(float *bv1, float *bv2) * every other triangle that doesn't require any realloc, but uses * much memory */ -int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision_list) +int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collision_list) { int i = 0, ret = 0, tempret = 0; @@ -786,6 +791,7 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision if (tree2->isleaf) { // save potential colliding triangles + CollisionPair *collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); VECCOPY(collpair->point_indexA, tree1->point_index); @@ -794,7 +800,7 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision VECCOPY(collpair->point_indexB, tree2->point_index); collpair->point_indexB[3] = tree2->point_index[3]; - BLI_linklist_append(&collision_list, collpair); + BLI_linklist_append(&collision_list[0], collpair); return 1; } @@ -870,6 +876,7 @@ void bvh_update(BVH * bvh, int moving) { leaf->parent->traversed = 0; } + if(!moving) bvh_calc_DOP_hull_static(bvh, &leaf, 1, leaf->bv); else From 01d19261bb315b841390a98cfe48b67e9991ed53 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 4 Nov 2007 21:02:37 +0000 Subject: [PATCH 041/101] Implemented simple selfcollisions with use of OpenMP (WITH_BF_OPENMP = 'true' - for NEW compilers like gcc 4.2.0 and MSVC prof) --- source/blender/blenkernel/BKE_cloth.h | 1 + source/blender/blenkernel/BKE_collisions.h | 2 + source/blender/blenkernel/intern/cloth.c | 58 ++++++++----- source/blender/blenkernel/intern/implicit.c | 96 +++++++++++++++++++-- source/blender/blenkernel/intern/kdop.c | 41 +++++---- source/blender/makesdna/DNA_cloth_types.h | 4 +- source/blender/src/buttons_object.c | 7 +- 7 files changed, 158 insertions(+), 51 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 1744b3f3393..42ea6db0430 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -149,6 +149,7 @@ typedef void ( *CM_COLLISION_SELF ) ( ClothModifierData *clmd, int step ); // only one available in the moment typedef enum { CM_IMPLICIT = 0, + CM_VERLET = 1, } CM_SOLVER_ID; diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h index 4271bc4fef3..fa5956c5bec 100644 --- a/source/blender/blenkernel/BKE_collisions.h +++ b/source/blender/blenkernel/BKE_collisions.h @@ -88,6 +88,8 @@ CollisionPair; // forward declarations ///////////////////////////////////////////////// +// NOTICE: mvert-routines for building + update the BVH are the most native ones + // builds bounding volume hierarchy BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon); BVH *bvh_build_from_float3 (MFace *mfaces, unsigned int numfaces, float (*x)[3], unsigned int numverts, float epsilon); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index bb99709b73a..cc5c6a289cd 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -111,11 +111,11 @@ double tval() /* Our available solvers. */ // 255 is the magic reserved number, so NEVER try to put 255 solvers in here! // 254 = MAX! -static CM_SOLVER_DEF solvers [] = - { - { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free }, - // { "Implicit C++", CM_IMPLICITCPP, implicitcpp_init, implicitcpp_solver, implicitcpp_free }, - }; +static CM_SOLVER_DEF solvers [] = +{ + { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free }, + // { "Implicit", CM_VERLET, verlet_init, verlet_solver, verlet_free }, +}; /* ********** cloth engine ******* */ /* Prototypes for internal functions. @@ -158,7 +158,8 @@ void cloth_init (ClothModifierData *clmd) clmd->coll_parms.self_friction = 5.0; clmd->coll_parms.friction = 10.0; clmd->coll_parms.loop_count = 1; - clmd->coll_parms.epsilon = 0.01f; + clmd->coll_parms.epsilon = 0.01; + clmd->coll_parms.selfepsilon = 0.1; /* These defaults are copied from softbody.c's * softbody_calc_forces() function. @@ -167,11 +168,11 @@ void cloth_init (ClothModifierData *clmd) clmd->sim_parms.eff_wind_scale = 250.0; // also from softbodies - clmd->sim_parms.maxgoal = 1.0f; - clmd->sim_parms.mingoal = 0.0f; - clmd->sim_parms.defgoal = 0.7f; - clmd->sim_parms.goalspring = 100.0f; - clmd->sim_parms.goalfrict = 0.0f; + clmd->sim_parms.maxgoal = 1.0; + clmd->sim_parms.mingoal = 0.0; + clmd->sim_parms.defgoal = 0.7; + clmd->sim_parms.goalspring = 100.0; + clmd->sim_parms.goalfrict = 0.0; clmd->sim_parms.cache = NULL; } @@ -519,6 +520,7 @@ void cloth_cache_get_frame ( ClothModifierData *clmd, float time ) memcpy ( clmd->clothObject->current_xold, frame->current_xold, sizeof ( float ) *frame->numverts * 3); + // TODO: temp off implicit_set_positions ( clmd ); return; @@ -621,32 +623,37 @@ void cloth_cache_free ( ClothModifierData *clmd, float time ) if ( frame->time >= newtime ) { + if ( frame->verts ) { MEM_freeN ( frame->verts ); } + if ( frame->x ) { MEM_freeN ( frame->x ); } + if ( frame->xold ) { MEM_freeN ( frame->xold ); } + if ( frame->v ) { MEM_freeN ( frame->v ); } + if ( frame->current_xold ) { MEM_freeN ( frame->current_xold ); } + MEM_freeN ( frame ); lastsearch->next = search->next; MEM_freeN ( search ); search = lastsearch->next; - lastsearch->next = NULL; } else { @@ -657,6 +664,7 @@ void cloth_cache_free ( ClothModifierData *clmd, float time ) if ( time <= 1.0 ) { + BLI_linklist_free(clmd->sim_parms.cache, NULL); clmd->sim_parms.cache = NULL; } @@ -852,7 +860,7 @@ void cloth_free_modifier (ClothModifierData *clmd) // Free the faces. if ( cloth->mfaces != NULL ) MEM_freeN ( cloth->mfaces ); - + // Free the verts. if ( cloth->x != NULL ) MEM_freeN ( cloth->x ); @@ -860,7 +868,7 @@ void cloth_free_modifier (ClothModifierData *clmd) // Free the verts. if ( cloth->xold != NULL ) MEM_freeN ( cloth->xold ); - + // Free the verts. if ( cloth->v != NULL ) MEM_freeN ( cloth->v ); @@ -876,7 +884,7 @@ void cloth_free_modifier (ClothModifierData *clmd) // Free the verts. if ( cloth->current_v != NULL ) MEM_freeN ( cloth->current_v ); - + cloth->verts = NULL; cloth->numverts = -1; @@ -902,6 +910,13 @@ void cloth_free_modifier (ClothModifierData *clmd) if(cloth->tree) bvh_free((BVH *)cloth->tree); + // free BVH self collision tree + if(cloth->selftree) + bvh_free((BVH *)cloth->selftree); + + if(cloth->edgehash) + BLI_edgehash_free ( cloth->edgehash, NULL ); + MEM_freeN (cloth); clmd->clothObject = NULL; } @@ -1019,6 +1034,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if (clmd->clothObject) { clmd->clothObject->old_solver_type = 255; + clmd->clothObject->edgehash = NULL; } else if (clmd->clothObject == NULL) { @@ -1058,12 +1074,12 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) clmd->clothObject->verts [i].goal= clmd->sim_parms.defgoal; else - clmd->clothObject->verts [i].goal= 0.0f; + clmd->clothObject->verts [i].goal= 0.0; clmd->clothObject->verts [i].flags = 0; VECCOPY(clmd->clothObject->xold[i], clmd->clothObject->x[i]); VECCOPY(clmd->clothObject->verts [i].xconst, clmd->clothObject->x[i]); VECCOPY(clmd->clothObject->current_xold[i], clmd->clothObject->x[i]); - VecMulf(clmd->clothObject->v[i], 0.0f); + VecMulf(clmd->clothObject->v[i], 0.0); clmd->clothObject->verts [i].impulse_count = 0; VECCOPY ( clmd->clothObject->verts [i].impulse, tnull ); @@ -1078,7 +1094,9 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d solvers [clmd->sim_parms.solver_type].init (ob, clmd); clmd->clothObject->tree = bvh_build_from_float3(CDDM_get_faces(dm), dm->getNumFaces(dm), clmd->clothObject->x, numverts, clmd->coll_parms.epsilon); - + + clmd->clothObject->selftree = bvh_build_from_float3(NULL, 0, clmd->clothObject->x, numverts, clmd->coll_parms.selfepsilon); + // cloth_cache_set_frame(clmd, 1); } @@ -1346,8 +1364,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) } if ( edgelist ) MEM_freeN ( edgelist ); - - BLI_edgehash_free ( edgehash, NULL ); + + cloth->edgehash = edgehash; return 1; diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 34cba02522d..a5777b991eb 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -46,8 +46,9 @@ #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_blenlib.h" +#include "BLI_edgehash.h" #include "BLI_threads.h" #include "BKE_collisions.h" #include "BKE_curve.h" @@ -62,7 +63,6 @@ #include "BKE_global.h" #include "BIF_editdeform.h" - #ifdef _WIN32 #include static LARGE_INTEGER _itstart, _itend; @@ -581,7 +581,7 @@ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (* /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */ // TODO: pragma below is wrong, correct it! -#pragma omp parallel for shared(to,from, fLongVector) private(i) +// #pragma omp parallel for shared(to,from, fLongVector) private(i) for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) { unsigned int row = from[i].r; @@ -593,7 +593,7 @@ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (* to[column][1] += INPR(from[i].m[1],fLongVector[row]); to[column][2] += INPR(from[i].m[2],fLongVector[row]); } -#pragma omp parallel for shared(to,from, fLongVector) private(i) +// #pragma omp parallel for shared(to,from, fLongVector) private(i) for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) { unsigned int row = from[i].r; @@ -1505,6 +1505,8 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // copy corrected positions back to simulation if(result) { + printf("result: %d\n", result); + memcpy(cloth->current_xold, cloth->current_x, sizeof(lfVector) * numverts); memcpy(id->Xnew, cloth->current_x, sizeof(lfVector) * numverts); @@ -1532,6 +1534,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); } + } else { @@ -1544,7 +1547,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // V = Vnew; cp_lfvector(id->V, id->Vnew, numverts); - + step += dt; if(effectors) pdEndEffectors(effectors); @@ -2171,8 +2174,9 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, Object *ob2 = NULL; BVH *bvh1 = NULL, *bvh2 = NULL; LinkNode *collision_list = NULL; - unsigned int i = 0; - int collisions = 0; + unsigned int i = 0, j = 0; + int collisions = 0, count = 0; + float (*current_x)[3]; if (!(((Cloth *)clmd->clothObject)->tree)) { @@ -2186,7 +2190,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, //////////////////////////////////////////////////////////// // static collisions //////////////////////////////////////////////////////////// - + /* // update cloth bvh bvh_update_from_float3(bvh1, cloth->current_xold, cloth->numverts, cloth->current_x, 0); // 0 means STATIC, 1 means MOVING (see later in this function) @@ -2238,6 +2242,80 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, VECADD(cloth->current_x[i], cloth->current_xold[i], cloth->current_v[i]); } ////////////////////////////////////////////// + */ + // Test on *simple* selfcollisions + collisions = 1; + count = 0; + current_x = cloth->current_x; // needed for openMP - return collisions; +#pragma omp parallel for private(i,j, collisions) shared(current_x) + for(count = 0; count < 6; count++) + { + collisions = 0; + + for(i = 0; i < cloth->numverts; i++) + { + for(j = i + 1; j < cloth->numverts; j++) + { + float temp[3]; + float length = 0; + float mindistance = cloth->selftree->epsilon; + + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + { + if((cloth->verts [i].goal >= SOFTGOALSNAP) + && (cloth->verts [j].goal >= SOFTGOALSNAP)) + { + continue; + } + } + + // check for adjacent points + if(BLI_edgehash_haskey ( cloth->edgehash, i, j )) + { + continue; + } + + VECSUB(temp, current_x[i], current_x[j]); + + length = Normalize(temp); + + if(length < mindistance) + { + float correction = mindistance - length; + + if(cloth->verts [i].goal >= SOFTGOALSNAP) + { + VecMulf(temp, -correction); + VECADD(current_x[j], current_x[j], temp); + } + else if(cloth->verts [j].goal >= SOFTGOALSNAP) + { + VecMulf(temp, correction); + VECADD(current_x[i], current_x[i], temp); + } + else + { + VecMulf(temp, -correction*0.5); + VECADD(current_x[j], current_x[j], temp); + + VECSUB(current_x[i], current_x[i], temp); + } + + collisions = 1; + } + } + } + } + + ////////////////////////////////////////////// + // SELFCOLLISIONS: update velocities + ////////////////////////////////////////////// + for(i = 0; i < cloth->numverts; i++) + { + VECSUB(cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i]); + } + ////////////////////////////////////////////// + + return 1; } diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index f9049fbcfcb..f39d5465b87 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -780,8 +780,7 @@ int bvh_overlap(float *bv1, float *bv2) */ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collision_list) { - int i = 0, ret = 0, tempret = 0; - + int i = 0, ret = 0; if (bvh_overlap(tree1->bv, tree2->bv)) { // Check if this node in the first tree is a leaf @@ -790,19 +789,25 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio // Check if this node in the second tree a leaf if (tree2->isleaf) { - // save potential colliding triangles + CollisionPair *collpair = NULL; - CollisionPair *collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); - - VECCOPY(collpair->point_indexA, tree1->point_index); - collpair->point_indexA[3] = tree1->point_index[3]; - - VECCOPY(collpair->point_indexB, tree2->point_index); - collpair->point_indexB[3] = tree2->point_index[3]; - - BLI_linklist_append(&collision_list[0], collpair); - - return 1; + if(tree1 != tree2) // do not collide same points + { + // save potential colliding triangles + collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); + + VECCOPY(collpair->point_indexA, tree1->point_index); + collpair->point_indexA[3] = tree1->point_index[3]; + + VECCOPY(collpair->point_indexB, tree2->point_index); + collpair->point_indexB[3] = tree2->point_index[3]; + + BLI_linklist_append(&collision_list[0], collpair); + + return 1; + } + else + return 0; } else { @@ -810,8 +815,8 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree2->nodes[i] && (tempret = bvh_traverse (tree1, tree2->nodes[i], collision_list))) - ret += tempret; + if (tree2->nodes[i] && (bvh_traverse (tree1, tree2->nodes[i], collision_list))) + ret = 1; } } } @@ -821,8 +826,8 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree1->nodes [i] && (tempret = bvh_traverse (tree1->nodes[i], tree2, collision_list))) - ret += tempret; + if (tree1->nodes [i] && (bvh_traverse (tree1->nodes[i], tree2, collision_list))) + ret = 1; } } } diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 2db2de7e183..0edfb64e92f 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -125,7 +125,7 @@ typedef struct CollisionSettings short collision_type; /* which collision system is used. */ short loop_count; /* How many iterations for the collision loop. */ int flags; /* collision flags defined in BKE_cloth.h */ - int pad; + float selfepsilon; } CollisionSettings; @@ -151,6 +151,7 @@ typedef struct Cloth unsigned char pad2; short pad3; struct BVH *tree; /* collision tree for this cloth object */ + struct BVH *selftree; /* self collision tree for this cloth object */ struct MFace *mfaces; struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ float (*x)[3]; /* The current position of all vertices.*/ @@ -159,6 +160,7 @@ typedef struct Cloth float (*current_xold)[3]; /* The TEMPORARY previous position of all vertices.*/ float (*v)[3]; /* the current velocity of all vertices */ float (*current_v)[3]; + struct EdgeHash *edgehash; // used for fast checking adjacent points } Cloth; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 0754aa62016..474236fd5b2 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3329,12 +3329,13 @@ static void object_panel_cloth_III(Object *ob) uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,70,130,20, &clmd->coll_parms.flags, 0, 0, 0, 0, "Enable collisions with this object"); + uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,160,130,20, &clmd->coll_parms.flags, 0, 0, 0, 0, "Enable collisions with this object"); if (clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) { // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ - uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,30,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); - uiDefBut(block, LABEL, 0, "",160,30,150,20, NULL, 0.0, 0, 0, 0, ""); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,140,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); + uiDefBut(block, LABEL, 0, "",160,140,150,20, NULL, 0.0, 0, 0, 0, ""); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Selfcoll balls:", 10,120,150,20, &clmd->coll_parms.selfepsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between two selfcollision points"); } else uiDefBut(block, LABEL, 0, "",140,10,170,20, NULL, 0.0, 0, 0, 0, ""); From 8c0968a01361af5f68a3ac83f552777eeb28aa49 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 4 Nov 2007 22:11:00 +0000 Subject: [PATCH 042/101] Kicked my own cache code, will use point cache in the near feature --- source/blender/blenkernel/BKE_cloth.h | 2 +- source/blender/blenkernel/intern/cloth.c | 286 +---------------------- source/blender/src/buttons_object.c | 4 +- 3 files changed, 10 insertions(+), 282 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 42ea6db0430..dd62a24a036 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -116,7 +116,7 @@ typedef enum // needed for buttons_object.c -void cloth_cache_free ( ClothModifierData *clmd, float time ); +// void cloth_cache_free ( ClothModifierData *clmd, float time ); void cloth_free_modifier ( ClothModifierData *clmd ); // needed for cloth.c diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index cc5c6a289cd..360bf421d71 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -403,278 +403,6 @@ DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) return NULL; } - -int cloth_cache_search_frame ( ClothModifierData *clmd, float time ) -{ - Frame *frame = NULL; - LinkNode *search = NULL; - - if ( clmd->clothObject ) - { - search = clmd->sim_parms.cache; - - while ( search ) - { - frame = ( Frame * ) search->link; - - if ( frame ) - { - if ( frame->time == time ) - return 1; - } - - search = search->next; - } - } - - return 0; - -} - -float cloth_cache_last_frame ( ClothModifierData *clmd ) -{ - Frame *frame = NULL; - LinkNode *search = NULL; - float time = 0; - - if ( clmd->clothObject ) - { - search = clmd->sim_parms.cache; - - while ( search ) - { - frame = ( Frame * ) search->link; - - if ( frame ) - { - if ( frame->time > time ) - time = frame->time; - } - } - } - return time; -} - -float cloth_cache_first_frame ( ClothModifierData *clmd ) -{ - Frame *frame = NULL; - LinkNode *search = NULL; - float time = -1.0; - - if ( clmd->clothObject ) - { - search = clmd->sim_parms.cache; - - while ( search ) - { - frame = ( Frame * ) search->link; - - if ( frame ) - { - if ( time < 0.0 ) - time = frame->time; - else - { - if ( frame->time < time ) - time = frame->time; - } - } - } - } - return time; -} - -void cloth_cache_get_frame ( ClothModifierData *clmd, float time ) -{ - Frame *frame = NULL; - LinkNode *search = NULL; - float newtime = time + clmd->sim_parms.preroll; - - if ( clmd->clothObject ) - { - search = clmd->sim_parms.cache; - - while ( search ) - { - frame = ( Frame * ) search->link; - - if ( frame ) - { - if ( frame->time == newtime ) - { - // something changed, free cache! - if ( clmd->clothObject->numverts != frame->numverts ) - { - cloth_cache_free ( clmd, 0 ); - printf ( "clmd->clothObject->numverts != frame->numverts\n" ); - return; - } - - memcpy ( clmd->clothObject->verts, frame->verts, sizeof ( ClothVertex ) *frame->numverts ); - - memcpy ( clmd->clothObject->x, frame->x, sizeof ( float ) *frame->numverts * 3); - - memcpy ( clmd->clothObject->xold, frame->xold, sizeof ( float ) *frame->numverts * 3); - - memcpy ( clmd->clothObject->v, frame->v, sizeof ( float ) *frame->numverts * 3); - - memcpy ( clmd->clothObject->current_xold, frame->current_xold, sizeof ( float ) *frame->numverts * 3); - - // TODO: temp off - implicit_set_positions ( clmd ); - - return; - } - } - - search = search->next; - } - } -} - -void cloth_cache_set_frame ( ClothModifierData *clmd, float time ) -{ - Frame *frame = NULL; - - if ( clmd->clothObject ) - { - frame = ( Frame * ) MEM_callocN ( sizeof ( Frame ), "cloth_cache_frame" ); - - if ( frame ) - { - frame->time = time; - frame->numverts = clmd->clothObject->numverts; - frame->verts = MEM_dupallocN ( clmd->clothObject->verts ); - - if ( !frame->verts ) - { - MEM_freeN ( frame ); - return; - } - - frame->x = MEM_dupallocN ( clmd->clothObject->x ); - - if ( !frame->x ) - { - MEM_freeN ( frame->verts ); - MEM_freeN ( frame ); - return; - } - - frame->xold = MEM_dupallocN ( clmd->clothObject->xold ); - - if ( !frame->xold ) - { - MEM_freeN ( frame->verts ); - MEM_freeN ( frame->x ); - MEM_freeN ( frame ); - return; - } - - frame->v = MEM_dupallocN ( clmd->clothObject->v ); - - if ( !frame->v ) - { - MEM_freeN ( frame->verts ); - MEM_freeN ( frame->x ); - MEM_freeN ( frame->xold ); - MEM_freeN ( frame ); - return; - } - - frame->current_xold= MEM_dupallocN ( clmd->clothObject->current_xold ); - - if ( !frame->current_xold ) - { - MEM_freeN ( frame->verts ); - MEM_freeN ( frame->x ); - MEM_freeN ( frame->xold ); - MEM_freeN ( frame->v ); - MEM_freeN ( frame ); - return; - } - - BLI_linklist_append ( &clmd->sim_parms.cache, frame ); - - } - } - -} - -// free cloth cache -void cloth_cache_free ( ClothModifierData *clmd, float time ) -{ - Frame *frame = NULL; - LinkNode *search = NULL, *lastsearch = NULL; - float newtime = time + clmd->sim_parms.preroll; - - if ( time <= 2.0 ) - newtime = time; - - if ( clmd->clothObject ) - { - if ( clmd->sim_parms.cache ) - { - lastsearch = search = clmd->sim_parms.cache; - - while ( search ) - { - frame = ( Frame * ) search->link; - - if ( frame->time >= newtime ) - { - - if ( frame->verts ) - { - MEM_freeN ( frame->verts ); - } - - if ( frame->x ) - { - MEM_freeN ( frame->x ); - } - - if ( frame->xold ) - { - MEM_freeN ( frame->xold ); - } - - if ( frame->v ) - { - MEM_freeN ( frame->v ); - } - - if ( frame->current_xold ) - { - MEM_freeN ( frame->current_xold ); - } - - MEM_freeN ( frame ); - - lastsearch->next = search->next; - MEM_freeN ( search ); - search = lastsearch->next; - } - else - { - lastsearch = search; - search = search->next; - } - } - - if ( time <= 1.0 ) - { - BLI_linklist_free(clmd->sim_parms.cache, NULL); - clmd->sim_parms.cache = NULL; - } - - if ( time <= 2.0 ) - clmd->sim_parms.preroll = 0; - } - } -} - - /** * cloth_deform_verts - simulates one step, framenr is in frames. * @@ -773,7 +501,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d // Insure we have a clmd->clothObject, in case allocation failed. if (clmd->clothObject != NULL) { - if(!cloth_cache_search_frame(clmd, framenr)) + // if(!cloth_cache_search_frame(clmd, framenr)) { verts = cloth->verts; @@ -798,13 +526,13 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d printf("Cloth simulation time: %f\n", tval()); - cloth_cache_set_frame(clmd, framenr); + // cloth_cache_set_frame(clmd, framenr); - } + }/* else // just retrieve the cached frame { cloth_cache_get_frame(clmd, framenr); - } + }*/ // Copy the result back to the object. cloth_to_object (ob, result, clmd); @@ -813,7 +541,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); } - } + }/* else if ( ( deltaTime <= 0.0f ) || ( deltaTime > 1.0f ) ) { if ( ( clmd->clothObject != NULL ) && ( clmd->sim_parms.cache ) ) @@ -824,7 +552,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d cloth_to_object (ob, result, clmd); } } - } + }*/ return result; } @@ -840,7 +568,7 @@ void cloth_free_modifier (ClothModifierData *clmd) cloth = clmd->clothObject; // free our frame cache - cloth_cache_free(clmd, 0); + // cloth_cache_free(clmd, 0); /* Calls the solver and collision frees first as they * might depend on data in clmd->clothObject. */ diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 474236fd5b2..45a1502840c 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2181,7 +2181,7 @@ void do_object_panels(unsigned short event) CFRA= 1; update_for_newframe_muted(); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - cloth_cache_free(clmd, 2); + // cloth_cache_free(clmd, 2); allqueue(REDRAWBUTSOBJECT, 0); allqueue(REDRAWVIEW3D, 0); } @@ -2192,7 +2192,7 @@ void do_object_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - cloth_cache_free(clmd, MAX2(2.0,G.scene->r.cfra+1.0)); + // cloth_cache_free(clmd, MAX2(2.0,G.scene->r.cfra+1.0)); allqueue(REDRAWBUTSOBJECT, 0); } } From 0a1be3e2cee4375c27155a8fe090542b8e25c7ed Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 5 Nov 2007 19:28:38 +0000 Subject: [PATCH 043/101] Fun commit: I put some 3-liner verlet integrator in, to activate it, set clmd->sim_parms.solver_type in cloth_init to 1 - bugs in there --- source/blender/blenkernel/BKE_cloth.h | 8 ++++++++ source/blender/blenkernel/intern/cloth.c | 6 +++--- source/blender/blenkernel/intern/implicit.c | 21 ++++----------------- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index dd62a24a036..783faf42e18 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -171,6 +171,11 @@ int implicit_init ( Object *ob, ClothModifierData *clmd ); int implicit_free ( ClothModifierData *clmd ); int implicit_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors ); +/* explicit verlet simulator */ +int verlet_init ( Object *ob, ClothModifierData *clmd ); +int verlet_free ( ClothModifierData *clmd ); +int verlet_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors ); + /* used for caching in implicit.c */ typedef struct Frame { @@ -227,5 +232,8 @@ typedef struct FaceCollPair } FaceCollPair; +// function definitions from implicit.c +DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar); + #endif diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 360bf421d71..4be365fdc86 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -114,7 +114,7 @@ double tval() static CM_SOLVER_DEF solvers [] = { { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free }, - // { "Implicit", CM_VERLET, verlet_init, verlet_solver, verlet_free }, + { "Verlet", CM_VERLET, verlet_init, verlet_solver, verlet_free }, }; /* ********** cloth engine ******* */ @@ -504,7 +504,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d // if(!cloth_cache_search_frame(clmd, framenr)) { verts = cloth->verts; - + /* // Force any pinned verts to their constrained location. for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) { @@ -515,7 +515,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d VECCOPY ( verts->xconst, mvert[i].co ); Mat4MulVecfl ( ob->obmat, verts->xconst ); } - + */ tstart(); /* Call the solver. */ diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index a5777b991eb..638f7350822 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -87,10 +87,6 @@ double itval() } #else #include -// intrinsics need better compile flag checking -// #include -// #include -// #include static struct timeval _itstart, _itend; static struct timezone itz; @@ -110,14 +106,7 @@ double itval() return t2-t1; } #endif -/* -#define C99 -#ifdef C99 -#defineDO_INLINE inline -#else -#defineDO_INLINE static -#endif -*/ + struct Cloth; ////////////////////////////////////////// @@ -1502,11 +1491,9 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // call collision function result = cloth_bvh_objcollision(clmd, step + dt, step, dt); - // copy corrected positions back to simulation + // copy corrected positions back to simulation if(result) { - printf("result: %d\n", result); - memcpy(cloth->current_xold, cloth->current_x, sizeof(lfVector) * numverts); memcpy(id->Xnew, cloth->current_x, sizeof(lfVector) * numverts); @@ -2284,12 +2271,12 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, { float correction = mindistance - length; - if(cloth->verts [i].goal >= SOFTGOALSNAP) + if((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [i].goal >= SOFTGOALSNAP)) { VecMulf(temp, -correction); VECADD(current_x[j], current_x[j], temp); } - else if(cloth->verts [j].goal >= SOFTGOALSNAP) + else if((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [j].goal >= SOFTGOALSNAP)) { VecMulf(temp, correction); VECADD(current_x[i], current_x[i], temp); From 873a26ff841e64c9b061779fa09b9461bb4a6681 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 5 Nov 2007 19:29:14 +0000 Subject: [PATCH 044/101] best part (file) was missing --- source/blender/blenkernel/intern/verlet.c | 170 ++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 source/blender/blenkernel/intern/verlet.c diff --git a/source/blender/blenkernel/intern/verlet.c b/source/blender/blenkernel/intern/verlet.c new file mode 100644 index 00000000000..71001fa92a5 --- /dev/null +++ b/source/blender/blenkernel/intern/verlet.c @@ -0,0 +1,170 @@ +/* implicit.c +* +* +* ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. The Blender +* Foundation also sells licenses for use in proprietary software under +* the Blender License. See http://www.blender.org/BL/ for information +* about this. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* The Original Code is Copyright (C) Blender Foundation +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): none yet. +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ +#include +#include +#include +#include +#include "MEM_guardedalloc.h" +/* types */ +#include "DNA_curve_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_cloth_types.h" +#include "DNA_key_types.h" +#include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_lattice_types.h" +#include "DNA_scene_types.h" +#include "DNA_modifier_types.h" +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_edgehash.h" +#include "BLI_threads.h" +#include "BKE_collisions.h" +#include "BKE_curve.h" +#include "BKE_displist.h" +#include "BKE_effect.h" +#include "BKE_global.h" +#include "BKE_key.h" +#include "BKE_object.h" +#include "BKE_cloth.h" +#include "BKE_modifier.h" +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BIF_editdeform.h" + +struct Cloth; + +int verlet_init ( Object *ob, ClothModifierData *clmd ) +{ + return 1; +} + +int verlet_free ( ClothModifierData *clmd ) +{ + return 1; +} + +void integrate ( ClothModifierData *clmd, float dt ) +{ + Cloth *cloth = clmd->clothObject; + unsigned int i = 0; + + // temporary vectors + float temp[3], velocity[3], force[3]; + + mul_fvector_S( force, clmd->sim_parms.gravity, dt*dt ); + + // iterate through all control points + for(i = 0; i < cloth->numverts; i++) + { + if(((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [i].goal < SOFTGOALSNAP)) || !(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL)) + { + // save current control point location + VECCOPY ( temp, cloth->x[i] ); + + // update control point by the formula + // x += (x - old_x)*dampingFactor + force*timeStep^2 + VECSUB ( velocity, cloth->x[i], cloth->xold[i] ); + VECSUBMUL( force, velocity, -clmd->sim_parms.Cvi * 0.01f* dt * dt); + VecMulf(velocity, 0.99); + VECADD ( cloth->x[i], cloth->x[i], velocity ); + VECADD ( cloth->x[i], cloth->x[i], force ); + + // store old control point location + VECCOPY ( cloth->xold[i], temp ); + } + } +} + +void satisfyconstraints(ClothModifierData *clmd) +{ + float delta[3]; + Cloth *cloth = clmd->clothObject; + unsigned int i = 0; + + for(i = 0; i < 5; i++) + { + // calculate spring forces + LinkNode *search = cloth->springs; + while(search) + { + ClothSpring *spring = search->link; + float temp = 0; + float restlen2 = spring->restlen * spring->restlen; + float len2 = 0, len = 0; + + VECSUB(delta, cloth->x[spring->kl], cloth->x[spring->ij]); + len = sqrt(INPR(delta, delta)); + + if(spring->type != CLOTH_SPRING_TYPE_BENDING) + { + temp = (len - spring->restlen)/len; + + mul_fvector_S(delta, delta, temp*0.5); + + // check if vertex is pinned + if(((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [spring->ij].goal < SOFTGOALSNAP)) || !(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL)) + VECADD(cloth->x[spring->ij], cloth->x[spring->ij], delta); + + // check if vertex is pinned + if(((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [spring->kl].goal < SOFTGOALSNAP)) || !(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL)) + VECSUB(cloth->x[spring->kl], cloth->x[spring->kl], delta); + } + + search = search->next; + } + } +} + +int verlet_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors ) +{ + float dt = 0.01; + float step = 0; + + while(step < 1.0f) + { + integrate(clmd, dt); + satisfyconstraints(clmd); + + step+= dt; + } + + return 1; +} + + + + + + From 47c62453db41003b8a3959f102d2fa344cf0ad97 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 6 Nov 2007 02:30:53 +0000 Subject: [PATCH 045/101] Bugfix for wrong springs (resulted in weird behaviour), Implemented two speedups: One for small bending/wrinkle values (1/3 speedup), another speedup is that cloth get automatically in sleep mode but wakes up every frame ([quality-1]/quality speedup) --- source/blender/blenkernel/BKE_cloth.h | 4 +- source/blender/blenkernel/intern/cloth.c | 20 +-- source/blender/blenkernel/intern/implicit.c | 96 +++++++++-- source/blender/blenkernel/intern/verlet.c | 170 -------------------- source/blender/makesdna/DNA_cloth_types.h | 2 + 5 files changed, 101 insertions(+), 191 deletions(-) delete mode 100644 source/blender/blenkernel/intern/verlet.c diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 783faf42e18..8be27ace346 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -86,7 +86,9 @@ typedef enum CLOTH_SIMSETTINGS_FLAG_COLLOBJ = ( 1 << 2 ), // object is only collision object, no cloth simulation is done CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ), // we have goals enabled CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ), // true if tearing is enabled - CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ), // true if tearing is enabled + CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ), + CLOTH_SIMSETTINGS_FLAG_BIG_FORCE = ( 1 << 6 ), // true if we have big spring force for bending + CLOTH_SIMSETTINGS_FLAG_SLEEP = ( 1 << 7 ), // true if we let the cloth go to sleep } CLOTH_SIMSETTINGS_FLAGS; /* SPRING FLAGS */ diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 4be365fdc86..eba11bfedda 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -114,7 +114,7 @@ double tval() static CM_SOLVER_DEF solvers [] = { { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free }, - { "Verlet", CM_VERLET, verlet_init, verlet_solver, verlet_free }, + // { "Verlet", CM_VERLET, verlet_init, verlet_solver, verlet_free }, }; /* ********** cloth engine ******* */ @@ -504,8 +504,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d // if(!cloth_cache_search_frame(clmd, framenr)) { verts = cloth->verts; - /* + // Force any pinned verts to their constrained location. + // has to be commented for verlet for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) { // Save the previous position. @@ -515,7 +516,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d VECCOPY ( verts->xconst, mvert[i].co ); Mat4MulVecfl ( ob->obmat, verts->xconst ); } - */ + tstart(); /* Call the solver. */ @@ -1031,8 +1032,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) { spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); - spring->ij = mface[i].v1; - spring->kl = mface[i].v3; + spring->ij = mface[i].v2; + spring->kl = mface[i].v4; VECSUB ( temp, mvert[spring->kl].co, mvert[spring->ij].co ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_SHEAR; @@ -1045,7 +1046,7 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) node = node2; } } - + // bending springs search2 = cloth->springs; for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) @@ -1083,9 +1084,10 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) } search2 = search2->next; } - - cloth->numsprings = struct_springs + shear_springs + bend_springs; - + + cloth->numspringssave = cloth->numsprings = struct_springs + shear_springs + bend_springs; + cloth->numothersprings = struct_springs + shear_springs; + for ( i = 0; i < numverts; i++ ) { BLI_linklist_free ( edgelist[i],NULL ); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 638f7350822..091a0580232 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -812,6 +812,31 @@ int implicit_free (ClothModifierData *clmd) return 1; } +void cloth_bending_mode(ClothModifierData *clmd, int enabled) +{ + Cloth *cloth = clmd->clothObject; + Implicit_Data *id; + + if(cloth) + { + id = cloth->implicit; + + if(id) + { + if(enabled) + { + cloth->numsprings = cloth->numspringssave; + } + else + { + cloth->numsprings = cloth->numothersprings; + } + + id->A[0].scount = id->dFdV[0].scount = id->dFdX[0].scount = id->P[0].scount = id->Pinv[0].scount = id->bigI[0].scount = cloth->numsprings; + } + } +} + DO_INLINE float fb(float length, float L) { float x = length/L; @@ -1223,37 +1248,48 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, { if(length < L) { + // clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; + s->flags |= CLOTH_SPRING_FLAG_NEEDED; k = clmd->sim_parms.bending; mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); VECADD(s->f, s->f, bending_force); - + + if(INPR(bending_force,bending_force) > 0.13*0.13) + { + clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; + } + dfdx_spring_type2(s->dfdx, dir,length,L,k, cb); } } } -DO_INLINE void cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) +DO_INLINE int cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) { if(s->flags & CLOTH_SPRING_FLAG_NEEDED) { + VECADD(lF[s->ij], lF[s->ij], s->f); + VECSUB(lF[s->kl], lF[s->kl], s->f); + if(s->type != CLOTH_SPRING_TYPE_BENDING) { sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, s->dfdv); sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv); add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); } - - VECADD(lF[s->ij], lF[s->ij], s->f); - VECSUB(lF[s->kl], lF[s->kl], s->f); - + else if(!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE)) + return 0; + sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx); sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, s->dfdx); add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, s->dfdx); - } + } + + return 1; } DO_INLINE void calculateTriangleNormal(float to[3], lfVector *X, MFace mface) @@ -1386,15 +1422,34 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec search = search->next; } + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE) + { + if(cloth->numspringssave != cloth->numsprings) + { + cloth_bending_mode(clmd, 1); + } + } + else + { + if(cloth->numspringssave == cloth->numsprings) + { + cloth_bending_mode(clmd, 0); + } + } + // apply spring forces search = cloth->springs; while(search) { // only handle active springs // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) - cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); + if(!cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX)) + break; search = search->next; } + + clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; + } void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv) @@ -1438,6 +1493,8 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase float dt = 1.0f / clmd->sim_parms.stepsPerFrame; Implicit_Data *id = cloth->implicit; int result = 0; + float force = 0, lastforce = 0; + lfVector *dx; if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { @@ -1457,10 +1514,27 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase effectors= pdInitEffectors(ob,NULL); // calculate - cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); - simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); + cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); - add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); + // check for sleeping + if(!(clmd->coll_parms.flags & CLOTH_SIMSETTINGS_FLAG_SLEEP)) + { + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); + + add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); + } + + dx = create_lfvector(numverts); + sub_lfvector_lfvector(dx, id->Xnew, id->X, numverts); + force = dot_lfvector(dx, dx, numverts); + del_lfvector(dx); + + if((force < 0.00001) && (lastforce >= force)) + clmd->coll_parms.flags |= CLOTH_SIMSETTINGS_FLAG_SLEEP; + else if((lastforce*2 < force)) + clmd->coll_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_SLEEP; + + lastforce = force; if(clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) { diff --git a/source/blender/blenkernel/intern/verlet.c b/source/blender/blenkernel/intern/verlet.c deleted file mode 100644 index 71001fa92a5..00000000000 --- a/source/blender/blenkernel/intern/verlet.c +++ /dev/null @@ -1,170 +0,0 @@ -/* implicit.c -* -* -* ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. The Blender -* Foundation also sells licenses for use in proprietary software under -* the Blender License. See http://www.blender.org/BL/ for information -* about this. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software Foundation, -* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -* -* The Original Code is Copyright (C) Blender Foundation -* All rights reserved. -* -* The Original Code is: all of this file. -* -* Contributor(s): none yet. -* -* ***** END GPL/BL DUAL LICENSE BLOCK ***** -*/ -#include -#include -#include -#include -#include "MEM_guardedalloc.h" -/* types */ -#include "DNA_curve_types.h" -#include "DNA_object_types.h" -#include "DNA_object_force.h" -#include "DNA_cloth_types.h" -#include "DNA_key_types.h" -#include "DNA_mesh_types.h" -#include "DNA_modifier_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_lattice_types.h" -#include "DNA_scene_types.h" -#include "DNA_modifier_types.h" -#include "BLI_arithb.h" -#include "BLI_blenlib.h" -#include "BLI_edgehash.h" -#include "BLI_threads.h" -#include "BKE_collisions.h" -#include "BKE_curve.h" -#include "BKE_displist.h" -#include "BKE_effect.h" -#include "BKE_global.h" -#include "BKE_key.h" -#include "BKE_object.h" -#include "BKE_cloth.h" -#include "BKE_modifier.h" -#include "BKE_utildefines.h" -#include "BKE_global.h" -#include "BIF_editdeform.h" - -struct Cloth; - -int verlet_init ( Object *ob, ClothModifierData *clmd ) -{ - return 1; -} - -int verlet_free ( ClothModifierData *clmd ) -{ - return 1; -} - -void integrate ( ClothModifierData *clmd, float dt ) -{ - Cloth *cloth = clmd->clothObject; - unsigned int i = 0; - - // temporary vectors - float temp[3], velocity[3], force[3]; - - mul_fvector_S( force, clmd->sim_parms.gravity, dt*dt ); - - // iterate through all control points - for(i = 0; i < cloth->numverts; i++) - { - if(((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [i].goal < SOFTGOALSNAP)) || !(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL)) - { - // save current control point location - VECCOPY ( temp, cloth->x[i] ); - - // update control point by the formula - // x += (x - old_x)*dampingFactor + force*timeStep^2 - VECSUB ( velocity, cloth->x[i], cloth->xold[i] ); - VECSUBMUL( force, velocity, -clmd->sim_parms.Cvi * 0.01f* dt * dt); - VecMulf(velocity, 0.99); - VECADD ( cloth->x[i], cloth->x[i], velocity ); - VECADD ( cloth->x[i], cloth->x[i], force ); - - // store old control point location - VECCOPY ( cloth->xold[i], temp ); - } - } -} - -void satisfyconstraints(ClothModifierData *clmd) -{ - float delta[3]; - Cloth *cloth = clmd->clothObject; - unsigned int i = 0; - - for(i = 0; i < 5; i++) - { - // calculate spring forces - LinkNode *search = cloth->springs; - while(search) - { - ClothSpring *spring = search->link; - float temp = 0; - float restlen2 = spring->restlen * spring->restlen; - float len2 = 0, len = 0; - - VECSUB(delta, cloth->x[spring->kl], cloth->x[spring->ij]); - len = sqrt(INPR(delta, delta)); - - if(spring->type != CLOTH_SPRING_TYPE_BENDING) - { - temp = (len - spring->restlen)/len; - - mul_fvector_S(delta, delta, temp*0.5); - - // check if vertex is pinned - if(((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [spring->ij].goal < SOFTGOALSNAP)) || !(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL)) - VECADD(cloth->x[spring->ij], cloth->x[spring->ij], delta); - - // check if vertex is pinned - if(((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [spring->kl].goal < SOFTGOALSNAP)) || !(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL)) - VECSUB(cloth->x[spring->kl], cloth->x[spring->kl], delta); - } - - search = search->next; - } - } -} - -int verlet_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors ) -{ - float dt = 0.01; - float step = 0; - - while(step < 1.0f) - { - integrate(clmd, dt); - satisfyconstraints(clmd); - - step+= dt; - } - - return 1; -} - - - - - - diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 0edfb64e92f..4d75f7a3778 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -161,6 +161,8 @@ typedef struct Cloth float (*v)[3]; /* the current velocity of all vertices */ float (*current_v)[3]; struct EdgeHash *edgehash; // used for fast checking adjacent points + unsigned int numothersprings; + unsigned int numspringssave; } Cloth; From cbc941e342478df6126068f84044d26a1b1aa4e1 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 6 Nov 2007 09:44:09 +0000 Subject: [PATCH 046/101] Merged pointcache from particles branch, but is not used in the moment --- source/blender/blenkernel/BKE_pointcache.h | 41 +++++ source/blender/blenkernel/intern/modifier.c | 111 ++++++++++++ source/blender/blenkernel/intern/pointcache.c | 159 ++++++++++++++++++ source/blender/makesdna/DNA_modifier_types.h | 11 ++ source/blender/src/buttons_editing.c | 23 +++ 5 files changed, 345 insertions(+) create mode 100644 source/blender/blenkernel/BKE_pointcache.h create mode 100644 source/blender/blenkernel/intern/pointcache.c diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h new file mode 100644 index 00000000000..9359177b4e9 --- /dev/null +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -0,0 +1,41 @@ +/* +* +* ***** BEGIN GPL 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. +* +* 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 Blender Foundation. +* All rights reserved. +* +* The Original Code is: all of this file. +* +* Contributor(s): Campbell Barton +* +* ***** END GPL LICENSE BLOCK ***** +*/ + +#ifndef BKE_POINTCACHE_H +#define BKE_POINTCACHE_H + +#include "DNA_ID.h" + +#define PTCache_EXT ".bphys" +#define PTCache_PATH "//pointcache/" + +int PTCache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext); +FILE * PTCache_id_fopen(struct ID *id, char mode, int cfra, int stack_index); +void PTCache_id_clear(struct ID *id, int cfra, int stack_index); + +#endif diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index b124395c207..22692f503e1 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5382,6 +5382,83 @@ static void meshdeformModifier_deformVertsEM( dm->release(dm); } + +/* PointCache - example DONT USE SERIOUSLY */ +static void pointCacheModifier_initData(ModifierData *md) +{ + PointCacheModifierData *pcm= (PointCacheModifierData*) md; + + pcm->mode= ePointCache_Read; /* read */ +} +static void pointCacheModifier_freeData(ModifierData *md) +{ + PointCacheModifierData *pcm = (PointCacheModifierData*) md; +} +static void pointCacheModifier_copyData(ModifierData *md, ModifierData *target) +{ + PointCacheModifierData *pcm= (PointCacheModifierData*) md; + PointCacheModifierData *tpcm= (PointCacheModifierData*) target; + + tpcm->mode = pcm->mode; +} +static int pointCacheModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} +CustomDataMask pointCacheModifier_requiredDataMask(ModifierData *md) +{ + PointCacheModifierData *pcm= (PointCacheModifierData*) md; + CustomDataMask dataMask = 0; + return dataMask; +} + +static void pointCacheModifier_deformVerts( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) +{ + PointCacheModifierData *pcm = (PointCacheModifierData*) md; + + FILE *fp = NULL; + int i; + int stack_index = modifiers_indexInObject(ob, md); + int totvert; + MVert *mvert, *mv; + + DerivedMesh *dm; + + if(derivedData) dm = CDDM_copy(derivedData); + else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); + else return; + + CDDM_apply_vert_coords(dm, vertexCos); + CDDM_calc_normals(dm); + + mvert = mv = dm->getVertArray(dm); + totvert = dm->getNumVerts(dm); + + if (pcm->mode == ePointCache_Read) { + fp = PTCache_id_fopen((ID *)ob, 'w', G.scene->r.cfra, stack_index); + if (!fp) return; + for (mv=mvert, i=0; ico, sizeof(float), 3, fp); + } + fclose(fp); + } else if (pcm->mode == ePointCache_Write) { + float pt[3]; + fp = PTCache_id_fopen((ID *)ob, 'r', G.scene->r.cfra, stack_index); + if (!fp) return; + for (mv=mvert, i=0; irelease(dm); +} + /***/ static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES]; @@ -5649,6 +5726,16 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->updateDepgraph = meshdeformModifier_updateDepgraph; mti->deformVerts = meshdeformModifier_deformVerts; mti->deformVertsEM = meshdeformModifier_deformVertsEM; + + mti = INIT_TYPE(PointCache); + mti->type = eModifierTypeType_OnlyDeform; + mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_RequiresOriginalData; + mti->initData = pointCacheModifier_initData; + mti->freeData = pointCacheModifier_freeData; + mti->copyData = pointCacheModifier_copyData; + mti->dependsOnTime = pointCacheModifier_dependsOnTime; + mti->requiredDataMask = pointCacheModifier_requiredDataMask; + mti->deformVerts = pointCacheModifier_deformVerts; typeArrInit = 0; #undef INIT_TYPE @@ -6032,3 +6119,27 @@ int modifiers_isDeformed(Object *ob) return 0; } +/* checks we only have deform modifiers */ +int modifiers_isDeformedOnly(Object *ob) +{ + ModifierData *md = modifiers_getVirtualModifierList(ob); + ModifierTypeInfo *mti; + for (; md; md=md->next) { + mti = modifierType_getInfo(md->type); + /* TODO - check the modifier is being used! */ + if (mti->type != eModifierTypeType_OnlyDeform) { + return 0; + } + } + return 1; +} + +int modifiers_indexInObject(Object *ob, ModifierData *md_seek) +{ + int i= 0; + ModifierData *md; + + for (md=ob->modifiers.first; (md && md_seek!=md); md=md->next, i++); + if (!md) return -1; /* modifier isnt in the object */ + return i; +} diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c new file mode 100644 index 00000000000..b87a43c30c3 --- /dev/null +++ b/source/blender/blenkernel/intern/pointcache.c @@ -0,0 +1,159 @@ +/** + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * +* Contributor(s): Campbell Barton + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + +#include +#include +#include +#include +#include + +#include "BKE_pointcache.h" + +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BKE_library.h" + +#include "BLI_blenlib.h" +#include "BKE_utildefines.h" +#include "blendef.h" + +/* needed for directory lookup */ +#ifndef WIN32 + #include +#else + #include "BLI_winstuff.h" +#endif + +/* Takes an Object ID and returns a unique name + - id: object id + - cfra: frame for the cache, can be negative + - stack_index: index in the modifier stack. we can have cache for more then one stack_index +*/ + +int PTCache_path(char *filename) +{ + sprintf(filename, PTCache_PATH); + BLI_convertstringcode(filename, G.sce, 0); + return strlen(filename); +} + +int PTCache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext) +{ + int len=0; + char *idname; + char *newname; + filename[0] = '\0'; + newname = filename; + + /* start with temp dir */ + if (do_path) { + len = PTCache_path(filename); + newname += len; + } + idname = (id->name+2); + /* convert chars to hex so they are always a valid file */ + while('\0' != *idname) { + sprintf(newname, "%02X", (char)(*idname++)); + newname+=2; + len += 2; + } + + if (do_ext) { + sprintf(newname, "_%06d_%02d"PTCache_EXT, cfra, stack_index); /* always 6 chars */ + len += 16; + } + + return len; /* make sure the above string is always 16 chars */ +} + +/* youll need to close yourself after! */ +FILE *PTCache_id_fopen(struct ID *id, char mode, int cfra, int stack_index) +{ + /* mode is same as fopen's modes */ + FILE *fp; + char filename[(FILE_MAXDIR+FILE_MAXFILE)*2]; + + PTCache_id_filename(id, filename, cfra, stack_index, 1, 1); + + if (mode=='r') { + if (!BLI_exists(filename)) { + printf("Error, file does not exist '%s'\n", filename); + return NULL; + } + fp = fopen(filename, "rb"); + } else if (mode=='w') { + BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */ + fp = fopen(filename, "wb"); + } + + if (!fp) { + printf("Error creating file filename '%s'\n", filename); + return NULL; + } + + return fp; +} + +/* youll need to close yourself after! */ +void PTCache_id_clear(struct ID *id, int cfra, int stack_index) +{ + int len; /* store the length of the string */ + + /* mode is same as fopen's modes */ + DIR *dir; + struct dirent *de; + char path[FILE_MAX]; + char filename[(FILE_MAXDIR+FILE_MAXFILE)*2]; + char path_full[(FILE_MAXDIR+FILE_MAXFILE)*2]; + + PTCache_path(path); + len = PTCache_id_filename(id, filename, cfra, stack_index, 0, 0); /* no path */ + + /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */ + + dir = opendir(path); + if (dir==NULL) + return; + + while ((de = readdir(dir)) != NULL) { + //if (S_ISREG(status.st_mode)) { /* is file */ + if (strstr(de->d_name, PTCache_EXT)) { /* do we have the right extension?*/ + if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ + BLI_join_dirfile(path_full, path, de->d_name); + BLI_delete(path_full, 0, 0); + } + } + //} + } + + closedir(dir); + return; +} + diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 0aa7d1d4d3d..ee28d7325c7 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -31,6 +31,7 @@ typedef enum ModifierType { eModifierType_Smooth, eModifierType_Cast, eModifierType_MeshDeform, + eModifierType_PointCache, eModifierType_Cloth, eModifierType_Collision, NUM_MODIFIER_TYPES @@ -386,4 +387,14 @@ typedef struct MeshDeformModifierData { int totvert, totcagevert; } MeshDeformModifierData; +typedef struct PointCacheModifierData { + ModifierData modifier; + short mode, pad1, pad2, pad3; +} PointCacheModifierData; + +typedef enum { + ePointCache_Read = (1<<0), + ePointCache_Write = (1<<1), +} PointCacheFlag; + #endif diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 82ca6e5bed0..3da0196cc46 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -88,6 +88,7 @@ #include "BKE_main.h" #include "BKE_modifier.h" #include "BKE_packedFile.h" +#include "BKE_pointcache.h" #include "BKE_scene.h" #include "BLI_blenlib.h" @@ -1398,6 +1399,14 @@ static void modifiers_convertToReal(void *ob_v, void *md_v) BIF_undo_push("Modifier convert to real"); } +static void modifiers_pointCacheClearModifier(void *ob_v, void *md_v) +{ + Object *ob = ob_v; + ModifierData *md = md_v; + int stack_index = modifiers_indexInObject(ob_v, md_v); + PTCache_id_clear((ID *)ob, CFRA, stack_index); +} + static void build_uvlayer_menu_vars(CustomData *data, char **menu_string, int *uvlayer_tmp, char *uvlayer_name) { @@ -1646,6 +1655,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco height = 211; } else if (md->type==eModifierType_MeshDeform) { height = 73; + } else if (md->type==eModifierType_PointCache) { + height = 48; } /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */ @@ -2144,6 +2155,18 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiDefButS(block, NUM, B_NOP, "Precision:", lx+(buttonWidth+1)/2,(cy-=24), buttonWidth/2,19, &mmd->gridsize, 2, 10, 0.5, 0, "The grid size for binding"); } uiBlockEndAlign(block); + } else if (md->type==eModifierType_PointCache) { + PointCacheModifierData *pcm = (PointCacheModifierData *) md; + uiBut *but; + cy -= 20; + uiBlockEndAlign(block); + + uiDefButS(block, ROW,B_MODIFIER_RECALC,"Write Cache", lx, cy, 75, 19, &pcm->mode, 12.0, ePointCache_Read, 0, 0, ""); + uiDefButS(block, ROW,B_MODIFIER_RECALC,"Read Cache", lx+75, cy, 75,19, &pcm->mode, 12.0, ePointCache_Write, 0, 0, ""); + cy -= 20; + but = uiDefBut(block, BUT, B_NOP, "Clear Cache", lx, cy, 150,19, 0, 0, 0, 0, 0, ""); + uiButSetFunc(but, modifiers_pointCacheClearModifier, ob, md); + } uiBlockEndAlign(block); From b37bbe9024e3da2efe01c48235993b426a3bb923 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 6 Nov 2007 12:08:39 +0000 Subject: [PATCH 047/101] New: pointcache integrated with cloth. Maybe some little glitches left there --- source/blender/blenkernel/BKE_cloth.h | 2 +- source/blender/blenkernel/intern/cloth.c | 159 ++++++++++++++----- source/blender/blenkernel/intern/implicit.c | 10 +- source/blender/makesdna/DNA_cloth_types.h | 23 ++- source/blender/makesdna/DNA_modifier_types.h | 2 +- source/blender/src/buttons_object.c | 6 +- 6 files changed, 141 insertions(+), 61 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 8be27ace346..83891cc74d3 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -118,7 +118,7 @@ typedef enum // needed for buttons_object.c -// void cloth_cache_free ( ClothModifierData *clmd, float time ); +void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr); void cloth_free_modifier ( ClothModifierData *clmd ); // needed for cloth.c diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index eba11bfedda..9720ec6b141 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -39,15 +39,15 @@ /* types */ #include "DNA_curve_types.h" +#include "DNA_cloth_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" -#include "DNA_cloth_types.h" #include "DNA_key_types.h" +#include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" -#include "DNA_lattice_types.h" -#include "DNA_scene_types.h" #include "DNA_modifier_types.h" +#include "DNA_scene_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -55,6 +55,8 @@ #include "BLI_linklist.h" #include "BKE_curve.h" +#include "BKE_cloth.h" +#include "BKE_collisions.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" #include "BKE_cdderivedmesh.h" @@ -63,12 +65,11 @@ #include "BKE_global.h" #include "BKE_key.h" #include "BKE_mesh.h" -#include "BKE_object.h" -#include "BKE_cloth.h" -#include "BKE_collisions.h" #include "BKE_modifier.h" +#include "BKE_object.h" +#include "BKE_pointcache.h" #include "BKE_utildefines.h" -#include "BKE_DerivedMesh.h" + #include "BIF_editdeform.h" #include "BIF_editkey.h" #include "DNA_screen_types.h" @@ -403,10 +404,89 @@ DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) return NULL; } -/** -* cloth_deform_verts - simulates one step, framenr is in frames. -* -**/ +int modifiers_indexInObject(Object *ob, ModifierData *md_seek); + +void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) +{ + int stack_index = -1; + + if(!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) + { + stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); + + PTCache_id_clear((ID *)ob, framenr, stack_index); + } +} +static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) +{ + FILE *fp = NULL; + int stack_index = -1; + unsigned int a; + Cloth *cloth = clmd->clothObject; + + if(!cloth) + return; + + stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); + + fp = PTCache_id_fopen((ID *)ob, 'w', framenr, stack_index); + if(!fp) return; + + for(a = 0; a < cloth->numverts; a++) + { + fwrite(&cloth->x[a], sizeof(float),3,fp); + fwrite(&cloth->xconst[a], sizeof(float),3,fp); + fwrite(&cloth->v[a], sizeof(float),3,fp); + } + + fclose(fp); +} +static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) +{ + FILE *fp = NULL; + int stack_index = -1; + unsigned int a, ret = 1; + Cloth *cloth = clmd->clothObject; + + if(!cloth) + return 0; + + stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); + + fp = PTCache_id_fopen((ID *)ob, 'r', framenr, stack_index); + if(!fp) + ret = 0; + else { + for(a = 0; a < cloth->numverts; a++) + { + if(fread(&cloth->x[a], sizeof(float), 3, fp) != 3) + { + ret = 0; + break; + } + if(fread(&cloth->xconst[a], sizeof(float), 3, fp) != 3) + { + ret = 0; + break; + } + if(fread(&cloth->v[a], sizeof(float), 3, fp) != 3) + { + ret = 0; + break; + } + } + + fclose(fp); + } + + implicit_set_positions(clmd); + + return ret; +} + +/************************************************ + * clothModifier_do - main simulation function +************************************************/ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { unsigned int i; @@ -421,7 +501,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d unsigned int framenr = (float)G.scene->r.cfra; float current_time = bsystem_time(ob, (float)G.scene->r.cfra, 0.0); ListBase *effectors = NULL; - ClothVertex *verts = NULL; float deltaTime = current_time - clmd->sim_parms.sim_time; clmd->sim_parms.dt = 1.0f / (clmd->sim_parms.stepsPerFrame * G.scene->r.frs_sec); @@ -441,7 +520,10 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d mface = CDDM_get_faces(result); clmd->sim_parms.sim_time = current_time; - + + if ( current_time < clmd->sim_parms.firstframe ) + return result; + // only be active during a specific period: // that's "first frame" and "last frame" on GUI /* @@ -501,20 +583,18 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d // Insure we have a clmd->clothObject, in case allocation failed. if (clmd->clothObject != NULL) { - // if(!cloth_cache_search_frame(clmd, framenr)) + if(!cloth_read_cache(ob, clmd, framenr)) { - verts = cloth->verts; - // Force any pinned verts to their constrained location. // has to be commented for verlet - for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) + for ( i = 0; i < clmd->clothObject->numverts; i++ ) { // Save the previous position. - VECCOPY ( cloth->xold[i], verts->xconst ); + VECCOPY ( cloth->xold[i], cloth->xconst[i] ); VECCOPY ( cloth->current_xold[i], cloth->x[i] ); // Get the current position. - VECCOPY ( verts->xconst, mvert[i].co ); - Mat4MulVecfl ( ob->obmat, verts->xconst ); + VECCOPY ( cloth->xconst[i], mvert[i].co ); + Mat4MulVecfl ( ob->obmat, cloth->xconst[i] ); } tstart(); @@ -527,13 +607,8 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d printf("Cloth simulation time: %f\n", tval()); - // cloth_cache_set_frame(clmd, framenr); - - }/* - else // just retrieve the cached frame - { - cloth_cache_get_frame(clmd, framenr); - }*/ + cloth_write_cache(ob, clmd, framenr); + } // Copy the result back to the object. cloth_to_object (ob, result, clmd); @@ -542,18 +617,15 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); } - }/* + } else if ( ( deltaTime <= 0.0f ) || ( deltaTime > 1.0f ) ) { - if ( ( clmd->clothObject != NULL ) && ( clmd->sim_parms.cache ) ) + if ( clmd->clothObject != NULL ) { - if ( cloth_cache_search_frame ( clmd, framenr ) ) - { - cloth_cache_get_frame(clmd, framenr); + if(cloth_read_cache(ob, clmd, framenr)) cloth_to_object (ob, result, clmd); - } } - }*/ + } return result; } @@ -569,7 +641,7 @@ void cloth_free_modifier (ClothModifierData *clmd) cloth = clmd->clothObject; // free our frame cache - // cloth_cache_free(clmd, 0); + // cloth_clear_cache(ob, clmd, 0); /* Calls the solver and collision frees first as they * might depend on data in clmd->clothObject. */ @@ -614,6 +686,10 @@ void cloth_free_modifier (ClothModifierData *clmd) if ( cloth->current_v != NULL ) MEM_freeN ( cloth->current_v ); + // Free the verts. + if ( cloth->xconst != NULL ) + MEM_freeN ( cloth->xconst ); + cloth->verts = NULL; cloth->numverts = -1; @@ -806,7 +882,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject->verts [i].goal= 0.0; clmd->clothObject->verts [i].flags = 0; VECCOPY(clmd->clothObject->xold[i], clmd->clothObject->x[i]); - VECCOPY(clmd->clothObject->verts [i].xconst, clmd->clothObject->x[i]); + VECCOPY(clmd->clothObject->xconst[i], clmd->clothObject->x[i]); VECCOPY(clmd->clothObject->current_xold[i], clmd->clothObject->x[i]); VecMulf(clmd->clothObject->v[i], 0.0); @@ -826,7 +902,8 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject->selftree = bvh_build_from_float3(NULL, 0, clmd->clothObject->x, numverts, clmd->coll_parms.selfepsilon); - // cloth_cache_set_frame(clmd, 1); + // save initial state + cloth_write_cache(ob, clmd, framenr-1); } return 1; @@ -900,6 +977,14 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_v." ); return; } + + clmd->clothObject->xconst = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_xconst" ); + if ( clmd->clothObject->xconst == NULL ) + { + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xconst." ); + return; + } // save face information clmd->clothObject->numfaces = numfaces; diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 091a0580232..41cc9e8cef4 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1369,7 +1369,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec if(verts [i].goal < SOFTGOALSNAP) { // current_position = xold + t * (newposition - xold) - VECSUB(tvect, verts[i].xconst, cloth->xold[i]); + VECSUB(tvect, cloth->xconst[i], cloth->xold[i]); mul_fvector_S(tvect, tvect, time); VECADD(tvect, tvect, cloth->xold[i]); @@ -1378,7 +1378,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec VECADDS(lF[i], lF[i], auxvect, -ks); // calulate damping forces generated by goals - VECSUB(velgoal, cloth->xold[i], verts[i].xconst); + VECSUB(velgoal, cloth->xold[i], cloth->xconst[i]); kd = clmd->sim_parms.goalfrict * 0.01f; // friction force scale taken from SB VECSUBADDSS(lF[i], velgoal, kd, lV[i], kd); @@ -1503,7 +1503,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // update velocities with constrained velocities from pinned verts if(verts [i].goal >= SOFTGOALSNAP) { - VECSUB(id->V[i], verts[i].xconst, cloth->xold[i]); + VECSUB(id->V[i], cloth->xconst[i], cloth->xold[i]); // VecMulf(id->V[i], 1.0 / dt); } } @@ -1625,8 +1625,8 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase } else { - VECCOPY(cloth->current_xold[i], verts[i].xconst); - VECCOPY(cloth->x[i], verts[i].xconst); + VECCOPY(cloth->current_xold[i], cloth->xconst[i]); + VECCOPY(cloth->x[i], cloth->xconst[i]); } } } diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 4d75f7a3778..2441c8b721f 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -43,13 +43,11 @@ typedef struct ClothVertex { int flags; /* General flags per vertex. */ - float xconst [3]; /* constrained position */ float mass; /* mass / weight of the vertex */ float goal; /* goal, from SB */ float impulse[3]; /* used in collision.c */ unsigned int impulse_count; /* same as above */ -} -ClothVertex; +} ClothVertex; /** @@ -66,8 +64,7 @@ typedef struct ClothSpring float dfdx[3][3]; float dfdv[3][3]; float f[3]; -} -ClothSpring; +} ClothSpring; @@ -108,13 +105,12 @@ typedef struct SimulationSettings float sim_time_old; struct LinkNode *cache; float defgoal; - int goalfrict; + float goalfrict; float goalspring; int maxspringlen; /* in percent!; if tearing enabled, a spring will get cut */ int lastframe; /* frame on which simulation stops */ int firstframe; /* frame on which simulation starts */ -} -SimulationSettings; +} SimulationSettings; typedef struct CollisionSettings @@ -126,8 +122,7 @@ typedef struct CollisionSettings short loop_count; /* How many iterations for the collision loop. */ int flags; /* collision flags defined in BKE_cloth.h */ float selfepsilon; -} -CollisionSettings; +} CollisionSettings; /** @@ -143,7 +138,7 @@ CollisionSettings; typedef struct Cloth { struct ClothVertex *verts; /* The vertices that represent this cloth. */ - struct LinkNode *springs; /* The springs connecting the mesh. */ + 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; @@ -160,10 +155,10 @@ typedef struct Cloth float (*current_xold)[3]; /* The TEMPORARY previous position of all vertices.*/ float (*v)[3]; /* the current velocity of all vertices */ float (*current_v)[3]; - struct EdgeHash *edgehash; // used for fast checking adjacent points + float (*xconst)[3]; + struct EdgeHash *edgehash; /* used for fast checking adjacent points */ unsigned int numothersprings; unsigned int numspringssave; -} -Cloth; +} Cloth; #endif diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index ee28d7325c7..151e652eef0 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -344,7 +344,7 @@ typedef struct SoftbodyModifierData { typedef struct ClothModifierData { ModifierData modifier; - Cloth *clothObject; /* The internal data structure for cloth. */ + struct Cloth *clothObject; /* The internal data structure for cloth. */ SimulationSettings sim_parms; /* definition is in DNA_cloth_types.h */ CollisionSettings coll_parms; /* definition is in DNA_cloth_types.h */ } ClothModifierData; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 2e3801135eb..70559d29f40 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2187,7 +2187,7 @@ void do_object_panels(unsigned short event) CFRA= 1; update_for_newframe_muted(); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - // cloth_cache_free(clmd, 2); + cloth_clear_cache(ob, clmd, 2); allqueue(REDRAWBUTSOBJECT, 0); allqueue(REDRAWVIEW3D, 0); } @@ -2198,7 +2198,7 @@ void do_object_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - // cloth_cache_free(clmd, MAX2(2.0,G.scene->r.cfra+1.0)); + cloth_clear_cache(ob, clmd, MAX2(2.0,G.scene->r.cfra+1.0)); allqueue(REDRAWBUTSOBJECT, 0); } } @@ -3242,7 +3242,7 @@ static void object_panel_cloth(Object *ob) } uiDefButF(block, NUM, B_CLOTH_RENEW, "G Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Damp:", 160,50,150,20, &clmd->sim_parms.goalfrict , 0.0, 50.0, 10, 0, "Goal (vertex target position) friction"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G 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"); } From c5d4e8a137437c047fc84cf9267b5b0d5c164188 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 6 Nov 2007 14:26:08 +0000 Subject: [PATCH 048/101] updating bullet --- extern/bullet2/src/Bullet-C-Api.h | 170 +++- .../BroadphaseCollision/btAxisSweep3.cpp | 638 +------------- .../BroadphaseCollision/btAxisSweep3.h | 832 +++++++++++++++++- .../btBroadphaseInterface.h | 18 +- .../BroadphaseCollision/btBroadphaseProxy.h | 48 +- .../btCollisionAlgorithm.cpp | 2 +- .../btCollisionAlgorithm.h | 8 +- .../BroadphaseCollision/btDispatcher.h | 10 +- .../btMultiSapBroadphase.cpp | 204 +++++ .../btMultiSapBroadphase.h | 119 +++ .../btOverlappingPairCache.cpp | 452 ++++++++-- .../btOverlappingPairCache.h | 229 ++++- .../btOverlappingPairCallback.h | 37 + .../btSimpleBroadphase.cpp | 246 ++++-- .../BroadphaseCollision/btSimpleBroadphase.h | 82 +- .../src/BulletCollision/CMakeLists.txt | 8 + .../SphereTriangleDetector.h | 4 +- .../btCollisionConfiguration.h | 47 + .../CollisionDispatch/btCollisionCreateFunc.h | 2 +- .../btCollisionDispatcher.cpp | 206 ++--- .../CollisionDispatch/btCollisionDispatcher.h | 56 +- .../CollisionDispatch/btCollisionObject.cpp | 5 + .../CollisionDispatch/btCollisionObject.h | 21 +- .../CollisionDispatch/btCollisionWorld.cpp | 60 +- .../CollisionDispatch/btCollisionWorld.h | 30 +- .../btCompoundCollisionAlgorithm.cpp | 8 +- .../btCompoundCollisionAlgorithm.h | 19 +- .../btConvexConcaveCollisionAlgorithm.cpp | 12 +- .../btConvexConcaveCollisionAlgorithm.h | 22 +- .../btConvexConvexAlgorithm.cpp | 17 +- .../btConvexConvexAlgorithm.h | 17 +- .../btDefaultCollisionConfiguration.cpp | 237 +++++ .../btDefaultCollisionConfiguration.h | 87 ++ .../btEmptyCollisionAlgorithm.h | 6 +- .../CollisionDispatch/btManifoldResult.cpp | 23 +- .../CollisionDispatch/btManifoldResult.h | 29 +- .../btSimulationIslandManager.cpp | 80 +- .../btSimulationIslandManager.h | 12 +- .../btSphereBoxCollisionAlgorithm.cpp | 19 +- .../btSphereBoxCollisionAlgorithm.h | 15 +- .../btSphereSphereCollisionAlgorithm.cpp | 12 +- .../btSphereSphereCollisionAlgorithm.h | 11 +- .../btSphereTriangleCollisionAlgorithm.cpp | 10 +- .../btSphereTriangleCollisionAlgorithm.h | 11 +- .../CollisionDispatch/btUnionFind.cpp | 1 + .../CollisionDispatch/btUnionFind.h | 6 +- .../CollisionShapes/btBoxShape.cpp | 11 +- .../CollisionShapes/btBoxShape.h | 102 ++- .../btBvhTriangleMeshShape.cpp | 49 +- .../CollisionShapes/btBvhTriangleMeshShape.h | 25 +- .../CollisionShapes/btCapsuleShape.cpp | 2 +- .../CollisionShapes/btCapsuleShape.h | 10 +- .../CollisionShapes/btCollisionShape.h | 24 +- .../CollisionShapes/btCompoundShape.cpp | 13 +- .../CollisionShapes/btCompoundShape.h | 51 +- .../CollisionShapes/btConcaveShape.h | 2 +- .../CollisionShapes/btConeShape.h | 10 +- .../CollisionShapes/btConvexHullShape.h | 7 +- .../CollisionShapes/btConvexInternalShape.cpp | 78 ++ .../CollisionShapes/btConvexInternalShape.h | 99 +++ .../CollisionShapes/btConvexShape.cpp | 59 -- .../CollisionShapes/btConvexShape.h | 90 +- .../btConvexTriangleMeshShape.cpp | 2 +- .../btConvexTriangleMeshShape.h | 10 +- .../CollisionShapes/btCylinderShape.cpp | 14 +- .../CollisionShapes/btCylinderShape.h | 18 +- .../CollisionShapes/btEmptyShape.cpp | 2 +- .../CollisionShapes/btEmptyShape.h | 10 +- .../btHeightfieldTerrainShape.cpp | 52 +- .../btHeightfieldTerrainShape.h | 4 +- .../CollisionShapes/btMinkowskiSumShape.cpp | 2 +- .../CollisionShapes/btMinkowskiSumShape.h | 10 +- .../CollisionShapes/btMultiSphereShape.cpp | 2 +- .../CollisionShapes/btMultiSphereShape.h | 10 +- .../CollisionShapes/btOptimizedBvh.cpp | 394 ++++++++- .../CollisionShapes/btOptimizedBvh.h | 85 +- .../btPolyhedralConvexShape.cpp | 2 +- .../CollisionShapes/btPolyhedralConvexShape.h | 10 +- .../CollisionShapes/btSphereShape.cpp | 2 +- .../CollisionShapes/btSphereShape.h | 18 +- .../CollisionShapes/btStaticPlaneShape.cpp | 2 +- .../CollisionShapes/btStaticPlaneShape.h | 4 +- .../btStridingMeshInterface.cpp | 2 +- .../CollisionShapes/btStridingMeshInterface.h | 2 +- .../CollisionShapes/btTetrahedronShape.h | 4 +- .../CollisionShapes/btTriangleBuffer.h | 2 +- .../CollisionShapes/btTriangleCallback.h | 2 +- .../btTriangleIndexVertexArray.cpp | 23 +- .../btTriangleIndexVertexArray.h | 10 +- .../CollisionShapes/btTriangleMesh.h | 4 +- .../CollisionShapes/btTriangleMeshShape.cpp | 5 +- .../CollisionShapes/btTriangleMeshShape.h | 12 +- .../CollisionShapes/btTriangleShape.h | 4 +- .../CollisionShapes/btUniformScalingShape.cpp | 114 +++ .../CollisionShapes/btUniformScalingShape.h | 86 ++ .../btContinuousConvexCollision.cpp | 24 +- .../btContinuousConvexCollision.h | 6 +- .../NarrowPhaseCollision/btConvexCast.h | 8 +- .../btConvexPenetrationDepthSolver.h | 4 +- .../btDiscreteCollisionDetectorInterface.h | 4 +- .../NarrowPhaseCollision/btGjkConvexCast.cpp | 2 +- .../NarrowPhaseCollision/btGjkConvexCast.h | 10 +- .../NarrowPhaseCollision/btGjkEpa.cpp | 4 +- .../NarrowPhaseCollision/btGjkEpa.h | 6 +- .../btGjkEpaPenetrationDepthSolver.cpp | 2 +- .../btGjkEpaPenetrationDepthSolver.h | 2 +- .../btGjkPairDetector.cpp | 2 +- .../NarrowPhaseCollision/btGjkPairDetector.h | 10 +- .../NarrowPhaseCollision/btManifoldPoint.h | 4 +- .../btMinkowskiPenetrationDepthSolver.cpp | 5 +- .../btMinkowskiPenetrationDepthSolver.h | 2 +- .../btPersistentManifold.cpp | 24 +- .../btPersistentManifold.h | 46 +- .../NarrowPhaseCollision/btRaycastCallback.h | 2 +- .../btSimplexSolverInterface.h | 4 +- .../src/BulletCollision/ibmsdk/Makefile | 95 ++ .../bullet2/src/BulletDynamics/CMakeLists.txt | 3 +- .../btConeTwistConstraint.cpp | 12 +- .../ConstraintSolver/btConeTwistConstraint.h | 3 + .../ConstraintSolver/btConstraintSolver.h | 13 +- .../ConstraintSolver/btContactConstraint.cpp | 20 +- .../ConstraintSolver/btContactConstraint.h | 4 +- .../ConstraintSolver/btContactSolverInfo.h | 26 +- .../btGeneric6DofConstraint.cpp | 790 ++++++++++------- .../btGeneric6DofConstraint.h | 459 ++++++++-- .../ConstraintSolver/btHingeConstraint.cpp | 261 +++++- .../ConstraintSolver/btHingeConstraint.h | 69 +- .../ConstraintSolver/btJacobianEntry.h | 4 +- .../btPoint2PointConstraint.cpp | 5 +- .../btPoint2PointConstraint.h | 14 +- .../btSequentialImpulseConstraintSolver.cpp | 522 ++++++----- .../btSequentialImpulseConstraintSolver.h | 25 +- .../btSolve2LinearConstraint.h | 4 +- .../ConstraintSolver/btSolverBody.h | 25 +- .../ConstraintSolver/btSolverConstraint.h | 20 +- .../ConstraintSolver/btTypedConstraint.cpp | 15 +- .../ConstraintSolver/btTypedConstraint.h | 30 +- .../BulletDynamics/Dynamics/Bullet-C-API.cpp | 402 +++++++++ .../Dynamics/btContinuousDynamicsWorld.cpp | 194 ++++ .../Dynamics/btContinuousDynamicsWorld.h | 46 + .../Dynamics/btDiscreteDynamicsWorld.cpp | 132 ++- .../Dynamics/btDiscreteDynamicsWorld.h | 13 +- .../BulletDynamics/Dynamics/btDynamicsWorld.h | 17 +- .../BulletDynamics/Dynamics/btRigidBody.cpp | 11 +- .../src/BulletDynamics/Dynamics/btRigidBody.h | 58 +- .../Dynamics/btSimpleDynamicsWorld.cpp | 20 +- .../Dynamics/btSimpleDynamicsWorld.h | 16 +- .../Vehicle/btRaycastVehicle.cpp | 27 +- .../BulletDynamics/Vehicle/btRaycastVehicle.h | 6 +- .../Vehicle/btVehicleRaycaster.h | 2 +- .../src/BulletDynamics/Vehicle/btWheelInfo.h | 4 +- .../src/BulletDynamics/ibmsdk/Makefile | 45 + extern/bullet2/src/LinearMath/CMakeLists.txt | 1 + extern/bullet2/src/LinearMath/btAabbUtil2.h | 4 +- .../src/LinearMath/btAlignedAllocator.cpp | 119 ++- .../src/LinearMath/btAlignedAllocator.h | 18 +- .../src/LinearMath/btAlignedObjectArray.h | 25 +- extern/bullet2/src/LinearMath/btIDebugDraw.h | 2 + extern/bullet2/src/LinearMath/btMatrix3x3.h | 2 +- extern/bullet2/src/LinearMath/btMinMax.h | 12 +- .../bullet2/src/LinearMath/btPoolAllocator.h | 94 ++ extern/bullet2/src/LinearMath/btQuadWord.h | 64 +- extern/bullet2/src/LinearMath/btQuaternion.h | 6 +- extern/bullet2/src/LinearMath/btScalar.h | 235 ++++- extern/bullet2/src/LinearMath/btStackAlloc.h | 17 +- extern/bullet2/src/LinearMath/btTransform.h | 8 +- .../bullet2/src/LinearMath/btTransformUtil.h | 8 +- extern/bullet2/src/LinearMath/btVector3.h | 50 ++ extern/bullet2/src/LinearMath/ibmsdk/Makefile | 30 + extern/bullet2/src/SConscript | 70 +- extern/bullet2/src/btBulletCollisionCommon.h | 4 +- extern/bullet2/src/btBulletDynamicsCommon.h | 2 + extern/bullet2/src/ibmsdk/Makefile | 10 + 173 files changed, 7409 insertions(+), 2698 deletions(-) create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h create mode 100644 extern/bullet2/src/BulletCollision/ibmsdk/Makefile create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h create mode 100644 extern/bullet2/src/BulletDynamics/ibmsdk/Makefile create mode 100755 extern/bullet2/src/LinearMath/btPoolAllocator.h create mode 100644 extern/bullet2/src/LinearMath/ibmsdk/Makefile create mode 100644 extern/bullet2/src/ibmsdk/Makefile diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h index ccb0c452f3e..45a4f684858 100644 --- a/extern/bullet2/src/Bullet-C-Api.h +++ b/extern/bullet2/src/Bullet-C-Api.h @@ -1,15 +1,173 @@ -#ifndef Bullet_C_API_H -#define Bullet_C_API_H +/* +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 + +#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +#ifdef BT_USE_DOUBLE_PRECISION +typedef double plReal; +#else +typedef float plReal; +#endif + +typedef plReal plVector3[3]; +typedef plReal plQuaternion[4]; #ifdef __cplusplus -extern "C" { -#endif // __cplusplus +extern "C" { +#endif + +/* Particular physics SDK */ + PL_DECLARE_HANDLE(plPhysicsSdkHandle); + +/* Dynamics world, belonging to some physics SDK */ + PL_DECLARE_HANDLE(plDynamicsWorldHandle); + +/* Rigid Body that can be part of a Dynamics World */ + PL_DECLARE_HANDLE(plRigidBodyHandle); + +/* Collision Shape/Geometry, property of a Rigid Body */ + PL_DECLARE_HANDLE(plCollisionShapeHandle); + +/* Constraint for Rigid Bodies */ + PL_DECLARE_HANDLE(plConstraintHandle); + +/* Triangle Mesh interface */ + PL_DECLARE_HANDLE(plMeshInterfaceHandle); + +/* Broadphase Scene/Proxy Handles */ + PL_DECLARE_HANDLE(plCollisionBroadphaseHandle); + PL_DECLARE_HANDLE(plBroadphaseProxyHandle); + PL_DECLARE_HANDLE(plCollisionWorldHandle); + +/* + Create and Delete a Physics SDK +*/ + + extern plPhysicsSdkHandle plNewBulletSdk(); //this could be also another sdk, like ODE, PhysX etc. + extern void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk); + +/* Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */ + + typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2); + + extern plCollisionBroadphaseHandle plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback); + + extern void plDestroyBroadphase(plCollisionBroadphaseHandle bp); + + extern plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); + + extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle); + + extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); + +/* todo: add pair cache support with queries like add/remove/find pair */ + + extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk); + +/* todo: add/remove objects */ + + +/* Dynamics World */ + + extern plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk); + + extern void plDeleteDynamicsWorld(plDynamicsWorldHandle world); + + extern void plStepSimulation(plDynamicsWorldHandle, plReal timeStep); + + extern void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); + + extern void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); + + +/* Rigid Body */ + + extern plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ); + + extern void plDeleteRigidBody(plRigidBodyHandle body); + + +/* Collision Shape definition */ + + extern plCollisionShapeHandle plNewSphereShape(plReal radius); + extern plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z); + extern plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewConeShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewCompoundShape(); + extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn); + + extern void plDeleteShape(plCollisionShapeHandle shape); + + /* Convex Meshes */ + extern plCollisionShapeHandle plNewConvexHullShape(); + extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z); +/* Concave static triangle meshes */ + extern plMeshInterfaceHandle plNewMeshInterface(); + extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); + extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); + + extern void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling); + +/* SOLID has Response Callback/Table/Management */ +/* PhysX has Triggers, User Callbacks and filtering */ +/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */ + +/* typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle rbHandle, plVector3 pos); */ +/* typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle rbHandle, plQuaternion orientation); */ + + /* get world transform */ + extern void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix); + extern void plGetPosition(plRigidBodyHandle object,plVector3 position); + extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation); + + /* set world transform (position/orientation) */ + extern void plSetPosition(plRigidBodyHandle object, const plVector3 position); + extern void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation); + extern void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient); + + typedef struct plRayCastResult { + plRigidBodyHandle m_body; + plCollisionShapeHandle m_shape; + plVector3 m_positionWorld; + plVector3 m_normalWorld; + } plRayCastResult; + + extern int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res); + + /* Sweep API */ + + /* extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */ + + /* Continuous Collision Detection API */ double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]); #ifdef __cplusplus } -#endif // __cplusplus - #endif +#endif //BULLET_C_API_H + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp index be4a11506df..d7eea33ea41 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp @@ -21,640 +21,18 @@ #include -#ifdef DEBUG_BROADPHASE -#include -void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) +btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache) { - int numEdges = m_pHandles[0].m_maxEdges[axis]; - printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); - - int i; - for (i=0;im_handle); - int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; - char beginOrEnd; - beginOrEnd=pEdge->IsMax()?'E':'B'; - printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); - } - - if (checkCardinality) - assert(numEdges == m_numHandles*2+1); -} -#endif //DEBUG_BROADPHASE - - -btBroadphaseProxy* btAxisSweep3::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask) -{ - (void)shapeType; - BP_FP_INT_TYPE handleId = addHandle(min,max, userPtr,collisionFilterGroup,collisionFilterMask); - - Handle* handle = getHandle(handleId); - - return handle; -} - -void btAxisSweep3::destroyProxy(btBroadphaseProxy* proxy) -{ - Handle* handle = static_cast(proxy); - removeHandle(handle->m_handleId); -} - -void btAxisSweep3::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax) -{ - Handle* handle = static_cast(proxy); - updateHandle(handle->m_handleId,aabbMin,aabbMax); - -} - - - - - - -btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles) -:btOverlappingPairCache() -{ - m_invalidPair = 0; - //assert(bounds.HasVolume()); - // 1 handle is reserved as sentinel - btAssert(maxHandles > 1 && maxHandles < BP_MAX_HANDLES); - - // init bounds - m_worldAabbMin = worldAabbMin; - m_worldAabbMax = worldAabbMax; - - btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; - - BP_FP_INT_TYPE maxInt = BP_HANDLE_SENTINEL; - - m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; - - // allocate handles buffer and put all handles on free list - m_pHandles = new Handle[maxHandles]; - m_maxHandles = maxHandles; - m_numHandles = 0; - - // handle 0 is reserved as the null index, and is also used as the sentinel - m_firstFreeHandle = 1; - { - for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) - m_pHandles[i].SetNextFree(i + 1); - m_pHandles[maxHandles - 1].SetNextFree(0); - } - - { - // allocate edge buffers - for (int i = 0; i < 3; i++) - m_pEdges[i] = new Edge[maxHandles * 2]; - } - //removed overlap management - - // make boundary sentinels - - m_pHandles[0].m_clientObject = 0; - - for (int axis = 0; axis < 3; axis++) - { - m_pHandles[0].m_minEdges[axis] = 0; - m_pHandles[0].m_maxEdges[axis] = 1; - - m_pEdges[axis][0].m_pos = 0; - m_pEdges[axis][0].m_handle = 0; - m_pEdges[axis][1].m_pos = BP_HANDLE_SENTINEL; - m_pEdges[axis][1].m_handle = 0; -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - - } + btAssert(maxHandles > 1 && maxHandles < 32767); } -btAxisSweep3::~btAxisSweep3() + +bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache ) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache) { - - for (int i = 2; i >= 0; i--) - delete[] m_pEdges[i]; - delete[] m_pHandles; -} - -void btAxisSweep3::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const -{ - btPoint3 clampedPoint(point); - - - - clampedPoint.setMax(m_worldAabbMin); - clampedPoint.setMin(m_worldAabbMax); - - btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; - out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & BP_HANDLE_MASK) | isMax); - out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & BP_HANDLE_MASK) | isMax); - out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & BP_HANDLE_MASK) | isMax); - -} - - - -BP_FP_INT_TYPE btAxisSweep3::allocHandle() -{ - assert(m_firstFreeHandle); - - BP_FP_INT_TYPE handle = m_firstFreeHandle; - m_firstFreeHandle = getHandle(handle)->GetNextFree(); - m_numHandles++; - - return handle; -} - -void btAxisSweep3::freeHandle(BP_FP_INT_TYPE handle) -{ - assert(handle > 0 && handle < m_maxHandles); - - getHandle(handle)->SetNextFree(m_firstFreeHandle); - m_firstFreeHandle = handle; - - m_numHandles--; -} - - - -BP_FP_INT_TYPE btAxisSweep3::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask) -{ - // quantize the bounds - BP_FP_INT_TYPE min[3], max[3]; - quantize(min, aabbMin, 0); - quantize(max, aabbMax, 1); - - // allocate a handle - BP_FP_INT_TYPE handle = allocHandle(); - assert(handle!= 0xcdcd); - - Handle* pHandle = getHandle(handle); - - pHandle->m_handleId = handle; - //pHandle->m_pOverlaps = 0; - pHandle->m_clientObject = pOwner; - pHandle->m_collisionFilterGroup = collisionFilterGroup; - pHandle->m_collisionFilterMask = collisionFilterMask; - - // compute current limit of edge arrays - BP_FP_INT_TYPE limit = m_numHandles * 2; - - - // insert new edges just inside the max boundary edge - for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) - { - - m_pHandles[0].m_maxEdges[axis] += 2; - - m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; - - m_pEdges[axis][limit - 1].m_pos = min[axis]; - m_pEdges[axis][limit - 1].m_handle = handle; - - m_pEdges[axis][limit].m_pos = max[axis]; - m_pEdges[axis][limit].m_handle = handle; - - pHandle->m_minEdges[axis] = limit - 1; - pHandle->m_maxEdges[axis] = limit; - } - - // now sort the new edges to their correct position - sortMinDown(0, pHandle->m_minEdges[0], false); - sortMaxDown(0, pHandle->m_maxEdges[0], false); - sortMinDown(1, pHandle->m_minEdges[1], false); - sortMaxDown(1, pHandle->m_maxEdges[1], false); - sortMinDown(2, pHandle->m_minEdges[2], true); - sortMaxDown(2, pHandle->m_maxEdges[2], true); - - - return handle; -} - - -void btAxisSweep3::removeHandle(BP_FP_INT_TYPE handle) -{ - - Handle* pHandle = getHandle(handle); - - //explicitly remove the pairs containing the proxy - //we could do it also in the sortMinUp (passing true) - //todo: compare performance - removeOverlappingPairsContainingProxy(pHandle); - - - // compute current limit of edge arrays - int limit = m_numHandles * 2; - - int axis; - - for (axis = 0;axis<3;axis++) - { - m_pHandles[0].m_maxEdges[axis] -= 2; - } - - // remove the edges by sorting them up to the end of the list - for ( axis = 0; axis < 3; axis++) - { - Edge* pEdges = m_pEdges[axis]; - BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; - pEdges[max].m_pos = BP_HANDLE_SENTINEL; - - sortMaxUp(axis,max,false); - - - BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; - pEdges[i].m_pos = BP_HANDLE_SENTINEL; - - - sortMinUp(axis,i,false); - - pEdges[limit-1].m_handle = 0; - pEdges[limit-1].m_pos = BP_HANDLE_SENTINEL; - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis,false); -#endif //DEBUG_BROADPHASE - - - } - - - // free the handle - freeHandle(handle); - - -} - -extern int gOverlappingPairs; - - -void btAxisSweep3::refreshOverlappingPairs() -{ - -} -void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback) -{ - - //perform a sort, to find duplicates and to sort 'invalid' pairs to the end - m_overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); - - //remove the 'invalid' ones -#ifdef USE_POPBACK_REMOVAL - while (m_invalidPair>0) - { - m_invalidPair--; - m_overlappingPairArray.pop_back(); - } -#else - m_overlappingPairArray.resize(m_overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; -#endif - - - int i; - - btBroadphasePair previousPair; - previousPair.m_pProxy0 = 0; - previousPair.m_pProxy1 = 0; - previousPair.m_algorithm = 0; - - - for (i=0;iprocessOverlap(pair); - } else - { - needsRemoval = true; - } - } else - { - //remove duplicate - needsRemoval = true; - //should have no algorithm - btAssert(!pair.m_algorithm); - } - - if (needsRemoval) - { - cleanOverlappingPair(pair); - - // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); - // m_overlappingPairArray.pop_back(); - pair.m_pProxy0 = 0; - pair.m_pProxy1 = 0; - m_invalidPair++; - gOverlappingPairs--; - } - - } -} - - -bool btAxisSweep3::testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - const Handle* pHandleA = static_cast(proxy0); - const Handle* pHandleB = static_cast(proxy1); - - //optimization 1: check the array index (memory address), instead of the m_pos - - for (int axis = 0; axis < 3; axis++) - { - if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || - pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) - { - return false; - } - } - return true; -} - -bool btAxisSweep3::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB) -{ - //optimization 1: check the array index (memory address), instead of the m_pos - - for (int axis = 0; axis < 3; axis++) - { - if (axis != ignoreAxis) - { - if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || - pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) - { - return false; - } - } - } - - //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization) - - /*for (int axis = 0; axis < 3; axis++) - { - if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos || - m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos) - { - return false; - } - } - */ - - return true; -} - -void btAxisSweep3::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax) -{ -// assert(bounds.IsFinite()); - //assert(bounds.HasVolume()); - - Handle* pHandle = getHandle(handle); - - // quantize the new bounds - BP_FP_INT_TYPE min[3], max[3]; - quantize(min, aabbMin, 0); - quantize(max, aabbMax, 1); - - // update changed edges - for (int axis = 0; axis < 3; axis++) - { - BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; - BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; - - int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; - int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; - - m_pEdges[axis][emin].m_pos = min[axis]; - m_pEdges[axis][emax].m_pos = max[axis]; - - // expand (only adds overlaps) - if (dmin < 0) - sortMinDown(axis, emin); - - if (dmax > 0) - sortMaxUp(axis, emax); - - // shrink (only removes overlaps) - if (dmin > 0) - sortMinUp(axis, emin); - - if (dmax < 0) - sortMaxDown(axis, emax); - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - } - - -} - - - - -// sorting a min edge downwards can only ever *add* overlaps -void btAxisSweep3::sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pPrev = pEdge - 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pEdge->m_pos < pPrev->m_pos) - { - Handle* pHandlePrev = getHandle(pPrev->m_handle); - - if (pPrev->IsMax()) - { - // if previous edge is a maximum check the bounds and add an overlap if necessary - if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev)) - { - addOverlappingPair(pHandleEdge,pHandlePrev); - - //AddOverlap(pEdge->m_handle, pPrev->m_handle); - - } - - // update edge reference in other handle - pHandlePrev->m_maxEdges[axis]++; - } - else - pHandlePrev->m_minEdges[axis]++; - - pHandleEdge->m_minEdges[axis]--; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pPrev; - *pPrev = swap; - - // decrement - pEdge--; - pPrev--; - } - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - -} - -// sorting a min edge upwards can only ever *remove* overlaps -void btAxisSweep3::sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pNext = pEdge + 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) - { - Handle* pHandleNext = getHandle(pNext->m_handle); - - if (pNext->IsMax()) - { - // if next edge is maximum remove any overlap between the two handles - if (updateOverlaps) - { - /* - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pNext->m_handle); - btBroadphasePair tmpPair(*handle0,*handle1); - removeOverlappingPair(tmpPair); - */ - - } - - // update edge reference in other handle - pHandleNext->m_maxEdges[axis]--; - } - else - pHandleNext->m_minEdges[axis]--; - - pHandleEdge->m_minEdges[axis]++; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pNext; - *pNext = swap; - - // increment - pEdge++; - pNext++; - } - - -} - -// sorting a max edge downwards can only ever *remove* overlaps -void btAxisSweep3::sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pPrev = pEdge - 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pEdge->m_pos < pPrev->m_pos) - { - Handle* pHandlePrev = getHandle(pPrev->m_handle); - - if (!pPrev->IsMax()) - { - // if previous edge was a minimum remove any overlap between the two handles - if (updateOverlaps) - { - //this is done during the overlappingpairarray iteration/narrowphase collision - /* - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pPrev->m_handle); - btBroadphasePair* pair = findPair(handle0,handle1); - //assert(pair); - - if (pair) - { - removeOverlappingPair(*pair); - } - */ - - } - - // update edge reference in other handle - pHandlePrev->m_minEdges[axis]++;; - } - else - pHandlePrev->m_maxEdges[axis]++; - - pHandleEdge->m_maxEdges[axis]--; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pPrev; - *pPrev = swap; - - // decrement - pEdge--; - pPrev--; - } - - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - -} - -// sorting a max edge upwards can only ever *add* overlaps -void btAxisSweep3::sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pNext = pEdge + 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) - { - Handle* pHandleNext = getHandle(pNext->m_handle); - - if (!pNext->IsMax()) - { - // if next edge is a minimum check the bounds and add an overlap if necessary - if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext)) - { - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pNext->m_handle); - addOverlappingPair(handle0,handle1); - } - - // update edge reference in other handle - pHandleNext->m_minEdges[axis]--; - } - else - pHandleNext->m_maxEdges[axis]--; - - pHandleEdge->m_maxEdges[axis]++; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pNext; - *pNext = swap; - - // increment - pEdge++; - pNext++; - } - + // 1 handle is reserved as sentinel + btAssert(maxHandles > 1 && maxHandles < 2147483647); } diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h index 57bbb368672..d36df6e6621 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h @@ -19,34 +19,24 @@ #ifndef AXIS_SWEEP_3_H #define AXIS_SWEEP_3_H -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btVector3.h" #include "btOverlappingPairCache.h" +#include "btBroadphaseInterface.h" #include "btBroadphaseProxy.h" - - -//Enable BP_USE_FIXEDPOINT_INT_32 if you need more then 32767 objects -//#define BP_USE_FIXEDPOINT_INT_32 1 - -#ifdef BP_USE_FIXEDPOINT_INT_32 - #define BP_FP_INT_TYPE unsigned int - #define BP_MAX_HANDLES 1500000 //arbitrary maximum number of handles - #define BP_HANDLE_SENTINEL 0x7fffffff - #define BP_HANDLE_MASK 0xfffffffe -#else - #define BP_FP_INT_TYPE unsigned short int - #define BP_MAX_HANDLES 32767 - #define BP_HANDLE_SENTINEL 0xffff - #define BP_HANDLE_MASK 0xfffe -#endif //BP_USE_FIXEDPOINT_INT_32 +#include "btOverlappingPairCallback.h" //#define DEBUG_BROADPHASE 1 -/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. -/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using integer coordinates instead of floats. -/// The testOverlap check is optimized to check the array index, rather then the actual AABB coordinates/pos -class btAxisSweep3 : public btOverlappingPairCache +/// btAxisSweep3Internal is an internal template class that implements sweep and prune. +/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead. +template +class btAxisSweep3Internal : public btBroadphaseInterface { +protected: + + BP_FP_INT_TYPE m_bpHandleMask; + BP_FP_INT_TYPE m_handleSentinel; public: @@ -61,36 +51,44 @@ public: }; public: - class Handle : public btBroadphaseProxy + ATTRIBUTE_ALIGNED16(class) Handle : public btBroadphaseProxy { public: - + BT_DECLARE_ALIGNED_ALLOCATOR(); + // indexes into the edge arrays BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12 - BP_FP_INT_TYPE m_handleId; +// BP_FP_INT_TYPE m_uniqueId; BP_FP_INT_TYPE m_pad; //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject - inline void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} - inline BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} + SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} + SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry -private: +protected: btPoint3 m_worldAabbMin; // overall system bounds btPoint3 m_worldAabbMax; // overall system bounds btVector3 m_quantize; // scaling factor for quantization BP_FP_INT_TYPE m_numHandles; // number of active handles - int m_maxHandles; // max number of handles + BP_FP_INT_TYPE m_maxHandles; // max number of handles Handle* m_pHandles; // handles pool BP_FP_INT_TYPE m_firstFreeHandle; // free handles list Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries) - int m_invalidPair; + btOverlappingPairCache* m_pairCache; + + ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. + btOverlappingPairCallback* m_userPairCallback; + + bool m_ownsPairCache; + + int m_invalidPair; // allocation/deallocation BP_FP_INT_TYPE allocHandle(); @@ -108,29 +106,773 @@ private: void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const; - void sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); - void sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); - void sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); - void sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); + void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); public: - btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles = 16384); - virtual ~btAxisSweep3(); - virtual void refreshOverlappingPairs(); + btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0); + + virtual ~btAxisSweep3Internal(); + + + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask); - void removeHandle(BP_FP_INT_TYPE handle); - void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax); - inline Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} + BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher); + void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher); + void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher); + SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} void processAllOverlappingPairs(btOverlapCallback* callback); //Broadphase Interface - virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask); - virtual void destroyProxy(btBroadphaseProxy* proxy); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); - bool testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + btOverlappingPairCache* getOverlappingPairCache() + { + return m_pairCache; + } + const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_pairCache; + } + + void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback) + { + m_userPairCallback = pairCallback; + } + const btOverlappingPairCallback* getOverlappingPairUserCallback() const + { + return m_userPairCallback; + } +}; + +//////////////////////////////////////////////////////////////////// + + + + +#ifdef DEBUG_BROADPHASE +#include + +template +void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) +{ + int numEdges = m_pHandles[0].m_maxEdges[axis]; + printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); + + int i; + for (i=0;im_handle); + int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; + char beginOrEnd; + beginOrEnd=pEdge->IsMax()?'E':'B'; + printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); + } + + if (checkCardinality) + assert(numEdges == m_numHandles*2+1); +} +#endif //DEBUG_BROADPHASE + +template +btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher) +{ + (void)shapeType; + BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher); + + Handle* handle = getHandle(handleId); + + return handle; +} + + + +template +void btAxisSweep3Internal::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + Handle* handle = static_cast(proxy); + removeHandle(handle->m_uniqueId,dispatcher); +} + +template +void btAxisSweep3Internal::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) +{ + Handle* handle = static_cast(proxy); + updateHandle(handle->m_uniqueId,aabbMin,aabbMax,dispatcher); + +} + + + + + +template +btAxisSweep3Internal::btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE maxHandles, btOverlappingPairCache* pairCache ) +:m_bpHandleMask(handleMask), +m_handleSentinel(handleSentinel), +m_pairCache(pairCache), +m_userPairCallback(0), +m_ownsPairCache(false), +m_invalidPair(0) +{ + if (!m_pairCache) + { + void* ptr = btAlignedAlloc(sizeof(btOverlappingPairCache),16); + m_pairCache = new(ptr) btOverlappingPairCache(); + m_ownsPairCache = true; + } + + //assert(bounds.HasVolume()); + + // init bounds + m_worldAabbMin = worldAabbMin; + m_worldAabbMax = worldAabbMax; + + btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; + + BP_FP_INT_TYPE maxInt = m_handleSentinel; + + m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; + + // allocate handles buffer and put all handles on free list + void* ptr = btAlignedAlloc(sizeof(Handle)*maxHandles,16); + m_pHandles = new(ptr) Handle[maxHandles]; + m_maxHandles = maxHandles; + m_numHandles = 0; + + // handle 0 is reserved as the null index, and is also used as the sentinel + m_firstFreeHandle = 1; + { + for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) + m_pHandles[i].SetNextFree(i + 1); + m_pHandles[maxHandles - 1].SetNextFree(0); + } + + { + // allocate edge buffers + for (int i = 0; i < 3; i++) + { + void* ptr = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16); + m_pEdges[i] = new(ptr) Edge[maxHandles * 2]; + } + } + //removed overlap management + + // make boundary sentinels + + m_pHandles[0].m_clientObject = 0; + + for (int axis = 0; axis < 3; axis++) + { + m_pHandles[0].m_minEdges[axis] = 0; + m_pHandles[0].m_maxEdges[axis] = 1; + + m_pEdges[axis][0].m_pos = 0; + m_pEdges[axis][0].m_handle = 0; + m_pEdges[axis][1].m_pos = m_handleSentinel; + m_pEdges[axis][1].m_handle = 0; +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + + } + +} + +template +btAxisSweep3Internal::~btAxisSweep3Internal() +{ + + for (int i = 2; i >= 0; i--) + { + btAlignedFree(m_pEdges[i]); + } + btAlignedFree(m_pHandles); + + if (m_ownsPairCache) + { + m_pairCache->~btOverlappingPairCache(); + btAlignedFree(m_pairCache); + } +} + +template +void btAxisSweep3Internal::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const +{ + btPoint3 clampedPoint(point); + + + + clampedPoint.setMax(m_worldAabbMin); + clampedPoint.setMin(m_worldAabbMax); + + btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; + out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax); + out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax); + out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax); + +} + + +template +BP_FP_INT_TYPE btAxisSweep3Internal::allocHandle() +{ + assert(m_firstFreeHandle); + + BP_FP_INT_TYPE handle = m_firstFreeHandle; + m_firstFreeHandle = getHandle(handle)->GetNextFree(); + m_numHandles++; + + return handle; +} + +template +void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle) +{ + assert(handle > 0 && handle < m_maxHandles); + + getHandle(handle)->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + m_numHandles--; +} + + +template +BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher) +{ + // quantize the bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // allocate a handle + BP_FP_INT_TYPE handle = allocHandle(); + + + Handle* pHandle = getHandle(handle); + + pHandle->m_uniqueId = handle; + //pHandle->m_pOverlaps = 0; + pHandle->m_clientObject = pOwner; + pHandle->m_collisionFilterGroup = collisionFilterGroup; + pHandle->m_collisionFilterMask = collisionFilterMask; + + // compute current limit of edge arrays + BP_FP_INT_TYPE limit = m_numHandles * 2; + + + // insert new edges just inside the max boundary edge + for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) + { + + m_pHandles[0].m_maxEdges[axis] += 2; + + m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; + + m_pEdges[axis][limit - 1].m_pos = min[axis]; + m_pEdges[axis][limit - 1].m_handle = handle; + + m_pEdges[axis][limit].m_pos = max[axis]; + m_pEdges[axis][limit].m_handle = handle; + + pHandle->m_minEdges[axis] = limit - 1; + pHandle->m_maxEdges[axis] = limit; + } + + // now sort the new edges to their correct position + sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false); + sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false); + sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false); + sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false); + sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true); + sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true); + + + return handle; +} + + +template +void btAxisSweep3Internal::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher) +{ + + Handle* pHandle = getHandle(handle); + + //explicitly remove the pairs containing the proxy + //we could do it also in the sortMinUp (passing true) + //todo: compare performance + m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher); + + + // compute current limit of edge arrays + int limit = m_numHandles * 2; + + int axis; + + for (axis = 0;axis<3;axis++) + { + m_pHandles[0].m_maxEdges[axis] -= 2; + } + + // remove the edges by sorting them up to the end of the list + for ( axis = 0; axis < 3; axis++) + { + Edge* pEdges = m_pEdges[axis]; + BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; + pEdges[max].m_pos = m_handleSentinel; + + sortMaxUp(axis,max,dispatcher,false); + + + BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; + pEdges[i].m_pos = m_handleSentinel; + + + sortMinUp(axis,i,dispatcher,false); + + pEdges[limit-1].m_handle = 0; + pEdges[limit-1].m_pos = m_handleSentinel; + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis,false); +#endif //DEBUG_BROADPHASE + + + } + + + // free the handle + freeHandle(handle); + + +} + +extern int gOverlappingPairs; +#include + +template +void btAxisSweep3Internal::calculateOverlappingPairs(btDispatcher* dispatcher) +{ +#ifdef USE_LAZY_REMOVAL + + if (m_ownsPairCache) + { + + btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_pairCache->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: + #define CLEAN_INVALID_PAIRS 1 + #ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + #endif//CLEAN_INVALID_PAIRS + + //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); + } +#endif //USE_LAZY_REMOVAL + + + + +} + + +template +bool btAxisSweep3Internal::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + const Handle* pHandleA = static_cast(proxy0); + const Handle* pHandleB = static_cast(proxy1); + + //optimization 1: check the array index (memory address), instead of the m_pos + + for (int axis = 0; axis < 3; axis++) + { + if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || + pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) + { + return false; + } + } + return true; +} + +template +bool btAxisSweep3Internal::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB) +{ + //optimization 1: check the array index (memory address), instead of the m_pos + + for (int axis = 0; axis < 3; axis++) + { + if (axis != ignoreAxis) + { + if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || + pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) + { + return false; + } + } + } + + //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization) + + /*for (int axis = 0; axis < 3; axis++) + { + if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos || + m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos) + { + return false; + } + } + */ + + return true; +} + +template +void btAxisSweep3Internal::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher) +{ +// assert(bounds.IsFinite()); + //assert(bounds.HasVolume()); + + Handle* pHandle = getHandle(handle); + + // quantize the new bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // update changed edges + for (int axis = 0; axis < 3; axis++) + { + BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; + BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; + + int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; + int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; + + m_pEdges[axis][emin].m_pos = min[axis]; + m_pEdges[axis][emax].m_pos = max[axis]; + + // expand (only adds overlaps) + if (dmin < 0) + sortMinDown(axis, emin,dispatcher,true); + + if (dmax > 0) + sortMaxUp(axis, emax,dispatcher,true); + + // shrink (only removes overlaps) + if (dmin > 0) + sortMinUp(axis, emin,dispatcher,true); + + if (dmax < 0) + sortMaxDown(axis, emax,dispatcher,true); + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + } + + +} + + + + +// sorting a min edge downwards can only ever *add* overlaps +template +void btAxisSweep3Internal::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (pPrev->IsMax()) + { + // if previous edge is a maximum check the bounds and add an overlap if necessary + if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev)) + { + m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev); + if (m_userPairCallback) + m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev); + + //AddOverlap(pEdge->m_handle, pPrev->m_handle); + + } + + // update edge reference in other handle + pHandlePrev->m_maxEdges[axis]++; + } + else + pHandlePrev->m_minEdges[axis]++; + + pHandleEdge->m_minEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a min edge upwards can only ever *remove* overlaps +template +void btAxisSweep3Internal::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + if (pNext->IsMax()) + { +#ifndef USE_LAZY_REMOVAL + // if next edge is maximum remove any overlap between the two handles + if (updateOverlaps) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); + if (m_userPairCallback) + m_userPairCallback->removeOverlappingPair(handle0,handle1); + + } +#endif //USE_LAZY_REMOVAL + + // update edge reference in other handle + pHandleNext->m_maxEdges[axis]--; + } + else + pHandleNext->m_minEdges[axis]--; + + pHandleEdge->m_minEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + + +} + +// sorting a max edge downwards can only ever *remove* overlaps +template +void btAxisSweep3Internal::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (!pPrev->IsMax()) + { + // if previous edge was a minimum remove any overlap between the two handles + if (updateOverlaps) + { + //this is done during the overlappingpairarray iteration/narrowphase collision +#ifndef USE_LAZY_REMOVAL + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pPrev->m_handle); + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); + if (m_userPairCallback) + m_userPairCallback->removeOverlappingPair(handle0,handle1); + +#endif //USE_LAZY_REMOVAL + + } + + // update edge reference in other handle + pHandlePrev->m_minEdges[axis]++;; + } + else + pHandlePrev->m_maxEdges[axis]++; + + pHandleEdge->m_maxEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a max edge upwards can only ever *add* overlaps +template +void btAxisSweep3Internal::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + if (!pNext->IsMax()) + { + // if next edge is a minimum check the bounds and add an overlap if necessary + if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext)) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + m_pairCache->addOverlappingPair(handle0,handle1); + if (m_userPairCallback) + m_userPairCallback->addOverlappingPair(handle0,handle1); + } + + // update edge reference in other handle + pHandleNext->m_minEdges[axis]--; + } + else + pHandleNext->m_maxEdges[axis]--; + + pHandleEdge->m_maxEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + +} + + + +//////////////////////////////////////////////////////////////////// + + +/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. +/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats. +/// For large worlds and many objects, use bt32BitAxisSweep3 instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance. +class btAxisSweep3 : public btAxisSweep3Internal +{ +public: + + btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0); + +}; + +/// bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune. +/// This comes at the cost of more memory per handle, and a bit slower performance. +/// It uses arrays rather then lists for storage of the 3 axis. +class bt32BitAxisSweep3 : public btAxisSweep3Internal +{ +public: + + bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0); }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h index b6ace03c07a..97ba20743d2 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h @@ -20,8 +20,10 @@ subject to the following restrictions: struct btDispatcherInfo; class btDispatcher; -struct btBroadphaseProxy; -#include "../../LinearMath/btVector3.h" +#include "btBroadphaseProxy.h" +class btOverlappingPairCache; + +#include "LinearMath/btVector3.h" ///BroadphaseInterface for aabb-overlapping object pairs class btBroadphaseInterface @@ -29,11 +31,15 @@ class btBroadphaseInterface public: virtual ~btBroadphaseInterface() {} - virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) =0; - virtual void destroyProxy(btBroadphaseProxy* proxy)=0; - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)=0; - virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy)=0; + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher) =0; + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0; + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0; + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb + virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0; + + virtual btOverlappingPairCache* getOverlappingPairCache()=0; + virtual const btOverlappingPairCache* getOverlappingPairCache() const =0; }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h index 40d9748ffa9..f0a462cce02 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -16,7 +16,8 @@ subject to the following restrictions: #ifndef BROADPHASE_PROXY_H #define BROADPHASE_PROXY_H -#include "../../LinearMath/btScalar.h" //for SIMD_FORCE_INLINE +#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE +#include "LinearMath/btAlignedAllocator.h" /// btDispatcher uses these types @@ -38,6 +39,7 @@ IMPLICIT_CONVEX_SHAPES_START_HERE, CONE_SHAPE_PROXYTYPE, CONVEX_SHAPE_PROXYTYPE, CYLINDER_SHAPE_PROXYTYPE, + UNIFORM_SCALING_SHAPE_PROXYTYPE, MINKOWSKI_SUM_SHAPE_PROXYTYPE, MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, //concave shapes @@ -62,8 +64,10 @@ CONCAVE_SHAPES_END_HERE, ///btBroadphaseProxy -struct btBroadphaseProxy +ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy { + +BT_DECLARE_ALIGNED_ALLOCATOR(); ///optional filtering to cull potential collisions enum CollisionFilterGroups @@ -78,8 +82,27 @@ struct btBroadphaseProxy //Usually the client btCollisionObject or Rigidbody class void* m_clientObject; - short int m_collisionFilterGroup; - short int m_collisionFilterMask; + + ///in the case of btMultiSapBroadphase, we store the collifionFilterGroup/Mask in the m_multiSapParentProxy + union + { + struct + { + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + }; + + void* m_multiSapParentProxy; + + }; + + int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc. + int m_unusedPadding; //making the structure 16 bytes, better for alignment etc. + + SIMD_FORCE_INLINE int getUid() + { + return m_uniqueId;//(int)this; + } //used for memory pools btBroadphaseProxy() :m_clientObject(0){} @@ -91,26 +114,28 @@ struct btBroadphaseProxy { } - static inline bool isPolyhedral(int proxyType) + + + static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType) { return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE); } - static inline bool isConvex(int proxyType) + static SIMD_FORCE_INLINE bool isConvex(int proxyType) { return (proxyType < CONCAVE_SHAPES_START_HERE); } - static inline bool isConcave(int proxyType) + static SIMD_FORCE_INLINE bool isConcave(int proxyType) { return ((proxyType > CONCAVE_SHAPES_START_HERE) && (proxyType < CONCAVE_SHAPES_END_HERE)); } - static inline bool isCompound(int proxyType) + static SIMD_FORCE_INLINE bool isCompound(int proxyType) { return (proxyType == COMPOUND_SHAPE_PROXYTYPE); } - static inline bool isInfinite(int proxyType) + static SIMD_FORCE_INLINE bool isInfinite(int proxyType) { return (proxyType == STATIC_PLANE_PROXYTYPE); } @@ -125,7 +150,7 @@ struct btBroadphaseProxy; /// contains a pair of aabb-overlapping objects -struct btBroadphasePair +ATTRIBUTE_ALIGNED16(struct) btBroadphasePair { btBroadphasePair () : @@ -136,6 +161,8 @@ struct btBroadphasePair { } +BT_DECLARE_ALIGNED_ALLOCATOR(); + btBroadphasePair(const btBroadphasePair& other) : m_pProxy0(other.m_pProxy0), m_pProxy1(other.m_pProxy1), @@ -181,6 +208,7 @@ SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePa */ + class btBroadphasePairSortPredicate { public: diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp index 2ad0c86d8a2..c95d1be0f2c 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp @@ -18,6 +18,6 @@ subject to the following restrictions: btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) { - m_dispatcher = ci.m_dispatcher; + m_dispatcher = ci.m_dispatcher1; } diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h index 55cec386a7b..610eab4ce5e 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef COLLISION_ALGORITHM_H #define COLLISION_ALGORITHM_H -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" struct btBroadphaseProxy; class btDispatcher; @@ -29,17 +29,17 @@ class btPersistentManifold; struct btCollisionAlgorithmConstructionInfo { btCollisionAlgorithmConstructionInfo() - :m_dispatcher(0), + :m_dispatcher1(0), m_manifold(0) { } btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp) - :m_dispatcher(dispatcher) + :m_dispatcher1(dispatcher) { (void)temp; } - btDispatcher* m_dispatcher; + btDispatcher* m_dispatcher1; btPersistentManifold* m_manifold; int getDispatcherId(); diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h index 3d958cc8fef..daea11f7788 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef _DISPATCHER_H #define _DISPATCHER_H -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" class btCollisionAlgorithm; struct btBroadphaseProxy; @@ -81,12 +81,18 @@ public: virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0; - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)=0; + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)=0; virtual int getNumManifolds() const = 0; virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0; + virtual btPersistentManifold** getInternalManifoldPointer() = 0; + + virtual void* allocateCollisionAlgorithm(int size) = 0; + + virtual void freeCollisionAlgorithm(void* ptr) = 0; + }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp new file mode 100644 index 00000000000..41406ff49f9 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp @@ -0,0 +1,204 @@ +/* +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. +*/ + +#include "btMultiSapBroadphase.h" + +#include "btSimpleBroadphase.h" +#include "LinearMath/btAabbUtil2.h" + +/// btSapBroadphaseArray m_sapBroadphases; + +/// btOverlappingPairCache* m_overlappingPairs; +extern int gOverlappingPairs; + +btMultiSapBroadphase::btMultiSapBroadphase(int maxProxies,btOverlappingPairCache* pairCache) +:m_overlappingPairs(pairCache), +m_ownsPairCache(false), +m_invalidPair(0) +{ + if (!m_overlappingPairs) + { + m_ownsPairCache = true; + void* mem = btAlignedAlloc(sizeof(btOverlappingPairCache),16); + m_overlappingPairs = new (mem)btOverlappingPairCache(); + } + + struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback + { + virtual ~btMultiSapOverlapFilterCallback() + {} + // return true when pairs need collision + virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const + { + btMultiSapBroadphase::btMultiSapProxy* multiSapProxy0 = (btMultiSapBroadphase::btMultiSapProxy*)childProxy0->m_multiSapParentProxy; + btMultiSapBroadphase::btMultiSapProxy* multiSapProxy1 = (btMultiSapBroadphase::btMultiSapProxy*)childProxy1->m_multiSapParentProxy; + + bool collides = (multiSapProxy0->m_collisionFilterGroup & multiSapProxy1->m_collisionFilterMask) != 0; + collides = collides && (multiSapProxy1->m_collisionFilterGroup & multiSapProxy0->m_collisionFilterMask); + + return collides; + } + }; + + void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16); + m_filterCallback = new (mem)btMultiSapOverlapFilterCallback(); + + m_overlappingPairs->setOverlapFilterCallback(m_filterCallback); + mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16); + m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs); +} + +btMultiSapBroadphase::~btMultiSapBroadphase() +{ + if (m_ownsPairCache) + { + btAlignedFree(m_overlappingPairs); + } +} + +btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher) +{ + void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16); + btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask); + m_multiSapProxies.push_back(proxy); + + ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision + ///this is needed to be able to calculate the aabb overlap + btBroadphaseProxy* simpleProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask, dispatcher); + simpleProxy->m_multiSapParentProxy = proxy; + + mem = btAlignedAlloc(sizeof(btChildProxy),16); + btChildProxy* childProxyRef = new btChildProxy(); + childProxyRef->m_proxy = simpleProxy; + childProxyRef->m_childBroadphase = m_simpleBroadphase; + proxy->m_childProxies.push_back(childProxyRef); + + ///this should deal with inserting/removal into child broadphases + setAabb(proxy,aabbMin,aabbMax,dispatcher); + return proxy; +} + +void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + ///not yet + btAssert(0); + +} +void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) +{ + btMultiSapProxy* multiProxy = static_cast(proxy); + multiProxy->m_aabbMin = aabbMin; + multiProxy->m_aabbMax = aabbMax; + + for (int i=0;im_childProxies.size();i++) + { + btChildProxy* childProxyRef = multiProxy->m_childProxies[i]; + childProxyRef->m_childBroadphase->setAabb(childProxyRef->m_proxy,aabbMin,aabbMax,dispatcher); + } + +} + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb +void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + m_simpleBroadphase->calculateOverlappingPairs(dispatcher); + +#ifndef USE_HASH_PAIRCACHE + + btBroadphasePairArray& overlappingPairArray = m_overlappingPairs->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + int i; + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_overlappingPairs->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + +///if you don't like to skip the invalid pairs in the array, execute following code: +#define CLEAN_INVALID_PAIRS 1 +#ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; +#endif//CLEAN_INVALID_PAIRS + +#endif //USE_HASH_PAIRCACHE + +} + + +bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) +{ + btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy; + btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy; + + return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax, + multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax); + +} diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h new file mode 100644 index 00000000000..1ee609b8d1f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h @@ -0,0 +1,119 @@ +/* +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. +*/ +#ifndef BT_MULTI_SAP_BROADPHASE +#define BT_MULTI_SAP_BROADPHASE + +#include "btBroadphaseInterface.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "btOverlappingPairCache.h" + +class btAxisSweep3; +class btSimpleBroadphase; + + +typedef btAlignedObjectArray btSapBroadphaseArray; + +///multi SAP broadphase +///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328 +///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 +class btMultiSapBroadphase :public btBroadphaseInterface +{ + btSapBroadphaseArray m_sapBroadphases; + + btSimpleBroadphase* m_simpleBroadphase; + + btOverlappingPairCache* m_overlappingPairs; + + bool m_ownsPairCache; + + btOverlapFilterCallback* m_filterCallback; + + int m_invalidPair; + + struct btChildProxy + { + btBroadphaseProxy* m_proxy; + btBroadphaseInterface* m_childBroadphase; + }; + +public: + + struct btMultiSapProxy : public btBroadphaseProxy + { + + ///array with all the entries that this proxy belongs to + btAlignedObjectArray m_childProxies; + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + int m_shapeType; + void* m_userPtr; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + + btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) + :m_aabbMin(aabbMin), + m_aabbMax(aabbMax), + m_shapeType(shapeType), + m_userPtr(userPtr), + m_collisionFilterGroup(collisionFilterGroup), + m_collisionFilterMask(collisionFilterMask) + { + + } + + + }; + +protected: + + btAlignedObjectArray m_multiSapProxies; + +public: + + btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0); + + btSapBroadphaseArray getBroadphaseArray() + { + return m_sapBroadphases; + } + + const btSapBroadphaseArray getBroadphaseArray() const + { + return m_sapBroadphases; + } + + virtual ~btMultiSapBroadphase(); + + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + virtual btOverlappingPairCache* getOverlappingPairCache() + { + return m_overlappingPairs; + } + virtual const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_overlappingPairs; + } +}; + +#endif //BT_MULTI_SAP_BROADPHASE diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp index 60f0a41a9d7..e4ef043f064 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp @@ -23,11 +23,19 @@ subject to the following restrictions: int gOverlappingPairs = 0; +int gRemovePairs =0; +int gAddedPairs =0; +int gFindPairs =0; + btOverlappingPairCache::btOverlappingPairCache(): -m_blockedForChanges(false), -m_overlapFilterCallback(0) -//m_NumOverlapBroadphasePair(0) + m_overlapFilterCallback(0), + m_blockedForChanges(false) { + int initialAllocatedSize= 2; + m_overlappingPairArray.reserve(initialAllocatedSize); +#ifdef USE_HASH_PAIRCACHE + growTables(); +#endif //USE_HASH_PAIRCACHE } @@ -36,51 +44,373 @@ btOverlappingPairCache::~btOverlappingPairCache() //todo/test: show we erase/delete data, or is it automatic } - -void btOverlappingPairCache::removeOverlappingPair(btBroadphasePair& findPair) -{ - - int findIndex = m_overlappingPairArray.findLinearSearch(findPair); - if (findIndex < m_overlappingPairArray.size()) - { - gOverlappingPairs--; - btBroadphasePair& pair = m_overlappingPairArray[findIndex]; - cleanOverlappingPair(pair); - - m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.size()-1); - m_overlappingPairArray.pop_back(); - } -} - - -void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair) +void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) { if (pair.m_algorithm) { { - delete pair.m_algorithm;; + pair.m_algorithm->~btCollisionAlgorithm(); + dispatcher->freeCollisionAlgorithm(pair.m_algorithm); pair.m_algorithm=0; } } } +void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class CleanPairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_cleanProxy; + btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; + + public: + CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) + :m_cleanProxy(cleanProxy), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + if ((pair.m_pProxy0 == m_cleanProxy) || + (pair.m_pProxy1 == m_cleanProxy)) + { + m_pairCache->cleanOverlappingPair(pair,m_dispatcher); + } + return false; + } + + }; + + CleanPairCallback cleanPairs(proxy,this,dispatcher); + + processAllOverlappingPairs(&cleanPairs,dispatcher); + +} + +void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class RemovePairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_obsoleteProxy; + + public: + RemovePairCallback(btBroadphaseProxy* obsoleteProxy) + :m_obsoleteProxy(obsoleteProxy) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + return ((pair.m_pProxy0 == m_obsoleteProxy) || + (pair.m_pProxy1 == m_obsoleteProxy)); + } + + }; + + + RemovePairCallback removeCallback(proxy); + + processAllOverlappingPairs(&removeCallback,dispatcher); +} + + +#ifdef USE_HASH_PAIRCACHE -void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + + + + +btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) +{ + gFindPairs++; + + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2); + + int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1); + + int index = m_hashTable[hash]; + while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) + { + index = m_next[index]; + } + + if (index == BT_NULL_PAIR) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; +} + +#include + +void btOverlappingPairCache::growTables() +{ + + int newCapacity = m_overlappingPairArray.capacity(); + + if (m_hashTable.size() < newCapacity) + { + //grow hashtable and next table + int curHashtableSize = m_hashTable.size(); + + m_hashTable.resize(newCapacity); + m_next.resize(newCapacity); + + + int i; + + for (i= 0; i < newCapacity; ++i) + { + m_hashTable[i] = BT_NULL_PAIR; + } + for (i = 0; i < newCapacity; ++i) + { + m_next[i] = BT_NULL_PAIR; + } + + for(i=0;igetUid(); + int proxyId2 = pair.m_pProxy1->getUid(); + if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2); + int hashValue = getHash(proxyId1,proxyId2) & (m_overlappingPairArray.capacity()-1); // New hash value with new mask + m_next[i] = m_hashTable[hashValue]; + m_hashTable[hashValue] = i; + } + + + } +} + +btBroadphasePair* btOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) +{ + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2); + + int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1); + + + + btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); + if (pair != NULL) + { + return pair; + } + + int count = m_overlappingPairArray.size(); + int oldCapacity = m_overlappingPairArray.capacity(); + void* mem = &m_overlappingPairArray.expand(); + int newCapacity = m_overlappingPairArray.capacity(); + + if (oldCapacity < newCapacity) + { + growTables(); + //hash with new capacity + hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1); + } + + pair = new (mem) btBroadphasePair(*proxy0,*proxy1); +// pair->m_pProxy0 = proxy0; +// pair->m_pProxy1 = proxy1; + pair->m_algorithm = 0; + pair->m_userInfo = 0; + + + m_next[count] = m_hashTable[hash]; + m_hashTable[hash] = count; + + return pair; +} + + + +void* btOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher) +{ + gRemovePairs++; + + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2); + + int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1); + + btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); + if (pair == NULL) + { + return 0; + } + + cleanOverlappingPair(*pair,dispatcher); + + void* userData = pair->m_userInfo; + + btAssert(pair->m_pProxy0->getUid() == proxyId1); + btAssert(pair->m_pProxy1->getUid() == proxyId2); + + int pairIndex = int(pair - &m_overlappingPairArray[0]); + btAssert(pairIndex < m_overlappingPairArray.size()); + + // Remove the pair from the hash table. + int index = m_hashTable[hash]; + btAssert(index != BT_NULL_PAIR); + + int previous = BT_NULL_PAIR; + while (index != pairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_NULL_PAIR) + { + btAssert(m_next[previous] == pairIndex); + m_next[previous] = m_next[pairIndex]; + } + else + { + m_hashTable[hash] = m_next[pairIndex]; + } + + // We now move the last pair into spot of the + // pair being removed. We need to fix the hash + // table indices to support the move. + + int lastPairIndex = m_overlappingPairArray.size() - 1; + + // If the removed pair is the last pair, we are done. + if (lastPairIndex == pairIndex) + { + m_overlappingPairArray.pop_back(); + return userData; + } + + // Remove the last pair from the hash table. + const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex]; + int lastHash = getHash(last->m_pProxy0->getUid(), last->m_pProxy1->getUid()) & (m_overlappingPairArray.capacity()-1); + + index = m_hashTable[lastHash]; + btAssert(index != BT_NULL_PAIR); + + previous = BT_NULL_PAIR; + while (index != lastPairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_NULL_PAIR) + { + btAssert(m_next[previous] == lastPairIndex); + m_next[previous] = m_next[lastPairIndex]; + } + else + { + m_hashTable[lastHash] = m_next[lastPairIndex]; + } + + // Copy the last pair into the remove pair's spot. + m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex]; + + // Insert the last pair into the hash table + m_next[pairIndex] = m_hashTable[lastHash]; + m_hashTable[lastHash] = pairIndex; + + m_overlappingPairArray.pop_back(); + + return userData; +} +#include + +void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) +{ + + int i; + +// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size()); + for (i=0;iprocessOverlap(*pair)) + { + removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher); + + gOverlappingPairs--; + } else + { + i++; + } + } +} + +#else + + + + +void* btOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher ) +{ +#ifndef USE_LAZY_REMOVAL + + btBroadphasePair findPair(*proxy0,*proxy1); + + int findIndex = m_overlappingPairArray.findLinearSearch(findPair); + if (findIndex < m_overlappingPairArray.size()) + { + gOverlappingPairs--; + btBroadphasePair& pair = m_overlappingPairArray[findIndex]; + void* userData = pair.m_userInfo; + cleanOverlappingPair(pair,dispatcher); + + m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1); + m_overlappingPairArray.pop_back(); + return userData; + } +#endif //USE_LAZY_REMOVAL + + return 0; +} + + + + + + + + +btBroadphasePair* btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) { //don't add overlap with own assert(proxy0 != proxy1); if (!needsBroadphaseCollision(proxy0,proxy1)) - return; - - - btBroadphasePair pair(*proxy0,*proxy1); + return 0; - m_overlappingPairArray.push_back(pair); + void* mem = &m_overlappingPairArray.expand(); + btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1); gOverlappingPairs++; + return pair; } @@ -109,69 +439,14 @@ void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroa -void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy) -{ - - class CleanPairCallback : public btOverlapCallback - { - btBroadphaseProxy* m_cleanProxy; - btOverlappingPairCache* m_pairCache; - - public: - CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache) - :m_cleanProxy(cleanProxy), - m_pairCache(pairCache) - { - } - virtual bool processOverlap(btBroadphasePair& pair) - { - if ((pair.m_pProxy0 == m_cleanProxy) || - (pair.m_pProxy1 == m_cleanProxy)) - { - m_pairCache->cleanOverlappingPair(pair); - } - return false; - } - - }; - - CleanPairCallback cleanPairs(proxy,this); - - processAllOverlappingPairs(&cleanPairs); - -} -void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy) -{ - - class RemovePairCallback : public btOverlapCallback - { - btBroadphaseProxy* m_obsoleteProxy; - - public: - RemovePairCallback(btBroadphaseProxy* obsoleteProxy) - :m_obsoleteProxy(obsoleteProxy) - { - } - virtual bool processOverlap(btBroadphasePair& pair) - { - return ((pair.m_pProxy0 == m_obsoleteProxy) || - (pair.m_pProxy1 == m_obsoleteProxy)); - } - - }; - RemovePairCallback removeCallback(proxy); +#include - processAllOverlappingPairs(&removeCallback); -} - - - -void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback) +void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) { int i; @@ -182,9 +457,9 @@ void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callb btBroadphasePair* pair = &m_overlappingPairArray[i]; if (callback->processOverlap(*pair)) { - cleanOverlappingPair(*pair); + cleanOverlappingPair(*pair,dispatcher); - m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1); m_overlappingPairArray.pop_back(); gOverlappingPairs--; } else @@ -194,3 +469,6 @@ void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callb } } + + +#endif //USE_HASH_PAIRCACHE diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h index a81fe3264df..a387505d1be 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -20,8 +20,12 @@ subject to the following restrictions: #include "btBroadphaseInterface.h" #include "btBroadphaseProxy.h" -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btAlignedObjectArray.h" +class btDispatcher; + +///disable the USE_HASH_PAIRCACHE define to use a pair manager that sorts the pairs to find duplicates/non-overlap +#define USE_HASH_PAIRCACHE 1 struct btOverlapCallback @@ -40,38 +44,226 @@ struct btOverlapFilterCallback virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; }; +typedef btAlignedObjectArray btBroadphasePairArray; + +#ifdef USE_HASH_PAIRCACHE + + +/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com + +extern int gRemovePairs; +extern int gAddedPairs; +extern int gFindPairs; + +const int BT_NULL_PAIR=0xffffffff; + +class btOverlappingPairCache +{ + btBroadphasePairArray m_overlappingPairArray; + btOverlapFilterCallback* m_overlapFilterCallback; + bool m_blockedForChanges; + + +public: + btOverlappingPairCache(); + virtual ~btOverlappingPairCache(); + + + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); + + SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const + { + if (m_overlapFilterCallback) + return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); + + bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; + collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + + return collides; + } + + // Add a pair and return the new pair. If the pair already exists, + // no new pair is created and the old one is returned. + SIMD_FORCE_INLINE btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + gAddedPairs++; + + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + return internalAddPair(proxy0,proxy1); + } + + + + void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); + + btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + const btBroadphasePairArray& getOverlappingPairArray() const + { + return m_overlappingPairArray; + } + + void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); + + + + btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1); + + int GetCount() const { return m_overlappingPairArray.size(); } +// btBroadphasePair* GetPairs() { return m_pairs; } + + btOverlapFilterCallback* getOverlapFilterCallback() + { + return m_overlapFilterCallback; + } + + void setOverlapFilterCallback(btOverlapFilterCallback* callback) + { + m_overlapFilterCallback = callback; + } + + int getNumOverlappingPairs() const + { + return m_overlappingPairArray.size(); + } +private: + + btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + void growTables(); + + SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2) + { + return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2; + } + + /* + // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm + // This assumes proxyId1 and proxyId2 are 16-bit. + SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2) + { + int key = (proxyId2 << 16) | proxyId1; + key = ~key + (key << 15); + key = key ^ (key >> 12); + key = key + (key << 2); + key = key ^ (key >> 4); + key = key * 2057; + key = key ^ (key >> 16); + return key; + } + */ + + + + SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2) + { + int key = ((unsigned int)proxyId1) | (((unsigned int)proxyId1) <<16); + // Thomas Wang's hash + + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; + } + + + + + + SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash) + { + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2); + + int index = m_hashTable[hash]; + + while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) + { + index = m_next[index]; + } + + if ( index == BT_NULL_PAIR ) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; + } + + +public: + + btAlignedObjectArray m_hashTable; + btAlignedObjectArray m_next; + +}; + + + +#else//USE_HASH_PAIRCACHE + +#define USE_LAZY_REMOVAL 1 + ///btOverlappingPairCache maintains the objects with overlapping AABB ///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase -class btOverlappingPairCache : public btBroadphaseInterface +class btOverlappingPairCache { protected: //avoid brute-force finding all the time - btAlignedObjectArray m_overlappingPairArray; - + btBroadphasePairArray m_overlappingPairArray; + //during the dispatch, check that user doesn't destroy/create proxy bool m_blockedForChanges; //if set, use the callback instead of the built in filter in needBroadphaseCollision btOverlapFilterCallback* m_overlapFilterCallback; + public: btOverlappingPairCache(); virtual ~btOverlappingPairCache(); - virtual void processAllOverlappingPairs(btOverlapCallback*); + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); - void removeOverlappingPair(btBroadphasePair& pair); + void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); - void cleanOverlappingPair(btBroadphasePair& pair); + void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); - void addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - void cleanProxyFromPairs(btBroadphaseProxy* proxy); + void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy); + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const @@ -84,10 +276,19 @@ class btOverlappingPairCache : public btBroadphaseInterface return collides; } - + + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + const btBroadphasePairArray& getOverlappingPairArray() const + { + return m_overlappingPairArray; + } + - virtual void refreshOverlappingPairs() =0; btBroadphasePair* getOverlappingPairArrayPtr() { @@ -115,6 +316,8 @@ class btOverlappingPairCache : public btBroadphaseInterface } }; +#endif //USE_HASH_PAIRCACHE + #endif //OVERLAPPING_PAIR_CACHE_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h new file mode 100644 index 00000000000..b8d967dc4b2 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h @@ -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. +*/ + +#ifndef OVERLAPPING_PAIR_CALLBACK_H +#define OVERLAPPING_PAIR_CALLBACK_H + +///btOverlappingPairCallback provides user callback to keep track of overlap between objects, like a collision sensor +class btOverlappingPairCallback +{ +public: + virtual ~btOverlappingPairCallback() + { + + } + + virtual void addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0; + + virtual void removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0; + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0) = 0; + +}; + +#endif //OVERLAPPING_PAIR_CALLBACK_H \ No newline at end of file diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp index 30bcbe0c5f1..e0bb0992933 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp @@ -22,75 +22,78 @@ subject to the following restrictions: #include "LinearMath/btMatrix3x3.h" #include +extern int gOverlappingPairs; void btSimpleBroadphase::validate() { - for (int i=0;i=0;i--) + if (m_ownsPairCache) { - BP_Proxy* proxy = m_pProxies[i]; - destroyProxy(proxy); + m_pairCache->~btOverlappingPairCache(); + btAlignedFree(m_pairCache); } - */ } -btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask) +btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher) { - if (m_numProxies >= m_maxProxies) + if (m_numHandles >= m_maxHandles) { - assert(0); + btAssert(0); return 0; //should never happen, but don't let the game crash ;-) } - assert(min[0]<= max[0] && min[1]<= max[1] && min[2]<= max[2]); + assert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]); - int freeIndex= m_freeProxies[m_firstFreeProxy]; - btSimpleBroadphaseProxy* proxy = new (&m_proxies[freeIndex])btSimpleBroadphaseProxy(min,max,shapeType,userPtr,collisionFilterGroup,collisionFilterMask); - m_firstFreeProxy++; - - btSimpleBroadphaseProxy* proxy1 = &m_proxies[0]; - - int index = int(proxy - proxy1); - btAssert(index == freeIndex); - - m_pProxies[m_numProxies] = proxy; - m_numProxies++; - //validate(); + int newHandleIndex = allocHandle(); + btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask); return proxy; } @@ -124,34 +127,19 @@ protected: }; }; -void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg) +void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher) { - int i; - btSimpleBroadphaseProxy* proxy0 = static_cast(proxyOrg); - btSimpleBroadphaseProxy* proxy1 = &m_proxies[0]; - - int index = int(proxy0 - proxy1); - btAssert (index < m_maxProxies); - m_freeProxies[--m_firstFreeProxy] = index; + freeHandle(proxy0); + + m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher); - removeOverlappingPairsContainingProxy(proxyOrg); - - for (i=0;im_min = aabbMin; @@ -186,37 +174,139 @@ public: } }; -void btSimpleBroadphase::refreshOverlappingPairs() +void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) { //first check for new overlapping pairs int i,j; - for (i=0;i= 0) { - btBroadphaseProxy* proxy0 = m_pProxies[i]; - for (j=i+1;jfindPair(proxy0,proxy1)) + { + m_pairCache->addOverlappingPair(proxy0,proxy1); + } + } else + { + #ifdef USE_HASH_PAIRCACHE + if ( m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); + } + #endif //USE_HASH_PAIRCACHE + + } } + proxy1 = &m_pHandles[proxy1->GetNextAllocated()]; + } + proxy0 = &m_pHandles[proxy0->GetNextAllocated()]; } + + #ifndef USE_HASH_PAIRCACHE + + if (m_ownsPairCache) + { + + btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_pairCache->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: + #define CLEAN_INVALID_PAIRS 1 + #ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + #endif//CLEAN_INVALID_PAIRS + + } + #endif //USE_HASH_PAIRCACHE } - - - CheckOverlapCallback checkOverlap; - - processAllOverlappingPairs(&checkOverlap); - - } +bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); + btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); + return aabbOverlap(p0,p1); +} + + + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h index fb155e7047c..09367a79d2b 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h @@ -24,6 +24,10 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy { btVector3 m_min; btVector3 m_max; + int m_nextFree; + int m_nextAllocated; +// int m_handleId; + btSimpleBroadphaseProxy() {}; @@ -34,25 +38,64 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy (void)shapeType; } + + SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;} + SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;} + + SIMD_FORCE_INLINE void SetNextAllocated(int next) {m_nextAllocated = next;} + SIMD_FORCE_INLINE int GetNextAllocated() const {return m_nextAllocated;} + }; ///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks -class btSimpleBroadphase : public btOverlappingPairCache +///btSimpleBroadphase is just a unit-test implementation to verify and test other broadphases. +///So please don't use this class, but use bt32BitAxisSweep3 or btAxisSweep3 instead! +class btSimpleBroadphase : public btBroadphaseInterface { protected: - btSimpleBroadphaseProxy* m_proxies; - int* m_freeProxies; - int m_firstFreeProxy; + int m_numHandles; // number of active handles + int m_maxHandles; // max number of handles + btSimpleBroadphaseProxy* m_pHandles; // handles pool + int m_firstFreeHandle; // free handles list + int m_firstAllocatedHandle; - btSimpleBroadphaseProxy** m_pProxies; - int m_numProxies; + int allocHandle() + { - + int freeHandle = m_firstFreeHandle; + m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree(); + + m_pHandles[freeHandle].SetNextAllocated(m_firstAllocatedHandle); + m_firstAllocatedHandle = freeHandle; + + m_numHandles++; + + return freeHandle; + } + + void freeHandle(btSimpleBroadphaseProxy* proxy) + { + int handle = int(proxy-m_pHandles); + btAssert(handle >= 0 && handle < m_maxHandles); + + proxy->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + m_firstAllocatedHandle = proxy->GetNextAllocated(); + proxy->SetNextAllocated(-1); + + m_numHandles--; + } + + + btOverlappingPairCache* m_pairCache; + bool m_ownsPairCache; + + int m_invalidPair; - int m_maxProxies; inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) @@ -67,24 +110,33 @@ protected: protected: - virtual void refreshOverlappingPairs(); + + public: - btSimpleBroadphase(int maxProxies=16384); + btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0); virtual ~btSimpleBroadphase(); static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1); - virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask); + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher); + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - virtual void destroyProxy(btBroadphaseProxy* proxy); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); - - + btOverlappingPairCache* getOverlappingPairCache() + { + return m_pairCache; + } + const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_pairCache; + } + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); }; diff --git a/extern/bullet2/src/BulletCollision/CMakeLists.txt b/extern/bullet2/src/BulletCollision/CMakeLists.txt index e565bf7edea..d2d3dc6fabf 100644 --- a/extern/bullet2/src/BulletCollision/CMakeLists.txt +++ b/extern/bullet2/src/BulletCollision/CMakeLists.txt @@ -8,6 +8,7 @@ ADD_LIBRARY(LibBulletCollision BroadphaseCollision/btBroadphaseProxy.cpp BroadphaseCollision/btCollisionAlgorithm.cpp BroadphaseCollision/btDispatcher.cpp + BroadphaseCollision/btMultiSapBroadphase.cpp BroadphaseCollision/btOverlappingPairCache.cpp BroadphaseCollision/btSimpleBroadphase.cpp CollisionDispatch/btCollisionDispatcher.cpp @@ -15,24 +16,30 @@ ADD_LIBRARY(LibBulletCollision CollisionDispatch/btCollisionWorld.cpp CollisionDispatch/btCompoundCollisionAlgorithm.cpp CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp + CollisionDispatch/btDefaultCollisionConfiguration.cpp CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp + CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp CollisionDispatch/btConvexConvexAlgorithm.cpp CollisionDispatch/btEmptyCollisionAlgorithm.cpp CollisionDispatch/btManifoldResult.cpp CollisionDispatch/btSimulationIslandManager.cpp CollisionDispatch/btUnionFind.cpp + CollisionDispatch/SphereTriangleDetector.cpp CollisionShapes/btBoxShape.cpp CollisionShapes/btBvhTriangleMeshShape.cpp + CollisionShapes/btCapsuleShape.cpp CollisionShapes/btCollisionShape.cpp CollisionShapes/btCompoundShape.cpp CollisionShapes/btConcaveShape.cpp CollisionShapes/btConeShape.cpp CollisionShapes/btConvexHullShape.cpp CollisionShapes/btConvexShape.cpp + CollisionShapes/btConvexInternalShape.cpp CollisionShapes/btConvexTriangleMeshShape.cpp CollisionShapes/btCylinderShape.cpp CollisionShapes/btEmptyShape.cpp + CollisionShapes/btHeightfieldTerrainShape.cpp CollisionShapes/btMinkowskiSumShape.cpp CollisionShapes/btMultiSphereShape.cpp CollisionShapes/btOptimizedBvh.cpp @@ -46,6 +53,7 @@ ADD_LIBRARY(LibBulletCollision CollisionShapes/btTriangleIndexVertexArray.cpp CollisionShapes/btTriangleMesh.cpp CollisionShapes/btTriangleMeshShape.cpp + CollisionShapes/btUniformScalingShape.cpp NarrowPhaseCollision/btContinuousConvexCollision.cpp NarrowPhaseCollision/btGjkEpa.cpp NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h index b32806a6846..0c817b221c8 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef SPHERE_TRIANGLE_DETECTOR_H #define SPHERE_TRIANGLE_DETECTOR_H -#include "../NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" -#include "../../LinearMath/btPoint3.h" +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "LinearMath/btPoint3.h" class btSphereShape; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h new file mode 100644 index 00000000000..fad770ac26d --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h @@ -0,0 +1,47 @@ +/* +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. +*/ + +#ifndef BT_COLLISION_CONFIGURATION +#define BT_COLLISION_CONFIGURATION +struct btCollisionAlgorithmCreateFunc; + +class btStackAlloc; +class btPoolAllocator; + +///btCollisionConfiguration allows to configure Bullet collision detection +///stack allocator size, default collision algorithms and persistent manifold pool size +///todo: describe the meaning +class btCollisionConfiguration +{ + +public: + + virtual ~btCollisionConfiguration() + { + } + + ///memory pools + virtual btPoolAllocator* getPersistentManifoldPool() = 0; + + virtual btPoolAllocator* getCollisionAlgorithmPool() = 0; + + virtual btStackAlloc* getStackAllocator() = 0; + + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0; + +}; + +#endif //BT_COLLISION_CONFIGURATION + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h index d51a59af7f0..c6728918d16 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef COLLISION_CREATE_FUNC #define COLLISION_CREATE_FUNC -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" typedef btAlignedObjectArray btCollisionObjectArray; class btCollisionAlgorithm; class btCollisionObject; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp index b535fac6563..644caf2677b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @@ -19,69 +19,37 @@ subject to the following restrictions: #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" + #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "LinearMath/btPoolAllocator.h" +#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" int gNumManifold = 0; #include - -btCollisionDispatcher::btCollisionDispatcher(bool noDefaultAlgorithms): -m_count(0), -m_useIslands(true), -m_convexConvexCreateFunc(0), -m_convexConcaveCreateFunc(0), -m_swappedConvexConcaveCreateFunc(0), -m_compoundCreateFunc(0), -m_swappedCompoundCreateFunc(0), -m_emptyCreateFunc(0) -{ - (void)noDefaultAlgorithms; - int i; - setNearCallback(defaultNearCallback); - m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc; - for (i=0;igetCollisionAlgorithmPool(); + + m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool(); for (i=0;igetCollisionAlgorithmCreateFunc(i,j); assert(m_doubleDispatch[i][j]); } } @@ -89,8 +57,6 @@ btCollisionDispatcher::btCollisionDispatcher (): }; -#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION - void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc) { @@ -99,12 +65,6 @@ void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int prox btCollisionDispatcher::~btCollisionDispatcher() { - delete m_convexConvexCreateFunc; - delete m_convexConcaveCreateFunc; - delete m_swappedConvexConcaveCreateFunc; - delete m_compoundCreateFunc; - delete m_swappedCompoundCreateFunc; - delete m_emptyCreateFunc; } btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) @@ -117,7 +77,18 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) btCollisionObject* body0 = (btCollisionObject*)b0; btCollisionObject* body1 = (btCollisionObject*)b1; - btPersistentManifold* manifold = new btPersistentManifold (body0,body1); + void* mem = 0; + + if (m_persistentManifoldPoolAllocator->getFreeCount()) + { + mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold)); + } else + { + mem = btAlignedAlloc(sizeof(btPersistentManifold),16); + + } + btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0); + manifold->m_index1a = m_manifoldsPtr.size(); m_manifoldsPtr.push_back(manifold); return manifold; @@ -137,13 +108,19 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) //printf("releaseManifold: gNumManifold %d\n",gNumManifold); clearManifold(manifold); - ///todo: this can be improved a lot, linear search might be slow part! - int findIndex = m_manifoldsPtr.findLinearSearch(manifold); - if (findIndex < m_manifoldsPtr.size()) + int findIndex = manifold->m_index1a; + btAssert(findIndex < m_manifoldsPtr.size()); + m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); + m_manifoldsPtr[findIndex]->m_index1a = findIndex; + m_manifoldsPtr.pop_back(); + + manifold->~btPersistentManifold(); + if (m_persistentManifoldPoolAllocator->validPtr(manifold)) { - m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); - m_manifoldsPtr.pop_back(); - delete manifold; + m_persistentManifoldPoolAllocator->free(manifold); + } else + { + btAlignedFree(manifold); } } @@ -152,99 +129,19 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) { - -#ifdef USE_DISPATCH_REGISTRY_ARRAY btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher = this; + + ci.m_dispatcher1 = this; ci.m_manifold = sharedManifold; - btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()] - ->CreateCollisionAlgorithm(ci,body0,body1); -#else - btCollisionAlgorithm* algo = internalFindAlgorithm(body0,body1); -#endif //USE_DISPATCH_REGISTRY_ARRAY + btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1); + return algo; } -#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION - -btCollisionAlgorithmCreateFunc* btCollisionDispatcher::internalFindCreateFunc(int proxyType0,int proxyType1) -{ - - if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) - { - return m_convexConvexCreateFunc; - } - - if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) - { - return m_convexConcaveCreateFunc; - } - - if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) - { - return m_swappedConvexConcaveCreateFunc; - } - - if (btBroadphaseProxy::isCompound(proxyType0)) - { - return m_compoundCreateFunc; - } else - { - if (btBroadphaseProxy::isCompound(proxyType1)) - { - return m_swappedCompoundCreateFunc; - } - } - - //failed to find an algorithm - return m_emptyCreateFunc; -} - -#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION -#ifndef USE_DISPATCH_REGISTRY_ARRAY - -btCollisionAlgorithm* btCollisionDispatcher::internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) -{ - m_count++; - - btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher = this; - - if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConvex() ) - { - return new btConvexConvexAlgorithm(sharedManifold,ci,body0,body1); - } - - if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConcave()) - { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); - } - - if (body1->getCollisionShape()->isConvex() && body0->getCollisionShape()->isConcave()) - { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); - } - - if (body0->getCollisionShape()->isCompound()) - { - return new btCompoundCollisionAlgorithm(ci,body0,body1,false); - } else - { - if (body1->getCollisionShape()->isCompound()) - { - return new btCompoundCollisionAlgorithm(ci,body0,body1,true); - } - } - - //failed to find an algorithm - return new btEmptyAlgorithm(ci); - -} -#endif //USE_DISPATCH_REGISTRY_ARRAY bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1) { @@ -316,13 +213,13 @@ public: }; -void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo) +void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) { //m_blockedForChanges = true; btCollisionPairCallback collisionCallback(dispatchInfo,this); - pairCache->processAllOverlappingPairs(&collisionCallback); + pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); //m_blockedForChanges = false; @@ -365,3 +262,26 @@ void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, } } + + +void* btCollisionDispatcher::allocateCollisionAlgorithm(int size) +{ + if (m_collisionAlgorithmPoolAllocator->getFreeCount()) + { + return m_collisionAlgorithmPoolAllocator->allocate(size); + } + + //warn user for overflow? + return btAlignedAlloc(size,16); +} + +void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr) +{ + if (m_collisionAlgorithmPoolAllocator->validPtr(ptr)) + { + m_collisionAlgorithmPoolAllocator->free(ptr); + } else + { + btAlignedFree(ptr); + } +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h index ca5aba8f01c..45aaa1bd90d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h @@ -16,17 +16,18 @@ subject to the following restrictions: #ifndef COLLISION__DISPATCHER_H #define COLLISION__DISPATCHER_H -#include "../BroadphaseCollision/btDispatcher.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -#include "../CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btAlignedObjectArray.h" class btIDebugDraw; class btOverlappingPairCache; - +class btPoolAllocator; +class btCollisionConfiguration; #include "btCollisionCreateFunc.h" @@ -51,21 +52,15 @@ class btCollisionDispatcher : public btDispatcher btNearCallback m_nearCallback; + btPoolAllocator* m_collisionAlgorithmPoolAllocator; + + btPoolAllocator* m_persistentManifoldPoolAllocator; + btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; - btCollisionAlgorithmCreateFunc* internalFindCreateFunc(int proxyType0,int proxyType1); - //default CreationFunctions, filling the m_doubleDispatch table - btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; - btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; - btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; + btCollisionConfiguration* m_collisionConfiguration; -#ifndef USE_DISPATCH_REGISTRY_ARRAY - btCollisionAlgorithm* internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0); -#endif //USE_DISPATCH_REGISTRY_ARRAY public: @@ -92,11 +87,7 @@ public: return m_manifoldsPtr[index]; } - ///the default constructor creates/register default collision algorithms, for convex, compound and concave shape support - btCollisionDispatcher (); - - ///a special constructor that doesn't create/register the default collision algorithms - btCollisionDispatcher(bool noDefaultAlgorithms); + btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration); virtual ~btCollisionDispatcher(); @@ -114,7 +105,7 @@ public: virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1); - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo); + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher); void setNearCallback(btNearCallback nearCallback) { @@ -129,6 +120,25 @@ public: //by default, Bullet will use this near callback static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); + virtual void* allocateCollisionAlgorithm(int size); + + virtual void freeCollisionAlgorithm(void* ptr); + + btCollisionConfiguration* getCollisionConfiguration() + { + return m_collisionConfiguration; + } + + const btCollisionConfiguration* getCollisionConfiguration() const + { + return m_collisionConfiguration; + } + + void setCollisionConfiguration(btCollisionConfiguration* config) + { + m_collisionConfiguration = config; + } + }; #endif //COLLISION__DISPATCHER_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp index d4c0a4e8cb3..6b72a131c4f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp @@ -13,15 +13,19 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ + #include "btCollisionObject.h" btCollisionObject::btCollisionObject() : m_broadphaseHandle(0), m_collisionShape(0), m_collisionFlags(0), + m_islandTag1(-1), + m_companionId(-1), m_activationState1(1), m_deactivationTime(btScalar(0.)), m_userObjectPointer(0), + m_internalOwner(0), m_hitFraction(btScalar(1.)), m_ccdSweptSphereRadius(btScalar(0.)), m_ccdSquareMotionThreshold(btScalar(0.)), @@ -55,3 +59,4 @@ void btCollisionObject::activate(bool forceActivation) } + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h index 9fb6a67c4a3..7c1ddbf1e2d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef COLLISION_OBJECT_H #define COLLISION_OBJECT_H -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btTransform.h" //island management, m_activationState1 #define ACTIVE_TAG 1 @@ -27,7 +27,8 @@ subject to the following restrictions: struct btBroadphaseProxy; class btCollisionShape; -#include "../../LinearMath/btMotionState.h" +#include "LinearMath/btMotionState.h" +#include "LinearMath/btAlignedAllocator.h" @@ -89,6 +90,8 @@ protected: public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + enum CollisionFlags { CF_STATIC_OBJECT= 1, @@ -98,28 +101,28 @@ public: }; - inline bool mergesSimulationIslands() const + SIMD_FORCE_INLINE bool mergesSimulationIslands() const { ///static objects, kinematic and object without contact response don't merge islands return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0); } - inline bool isStaticObject() const { + SIMD_FORCE_INLINE bool isStaticObject() const { return (m_collisionFlags & CF_STATIC_OBJECT) != 0; } - inline bool isKinematicObject() const + SIMD_FORCE_INLINE bool isKinematicObject() const { return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0; } - inline bool isStaticOrKinematicObject() const + SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const { return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ; } - inline bool hasContactResponse() const { + SIMD_FORCE_INLINE bool hasContactResponse() const { return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0; } @@ -133,12 +136,12 @@ public: m_collisionShape = collisionShape; } - const btCollisionShape* getCollisionShape() const + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_collisionShape; } - btCollisionShape* getCollisionShape() + SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() { return m_collisionShape; } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index b49036a5b50..b4828508bcb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -24,6 +24,9 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" + #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" #include "LinearMath/btAabbUtil2.h" #include "LinearMath/btQuickprof.h" @@ -32,23 +35,20 @@ subject to the following restrictions: //When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" -btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize) +btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration) :m_dispatcher1(dispatcher), -m_broadphasePairCache(pairCache), -m_ownsDispatcher(false), -m_ownsBroadphasePairCache(false) +m_broadphasePairCache(pairCache) { - m_stackAlloc = new btStackAlloc(stackSize); + m_stackAlloc = collisionConfiguration->getStackAllocator(); m_dispatchInfo.m_stackAllocator = m_stackAlloc; } btCollisionWorld::~btCollisionWorld() { - m_stackAlloc->destroy(); - delete m_stackAlloc; //clean up remaining objects int i; @@ -62,15 +62,11 @@ btCollisionWorld::~btCollisionWorld() // // only clear the cached algorithms // - getBroadphase()->cleanProxyFromPairs(bp); - getBroadphase()->destroyProxy(bp); + getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); + getBroadphase()->destroyProxy(bp,m_dispatcher1); } } - if (m_ownsDispatcher) - delete m_dispatcher1; - if (m_ownsBroadphasePairCache) - delete m_broadphasePairCache; } @@ -105,7 +101,8 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho type, collisionObject, collisionFilterGroup, - collisionFilterMask + collisionFilterMask, + m_dispatcher1 )) ; @@ -130,11 +127,10 @@ void btCollisionWorld::performDiscreteCollisionDetection() for (int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax); - m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax); + m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax,m_dispatcher1); } - m_broadphasePairCache->refreshOverlappingPairs(); - + m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); END_PROFILE("perform Broadphase Collision Detection"); @@ -142,13 +138,14 @@ void btCollisionWorld::performDiscreteCollisionDetection() btDispatcher* dispatcher = getDispatcher(); if (dispatcher) - dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache,dispatchInfo); + dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); END_PROFILE("performDiscreteCollisionDetection"); } + void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) { @@ -163,8 +160,8 @@ void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) // // only clear the cached algorithms // - getBroadphase()->cleanProxyFromPairs(bp); - getBroadphase()->destroyProxy(bp); + getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); + getBroadphase()->destroyProxy(bp,m_dispatcher1); collisionObject->setBroadphaseHandle(0); } } @@ -209,19 +206,28 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt btConvexShape* convexShape = (btConvexShape*) collisionShape; btVoronoiSimplexSolver simplexSolver; +#define USE_SUBSIMPLEX_CONVEX_CAST 1 +#ifdef USE_SUBSIMPLEX_CONVEX_CAST btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); - //GjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); - //ContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); - +#else + //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); + //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); +#endif //#USE_SUBSIMPLEX_CONVEX_CAST + if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) { //add hit if (castResult.m_normal.length2() > btScalar(0.0001)) { - castResult.m_normal.normalize(); + if (castResult.m_fraction < resultCallback.m_closestHitFraction) { +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + //rotate normal into worldspace + castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal; +#endif //USE_SUBSIMPLEX_CONVEX_CAST + castResult.m_normal.normalize(); btCollisionWorld::LocalRayResult localRayResult ( collisionObject, @@ -230,7 +236,8 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt castResult.m_fraction ); - resultCallback.AddSingleResult(localRayResult); + bool normalInWorldSpace = true; + resultCallback.AddSingleResult(localRayResult, normalInWorldSpace); } } @@ -279,7 +286,8 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt hitNormalLocal, hitFraction); - return m_resultCallback->AddSingleResult(rayResult); + bool normalInWorldSpace = false; + return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace); } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index b6d80233ab7..bda03ccedeb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -68,12 +68,12 @@ class btStackAlloc; class btCollisionShape; class btConvexShape; class btBroadphaseInterface; -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" #include "btCollisionObject.h" #include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray -#include "../BroadphaseCollision/btOverlappingPairCache.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "LinearMath/btAlignedObjectArray.h" ///CollisionWorld is interface and container for the collision detection class btCollisionWorld @@ -90,15 +90,12 @@ protected: btStackAlloc* m_stackAlloc; - btOverlappingPairCache* m_broadphasePairCache; + btBroadphaseInterface* m_broadphasePairCache; - bool m_ownsDispatcher; - bool m_ownsBroadphasePairCache; - public: //this constructor doesn't own the dispatcher and paircache/broadphase - btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize = 2*1024*1024); + btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration); virtual ~btCollisionWorld(); @@ -110,7 +107,7 @@ public: btOverlappingPairCache* getPairCache() { - return m_broadphasePairCache; + return m_broadphasePairCache->getOverlappingPairCache(); } @@ -166,7 +163,7 @@ public: :m_closestHitFraction(btScalar(1.)) { } - virtual btScalar AddSingleResult(LocalRayResult& rayResult) = 0; + virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0; }; struct ClosestRayResultCallback : public RayResultCallback @@ -185,7 +182,7 @@ public: btVector3 m_hitPointWorld; btCollisionObject* m_collisionObject; - virtual btScalar AddSingleResult(LocalRayResult& rayResult) + virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) { //caller already does the filter on the m_closestHitFraction @@ -193,7 +190,14 @@ public: m_closestHitFraction = rayResult.m_hitFraction; m_collisionObject = rayResult.m_collisionObject; - m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + if (normalInWorldSpace) + { + m_hitNormalWorld = rayResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + } m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); return rayResult.m_hitFraction; } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp index 92f4c8b28a6..7c0c7a3b0a9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -19,7 +19,8 @@ subject to the following restrictions: btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) -:m_isSwapped(isSwapped) +:btCollisionAlgorithm(ci), +m_isSwapped(isSwapped) { btCollisionObject* colObj = m_isSwapped? body1 : body0; btCollisionObject* otherObj = m_isSwapped? body0 : body1; @@ -35,7 +36,7 @@ btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlg btCollisionShape* childShape = compoundShape->getChildShape(i); btCollisionShape* orgShape = colObj->getCollisionShape(); colObj->setCollisionShape( childShape ); - m_childCollisionAlgorithms[i] = ci.m_dispatcher->findAlgorithm(colObj,otherObj); + m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj); colObj->setCollisionShape( orgShape ); } } @@ -47,7 +48,8 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() int i; for (i=0;i~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h index 7091b233b46..a381d8b3c3f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -16,15 +16,16 @@ subject to the following restrictions: #ifndef COMPOUND_COLLISION_ALGORITHM_H #define COMPOUND_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btDispatcher.h" -#include "../BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" class btDispatcher; -#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" #include "btCollisionCreateFunc.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" +class btDispatcher; /// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes /// Place holder, not fully implemented yet @@ -47,7 +48,8 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btCompoundCollisionAlgorithm(ci,body0,body1,false); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); + return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false); } }; @@ -55,7 +57,8 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btCompoundCollisionAlgorithm(ci,body0,body1,true); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); + return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp index 24ceacfd40d..559b633feb9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp @@ -29,7 +29,7 @@ subject to the following restrictions: btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) : btCollisionAlgorithm(ci), m_isSwapped(isSwapped), -m_btConvexTriangleCallback(ci.m_dispatcher,body0,body1,isSwapped) +m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) { } @@ -79,7 +79,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i //aabb filter is already applied! btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher = m_dispatcher; + ci.m_dispatcher1 = m_dispatcher; btCollisionObject* ob = static_cast(m_triBody); @@ -115,7 +115,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i ob->setCollisionShape( &tm ); - btCollisionAlgorithm* colAlgo = ci.m_dispatcher->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); ///this should use the btDispatcher, so the actual registered algorithm is used // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); @@ -123,7 +123,8 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i // cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex); // cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); - delete colAlgo; + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); ob->setCollisionShape( tmpShape ); } @@ -188,9 +189,10 @@ void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* bod concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax()); + resultOut->refreshContactPoints(); } - + } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h index 4915b6c20c8..da33e988991 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h @@ -16,13 +16,13 @@ subject to the following restrictions: #ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H #define CONVEX_CONCAVE_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btDispatcher.h" -#include "../BroadphaseCollision/btBroadphaseInterface.h" -#include "../CollisionShapes/btTriangleCallback.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" class btDispatcher; -#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" #include "btCollisionCreateFunc.h" ///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called. @@ -55,11 +55,11 @@ int m_triangleCount; void clearCache(); - inline const btVector3& getAabbMin() const + SIMD_FORCE_INLINE const btVector3& getAabbMin() const { return m_aabbMin; } - inline const btVector3& getAabbMax() const + SIMD_FORCE_INLINE const btVector3& getAabbMax() const { return m_aabbMax; } @@ -94,7 +94,8 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); + return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); } }; @@ -102,7 +103,8 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); + return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp index 9105fe20b49..d1692cdac69 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp @@ -48,26 +48,16 @@ subject to the following restrictions: -btConvexConvexAlgorithm::CreateFunc::CreateFunc() -{ - m_ownsSolvers = true; - m_simplexSolver = new btVoronoiSimplexSolver(); - m_pdSolver = new btGjkEpaPenetrationDepthSolver; -} + btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) { - m_ownsSolvers = false; m_simplexSolver = simplexSolver; m_pdSolver = pdSolver; } btConvexConvexAlgorithm::CreateFunc::~CreateFunc() { - if (m_ownsSolvers){ - delete m_simplexSolver; - delete m_pdSolver; - } } btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) @@ -152,6 +142,11 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); #endif + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h index cbea9a92b75..ca58bce25f1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h @@ -16,12 +16,13 @@ subject to the following restrictions: #ifndef CONVEX_CONVEX_ALGORITHM_H #define CONVEX_CONVEX_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../NarrowPhaseCollision/btGjkPairDetector.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" #include "btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" class btConvexPenetrationDepthSolver; @@ -58,15 +59,15 @@ public: { btConvexPenetrationDepthSolver* m_pdSolver; btSimplexSolverInterface* m_simplexSolver; - bool m_ownsSolvers; CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); - CreateFunc(); + virtual ~CreateFunc(); virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm)); + return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp new file mode 100644 index 00000000000..661270b9bcb --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp @@ -0,0 +1,237 @@ + +/* +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. +*/ + +#include "btDefaultCollisionConfiguration.h" + +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" + + + +#include "LinearMath/btStackAlloc.h" +#include "LinearMath/btPoolAllocator.h" + + + +#define DEFAULT_MAX_OVERLAPPING_PAIRS 65535 +#define DEFAULT_STACK_ALLOCATOR_SIZE (5*1024*1024) + + +btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool) +{ + + void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16); + m_simplexSolver = new (mem)btVoronoiSimplexSolver(); + mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16); + m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver; + + //default CreationFunctions, filling the m_doubleDispatch table + mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16); + m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); + mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); + m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); + m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc; + mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16); + m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16); + m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc; + mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16); + m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16); + m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); + m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); + m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc; + m_boxSphereCF->m_swapped = true; + mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); + m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); + m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; + m_triangleSphereCF->m_swapped = true; + + + ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool + int maxSize = sizeof(btConvexConvexAlgorithm); + int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm); + int maxSize3 = sizeof(btCompoundCollisionAlgorithm); + int maxSize4 = sizeof(btEmptyAlgorithm); + + int collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4); + + if (stackAlloc) + { + m_ownsStackAllocator = false; + this->m_stackAlloc = stackAlloc; + } else + { + m_ownsStackAllocator = true; + void* mem = btAlignedAlloc(sizeof(btStackAlloc),16); + m_stackAlloc = new(mem)btStackAlloc(DEFAULT_STACK_ALLOCATOR_SIZE); + } + + if (persistentManifoldPool) + { + m_ownsPersistentManifoldPool = false; + m_persistentManifoldPool = persistentManifoldPool; + } else + { + m_ownsPersistentManifoldPool = true; + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),DEFAULT_MAX_OVERLAPPING_PAIRS); + } + + if (collisionAlgorithmPool) + { + m_ownsCollisionAlgorithmPool = false; + m_collisionAlgorithmPool = collisionAlgorithmPool; + } else + { + m_ownsCollisionAlgorithmPool = true; + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,DEFAULT_MAX_OVERLAPPING_PAIRS); + } + + +} + +btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration() +{ + if (m_ownsStackAllocator) + { + m_stackAlloc->destroy(); + m_stackAlloc->~btStackAlloc(); + btAlignedFree(m_stackAlloc); + } + if (m_ownsCollisionAlgorithmPool) + { + m_collisionAlgorithmPool->~btPoolAllocator(); + btAlignedFree(m_collisionAlgorithmPool); + } + if (m_ownsPersistentManifoldPool) + { + m_persistentManifoldPool->~btPoolAllocator(); + btAlignedFree(m_persistentManifoldPool); + } + + m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexConvexCreateFunc); + + m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexConcaveCreateFunc); + m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedConvexConcaveCreateFunc); + + m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_compoundCreateFunc); + + m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedCompoundCreateFunc); + + m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_emptyCreateFunc); + + m_sphereSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereSphereCF); + + m_sphereBoxCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereBoxCF); + m_boxSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_boxSphereCF); + m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereTriangleCF); + m_triangleSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_triangleSphereCF); + + m_simplexSolver->~btVoronoiSimplexSolver(); + btAlignedFree(m_simplexSolver); + m_pdSolver->~btGjkEpaPenetrationDepthSolver(); + btAlignedFree(m_pdSolver); + + +} + + +btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) +{ + + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_sphereSphereCF; + } + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE)) + { + return m_sphereBoxCF; + } + + if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_boxSphereCF; + } + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE)) + { + return m_sphereTriangleCF; + } + + if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_triangleSphereCF; + } + + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_convexConvexCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_convexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) + { + return m_swappedConvexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isCompound(proxyType0)) + { + return m_compoundCreateFunc; + } else + { + if (btBroadphaseProxy::isCompound(proxyType1)) + { + return m_swappedCompoundCreateFunc; + } + } + + //failed to find an algorithm + return m_emptyCreateFunc; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h new file mode 100644 index 00000000000..2e99f1db18f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h @@ -0,0 +1,87 @@ +/* +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. +*/ + +#ifndef BT_DEFAULT_COLLISION_CONFIGURATION +#define BT_DEFAULT_COLLISION_CONFIGURATION + +#include "btCollisionConfiguration.h" +class btVoronoiSimplexSolver; +class btGjkEpaPenetrationDepthSolver; + + +///btCollisionConfiguration allows to configure Bullet collision detection +///stack allocator, pool memory allocators +///todo: describe the meaning +class btDefaultCollisionConfiguration : public btCollisionConfiguration +{ + + int m_persistentManifoldPoolSize; + + btStackAlloc* m_stackAlloc; + bool m_ownsStackAllocator; + + btPoolAllocator* m_persistentManifoldPool; + bool m_ownsPersistentManifoldPool; + + btPoolAllocator* m_collisionAlgorithmPool; + bool m_ownsCollisionAlgorithmPool; + + //default simplex/penetration depth solvers + btVoronoiSimplexSolver* m_simplexSolver; + btGjkEpaPenetrationDepthSolver* m_pdSolver; + + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; + btCollisionAlgorithmCreateFunc* m_sphereSphereCF; + btCollisionAlgorithmCreateFunc* m_sphereBoxCF; + btCollisionAlgorithmCreateFunc* m_boxSphereCF; + btCollisionAlgorithmCreateFunc* m_sphereTriangleCF; + btCollisionAlgorithmCreateFunc* m_triangleSphereCF; + +public: + + btDefaultCollisionConfiguration(btStackAlloc* stackAlloc=0,btPoolAllocator* persistentManifoldPool=0,btPoolAllocator* collisionAlgorithmPool=0); + + virtual ~btDefaultCollisionConfiguration(); + + ///memory pools + virtual btPoolAllocator* getPersistentManifoldPool() + { + return m_persistentManifoldPool; + } + + virtual btPoolAllocator* getCollisionAlgorithmPool() + { + return m_collisionAlgorithmPool; + } + + virtual btStackAlloc* getStackAllocator() + { + return m_stackAlloc; + } + + + btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + + +}; + +#endif //BT_DEFAULT_COLLISION_CONFIGURATION + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h index b1a193d2cfd..89e7080780c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h @@ -15,8 +15,9 @@ subject to the following restrictions: #ifndef EMPTY_ALGORITH #define EMPTY_ALGORITH -#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" #include "btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" #define ATTRIBUTE_ALIGNED(a) @@ -39,7 +40,8 @@ public: { (void)body0; (void)body1; - return new btEmptyAlgorithm(ci); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm)); + return new(mem) btEmptyAlgorithm(ci); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp index 490acc0b611..61c4c231da4 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp @@ -79,12 +79,25 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b } btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); - + newPt.m_positionWorldOnA = pointA; + newPt.m_positionWorldOnB = pointInWorld; + int insertIndex = m_manifoldPtr->getCacheEntry(newPt); newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1); newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1); + + ///todo, check this for any side effects + if (insertIndex >= 0) + { + //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); + m_manifoldPtr->replaceContactPoint(newPt,insertIndex); + } else + { + m_manifoldPtr->AddManifoldPoint(newPt); + } + //User can override friction and/or restitution if (gContactAddedCallback && //and if either of the two bodies requires custom material @@ -97,13 +110,5 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b (*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1); } - if (insertIndex >= 0) - { - //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); - m_manifoldPtr->replaceContactPoint(newPt,insertIndex); - } else - { - m_manifoldPtr->AddManifoldPoint(newPt); - } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h index 77192625513..5aac9a46f6a 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h @@ -18,12 +18,12 @@ subject to the following restrictions: #define MANIFOLD_RESULT_H class btCollisionObject; -class btPersistentManifold; +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" class btManifoldPoint; #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btTransform.h" typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1); extern ContactAddedCallback gContactAddedCallback; @@ -60,6 +60,15 @@ public: m_manifoldPtr = manifoldPtr; } + const btPersistentManifold* getPersistentManifold() const + { + return m_manifoldPtr; + } + btPersistentManifold* getPersistentManifold() + { + return m_manifoldPtr; + } + virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1) { m_partId0=partId0; @@ -70,6 +79,22 @@ public: virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); + SIMD_FORCE_INLINE void refreshContactPoints() + { + btAssert(m_manifoldPtr); + if (!m_manifoldPtr->getNumContacts()) + return; + + bool isSwapped = m_manifoldPtr->getBody0() != m_body0; + + if (isSwapped) + { + m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA); + } else + { + m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB); + } + } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp index ac2e8554c3a..6c42d1706ff 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -25,17 +25,17 @@ void btSimulationIslandManager::initUnionFind(int n) } -void btSimulationIslandManager::findUnions(btDispatcher* dispatcher) +void btSimulationIslandManager::findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld) { { - for (int i=0;igetNumManifolds();i++) - { - const btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); - //static objects (invmass btScalar(0.)) don't merge ! + btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr(); - const btCollisionObject* colObj0 = static_cast(manifold->getBody0()); - const btCollisionObject* colObj1 = static_cast(manifold->getBody1()); + for (int i=0;igetPairCache()->getNumOverlappingPairs();i++) + { + const btBroadphasePair& collisionPair = pairPtr[i]; + btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && ((colObj1) && ((colObj1)->mergesSimulationIslands()))) @@ -71,7 +71,7 @@ void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld } // do the union find - findUnions(dispatcher); + findUnions(dispatcher,colWorld); @@ -138,19 +138,6 @@ class btPersistentManifoldSortPredicate void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) { - - - /*if (0) - { - int maxNumManifolds = dispatcher->getNumManifolds(); - btCollisionDispatcher* colDis = (btCollisionDispatcher*)dispatcher; - btPersistentManifold** manifold = colDis->getInternalManifoldPointer(); - callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, 0); - return; - } - */ - - BEGIN_PROFILE("islandUnionFindAndHeapSort"); //we are going to sort the unionfind array, and store the element id in the size @@ -247,11 +234,17 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, } } - btAlignedObjectArray islandmanifold; + int i; int maxNumManifolds = dispatcher->getNumManifolds(); - islandmanifold.reserve(maxNumManifolds); +#define SPLIT_ISLANDS 1 +#ifdef SPLIT_ISLANDS + + +#endif //SPLIT_ISLANDS + + for (i=0;igetManifoldByIndexInternal(i); @@ -265,29 +258,35 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, { //kinematic objects don't merge islands, but wake up all connected objects - if (colObj0->isStaticOrKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) + if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) { colObj1->activate(); } - if (colObj1->isStaticOrKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) + if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) { colObj0->activate(); } - - //filtering for response +#ifdef SPLIT_ISLANDS + // //filtering for response if (dispatcher->needsResponse(colObj0,colObj1)) - islandmanifold.push_back(manifold); + m_islandmanifold.push_back(manifold); +#endif //SPLIT_ISLANDS } } - int numManifolds = int (islandmanifold.size()); - +#ifndef SPLIT_ISLANDS + btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); + + callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); +#else // Sort manifolds, based on islands // Sort the vector using predicate and std::sort //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); + int numManifolds = int (m_islandmanifold.size()); + //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) - islandmanifold.heapSort(btPersistentManifoldSortPredicate()); + m_islandmanifold.heapSort(btPersistentManifoldSortPredicate()); //now process all active islands (sets of manifolds for now) @@ -298,8 +297,9 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, END_PROFILE("islandUnionFindAndHeapSort"); - btAlignedObjectArray islandBodies; + +// printf("Start Islands\n"); //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated for ( startIslandIndex=0;startIslandIndexisActive()) islandSleeping = true; } @@ -325,12 +325,12 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, if (startManifoldIndexProcessIsland(&islandBodies[0],islandBodies.size(),startManifold,numIslandManifolds, islandId); + callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); +// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); } if (numIslandManifolds) @@ -350,8 +351,9 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, startManifoldIndex = endManifoldIndex; } - islandBodies.resize(0); + m_islandBodies.resize(0); } +#endif //SPLIT_ISLANDS - + m_islandmanifold.resize(0); } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h index d91ed1c20eb..01a059b5fbe 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h @@ -16,18 +16,26 @@ subject to the following restrictions: #ifndef SIMULATION_ISLAND_MANAGER_H #define SIMULATION_ISLAND_MANAGER_H -#include "../CollisionDispatch/btUnionFind.h" +#include "BulletCollision/CollisionDispatch/btUnionFind.h" #include "btCollisionCreateFunc.h" +#include "LinearMath/btAlignedObjectArray.h" + class btCollisionObject; class btCollisionWorld; class btDispatcher; +class btPersistentManifold; + ///SimulationIslandManager creates and handles simulation islands, using btUnionFind class btSimulationIslandManager { btUnionFind m_unionFind; + btAlignedObjectArray m_islandmanifold; + btAlignedObjectArray m_islandBodies; + + public: btSimulationIslandManager(); virtual ~btSimulationIslandManager(); @@ -42,7 +50,7 @@ public: virtual void storeIslandActivationState(btCollisionWorld* world); - void findUnions(btDispatcher* dispatcher); + void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp index 05556bd34e2..1e4bbce451d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp @@ -68,18 +68,25 @@ void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,b btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius); + resultOut->setPersistentManifold(m_manifoldPtr); + if (dist < SIMD_EPSILON) { btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize(); /// report a contact. internally this will be kept persistent, and contact reduction is done - resultOut->setPersistentManifold(m_manifoldPtr); resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist); } - + if (m_ownManifold) + { + if (m_manifoldPtr->getNumContacts()) + { + resultOut->refreshContactPoints(); + } + } } @@ -102,8 +109,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* box btVector3 bounds[2]; btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape(); - bounds[0] = -boxShape->getHalfExtents(); - bounds[1] = boxShape->getHalfExtents(); + bounds[0] = -boxShape->getHalfExtentsWithoutMargin(); + bounds[1] = boxShape->getHalfExtentsWithoutMargin(); margins = boxShape->getMargin();//also add sphereShape margin? @@ -209,6 +216,10 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* btVector3 p0, tmp, prel, n[6], normal; btScalar fSep = btScalar(-10000000.0), fSepThis; + // set p0 and normal to a default value to shup up GCC + p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) ); n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) ); n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) ); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h index 07592909200..b839dc4adb1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h @@ -16,11 +16,13 @@ subject to the following restrictions: #ifndef SPHERE_BOX_COLLISION_ALGORITHM_H #define SPHERE_BOX_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" class btPersistentManifold; -#include "../../LinearMath/btVector3.h" +#include "btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" /// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. /// Other features are frame-coherency (persistent data) and collision response. @@ -48,12 +50,13 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm)); if (!m_swapped) { - return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); + return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); } else { - return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); + return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); } } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp index 424ff432f84..e7f42647e61 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp @@ -46,6 +46,8 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0 if (!m_manifoldPtr) return; + resultOut->setPersistentManifold(m_manifoldPtr); + btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape(); btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape(); @@ -54,10 +56,13 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0 btScalar radius0 = sphere0->getRadius(); btScalar radius1 = sphere1->getRadius(); + m_manifoldPtr->clearManifold(); + ///iff distance positive, don't generate a new contact if ( len > (radius0+radius1)) + { return; - + } ///distance (negative means penetration) btScalar dist = len - (radius0+radius1); @@ -68,9 +73,12 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0 btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; /// report a contact. internally this will be kept persistent, and contact reduction is done - resultOut->setPersistentManifold(m_manifoldPtr); + + resultOut->addContactPoint(normalOnSurfaceB,pos1,dist); + //no resultOut->refreshContactPoints(); needed, because of clearManifold (all points are new) + } btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h index 7a19ff31edf..bcaa0d303a9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h @@ -16,9 +16,11 @@ subject to the following restrictions: #ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H #define SPHERE_SPHERE_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" + class btPersistentManifold; /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. @@ -46,7 +48,8 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btSphereSphereCollisionAlgorithm(0,ci,body0,body1); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm)); + return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp index b011b707e3f..5d50bfed7a1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp @@ -48,8 +48,11 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co if (!m_manifoldPtr) return; - btSphereShape* sphere = (btSphereShape*)col0->getCollisionShape(); - btTriangleShape* triangle = (btTriangleShape*)col1->getCollisionShape(); + btCollisionObject* sphereObj = m_swapped? col1 : col0; + btCollisionObject* triObj = m_swapped? col0 : col1; + + btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape(); + btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape(); /// report a contact. internally this will be kept persistent, and contact reduction is done resultOut->setPersistentManifold(m_manifoldPtr); @@ -62,6 +65,9 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + if (m_ownManifold) + resultOut->refreshContactPoints(); + } btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h index 57c6e6af619..4aefc0c43a5 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h @@ -16,10 +16,11 @@ subject to the following restrictions: #ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H #define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" class btPersistentManifold; +#include "btCollisionDispatcher.h" /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. /// Other features are frame-coherency (persistent data) and collision response. @@ -49,7 +50,9 @@ public: virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm)); + + return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp index 62254335796..c81be8aa75c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp @@ -18,6 +18,7 @@ subject to the following restrictions: + btUnionFind::~btUnionFind() { Free(); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h index 236cc33b94f..820c8bc858e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef UNION_FIND_H #define UNION_FIND_H -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" #define USE_PATH_COMPRESSION 1 @@ -46,11 +46,11 @@ class btUnionFind void reset(int N); - inline int getNumElements() const + SIMD_FORCE_INLINE int getNumElements() const { return int(m_elements.size()); } - inline bool isRoot(int x) const + SIMD_FORCE_INLINE bool isRoot(int x) const { return (x == m_elements[x].m_id); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp index 636b0046c13..adac455bbcb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp @@ -15,16 +15,13 @@ subject to the following restrictions: #include "btBoxShape.h" -btVector3 btBoxShape::getHalfExtents() const -{ - return m_implicitShapeDimensions * m_localScaling; -} + //{ void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const { - btVector3 halfExtents = getHalfExtents(); + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); btMatrix3x3 abs_b = t.getBasis().absolute(); btPoint3 center = t.getOrigin(); @@ -40,10 +37,10 @@ void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabb } -void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //btScalar margin = btScalar(0.); - btVector3 halfExtents = getHalfExtents(); + btVector3 halfExtents = getHalfExtentsWithMargin(); btScalar lx=btScalar(2.)*(halfExtents.x()); btScalar ly=btScalar(2.)*(halfExtents.y()); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h index bc42f146c7c..98f1bd34b09 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h @@ -18,9 +18,9 @@ subject to the following restrictions: #include "btPolyhedralConvexShape.h" #include "btCollisionMargin.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btSimdMinMax.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btMinMax.h" ///btBoxShape implements both a feature based (vertex/edge/plane) and implicit (getSupportingVertex) Box class btBoxShape: public btPolyhedralConvexShape @@ -31,47 +31,52 @@ class btBoxShape: public btPolyhedralConvexShape public: - btVector3 getHalfExtents() const; - + btVector3 getHalfExtentsWithMargin() const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; + return halfExtents; + } + + const btVector3& getHalfExtentsWithoutMargin() const + { + return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included + } + + virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;} virtual btVector3 localGetSupportingVertex(const btVector3& vec) const { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; - btVector3 halfExtents = getHalfExtents(); - - btVector3 supVertex; - supVertex = btPoint3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), - vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), - vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); - - return supVertex; + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); } - virtual inline btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - btVector3 halfExtents = getHalfExtents(); - btVector3 margin(getMargin(),getMargin(),getMargin()); - halfExtents -= margin; - - return btVector3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), - vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), - vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); } virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const { - btVector3 halfExtents = getHalfExtents(); - btVector3 margin(getMargin(),getMargin(),getMargin()); - halfExtents -= margin; - - + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + for (int i=0;icalculateAabbBruteForce(bvhAabbMin,bvhAabbMax); - m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + + if (buildBvh) + { + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new (mem) btOptimizedBvh(); + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + m_ownsBvh = true; + } #endif //DISABLE_BVH } -btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) -:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression) +btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh) +:btTriangleMeshShape(meshInterface), +m_bvh(0), +m_useQuantizedAabbCompression(useQuantizedAabbCompression), +m_ownsBvh(false) { //construct bvh from meshInterface #ifndef DISABLE_BVH - m_bvh = new btOptimizedBvh(); - m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + if (buildBvh) + { + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new (mem) btOptimizedBvh(); + + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + m_ownsBvh = true; + } #endif //DISABLE_BVH @@ -67,7 +85,11 @@ void btBvhTriangleMeshShape::refitTree() btBvhTriangleMeshShape::~btBvhTriangleMeshShape() { - delete m_bvh; + if (m_ownsBvh) + { + m_bvh->~btOptimizedBvh(); + btAlignedFree(m_bvh); + } } //perform bvh tree traversal and report overlapping triangles to 'callback' @@ -163,9 +185,14 @@ void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) { btTriangleMeshShape::setLocalScaling(scaling); - delete m_bvh; + if (m_ownsBvh) + { + m_bvh->~btOptimizedBvh(); + btAlignedFree(m_bvh); + } ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work - m_bvh = new btOptimizedBvh(); + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new(mem) btOptimizedBvh(); //rebuild the bvh... m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h index 4914d9f959c..95c73b2441f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h @@ -18,6 +18,7 @@ subject to the following restrictions: #include "btTriangleMeshShape.h" #include "btOptimizedBvh.h" +#include "LinearMath/btAlignedAllocator.h" ///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. ///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. @@ -26,15 +27,18 @@ ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape btOptimizedBvh* m_bvh; bool m_useQuantizedAabbCompression; - bool m_pad[12];////need padding due to alignment + bool m_ownsBvh; + bool m_pad[11];////need padding due to alignment public: - btBvhTriangleMeshShape() :btTriangleMeshShape(0) {}; - btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression); + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btBvhTriangleMeshShape() :btTriangleMeshShape(0),m_bvh(0),m_ownsBvh(false) {}; + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true); ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb - btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true); virtual ~btBvhTriangleMeshShape(); @@ -56,7 +60,7 @@ public: void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax); //debugging - virtual char* getName()const {return "BVHTRIANGLEMESH";} + virtual const char* getName()const {return "BVHTRIANGLEMESH";} virtual void setLocalScaling(const btVector3& scaling); @@ -65,6 +69,17 @@ public: { return m_bvh; } + + + void setOptimizedBvh(btOptimizedBvh* bvh) + { + btAssert(!m_bvh); + btAssert(!m_ownsBvh); + + m_bvh = bvh; + m_ownsBvh = false; + } + bool usesQuantizedAabbCompression() const { return m_useQuantizedAabbCompression; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp index b7e15172da2..b4f21f38b3d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp @@ -112,7 +112,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) } -void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //as an approximation, take the inertia of the box that bounds the spheres diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h index 27da8adefa5..0b566450fef 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h @@ -16,20 +16,20 @@ subject to the following restrictions: #ifndef BT_CAPSULE_SHAPE_H #define BT_CAPSULE_SHAPE_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types ///btCapsuleShape represents a capsule around the Y axis ///A more general solution that can represent capsules is the btMultiSphereShape -class btCapsuleShape : public btConvexShape +class btCapsuleShape : public btConvexInternalShape { public: btCapsuleShape(btScalar radius,btScalar height); ///CollisionShape Interface - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; /// btConvexShape Interface virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; @@ -38,7 +38,7 @@ public: virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; } - virtual char* getName()const + virtual const char* getName()const { return "CapsuleShape"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h index 96268734a83..53fb12e33a1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h @@ -16,11 +16,11 @@ subject to the following restrictions: #ifndef COLLISION_SHAPE_H #define COLLISION_SHAPE_H -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btMatrix3x3.h" -#include "../../LinearMath/btPoint3.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" //for the shape types +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btPoint3.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types ///btCollisionShape provides interface for collision shapes that can be shared among btCollisionObjects. class btCollisionShape @@ -49,26 +49,26 @@ public: #ifndef __SPU__ - inline bool isPolyhedral() const + SIMD_FORCE_INLINE bool isPolyhedral() const { return btBroadphaseProxy::isPolyhedral(getShapeType()); } - inline bool isConvex() const + SIMD_FORCE_INLINE bool isConvex() const { return btBroadphaseProxy::isConvex(getShapeType()); } - inline bool isConcave() const + SIMD_FORCE_INLINE bool isConcave() const { return btBroadphaseProxy::isConcave(getShapeType()); } - inline bool isCompound() const + SIMD_FORCE_INLINE bool isCompound() const { return btBroadphaseProxy::isCompound(getShapeType()); } ///isInfinite is used to catch simulation error (aabb check) - inline bool isInfinite() const + SIMD_FORCE_INLINE bool isInfinite() const { return btBroadphaseProxy::isInfinite(getShapeType()); } @@ -76,11 +76,11 @@ public: virtual int getShapeType() const=0; virtual void setLocalScaling(const btVector3& scaling) =0; virtual const btVector3& getLocalScaling() const =0; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) = 0; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0; //debugging support - virtual char* getName()const =0 ; + virtual const char* getName()const =0 ; #endif //__SPU__ diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp index a4712b3e925..114a1f4c1fc 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -35,8 +35,15 @@ btCompoundShape::~btCompoundShape() void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) { - m_childTransforms.push_back(localTransform); - m_childShapes.push_back(shape); + //m_childTransforms.push_back(localTransform); + //m_childShapes.push_back(shape); + btCompoundShapeChild child; + child.m_transform = localTransform; + child.m_childShape = shape; + child.m_childShapeType = shape->getShapeType(); + child.m_childMargin = shape->getMargin(); + + m_children.push_back(child); //extend the local aabbMin/aabbMax btVector3 localAabbMin,localAabbMax; @@ -76,7 +83,7 @@ void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVect aabbMax = center + extent; } -void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //approximation: take the inertia from the aabb for now btTransform ident; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h index 86dc1f80947..d23bd65b5e8 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h @@ -18,26 +18,39 @@ subject to the following restrictions: #include "btCollisionShape.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btMatrix3x3.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" #include "btCollisionMargin.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" class btOptimizedBvh; +ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTransform m_transform; + btCollisionShape* m_childShape; + int m_childShapeType; + btScalar m_childMargin; +}; + /// btCompoundShape allows to store multiple other btCollisionShapes /// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape. -class btCompoundShape : public btCollisionShape +ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape { - btAlignedObjectArray m_childTransforms; - btAlignedObjectArray m_childShapes; + //btAlignedObjectArray m_childTransforms; + //btAlignedObjectArray m_childShapes; + btAlignedObjectArray m_children; btVector3 m_localAabbMin; btVector3 m_localAabbMax; btOptimizedBvh* m_aabbTree; public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + btCompoundShape(); virtual ~btCompoundShape(); @@ -46,25 +59,31 @@ public: int getNumChildShapes() const { - return int (m_childShapes.size()); + return int (m_children.size()); } btCollisionShape* getChildShape(int index) { - return m_childShapes[index]; + return m_children[index].m_childShape; } const btCollisionShape* getChildShape(int index) const { - return m_childShapes[index]; + return m_children[index].m_childShape; } - btTransform& getChildTransform(int index) + btTransform getChildTransform(int index) { - return m_childTransforms[index]; + return m_children[index].m_transform; } - const btTransform& getChildTransform(int index) const + const btTransform getChildTransform(int index) const { - return m_childTransforms[index]; + return m_children[index].m_transform; + } + + + btCompoundShapeChild* getChildList() + { + return &m_children[0]; } ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version @@ -80,7 +99,7 @@ public: return m_localScaling; } - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;} @@ -92,7 +111,7 @@ public: { return m_collisionMargin; } - virtual char* getName()const + virtual const char* getName()const { return "Compound"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h index 73f974e4ee9..4db4e6513dd 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h @@ -17,7 +17,7 @@ subject to the following restrictions: #define CONCAVE_SHAPE_H #include "btCollisionShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "btTriangleCallback.h" diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h index 3ccda5b12c6..34f36b35f87 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h @@ -16,11 +16,11 @@ subject to the following restrictions: #ifndef CONE_MINKOWSKI_H #define CONE_MINKOWSKI_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types ///btConeShape implements a Cone shape, around the Y axis -class btConeShape : public btConvexShape +class btConeShape : public btConvexInternalShape { @@ -42,7 +42,7 @@ public: btScalar getHeight() const { return m_height;} - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const { btTransform identity; identity.setIdentity(); @@ -72,7 +72,7 @@ public: virtual int getShapeType() const { return CONE_SHAPE_PROXYTYPE; } - virtual char* getName()const + virtual const char* getName()const { return "Cone"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h index 3fd5e382525..0928d68b8fc 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h @@ -17,8 +17,8 @@ subject to the following restrictions: #define CONVEX_HULL_SHAPE_H #include "btPolyhedralConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types -#include "../../LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "LinearMath/btAlignedObjectArray.h" ///ConvexHullShape implements an implicit (getSupportingVertex) Convex Hull of a Point Cloud (vertices) ///No connectivity is needed. localGetSupportingVertex iterates linearly though all vertices. @@ -29,6 +29,7 @@ ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexShape btAlignedObjectArray m_points; public: + BT_DECLARE_ALIGNED_ALLOCATOR(); ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory. @@ -56,7 +57,7 @@ public: virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; } //debugging - virtual char* getName()const {return "Convex";} + virtual const char* getName()const {return "Convex";} virtual int getNumVertices() const; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp new file mode 100644 index 00000000000..f828d28e18c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp @@ -0,0 +1,78 @@ +/* +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. +*/ + + +#include "btConvexInternalShape.h" + + +btConvexInternalShape::btConvexInternalShape() +: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), +m_collisionMargin(CONVEX_DISTANCE_MARGIN) +{ +} + + +void btConvexInternalShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} + + + +void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const +{ + + btScalar margin = getMargin(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + + btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); + + btVector3 tmp = trans(sv); + maxAabb[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); + minAabb[i] = tmp[i]-margin; + } +}; + + +btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const +{ +#ifndef __SPU__ + + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; + +#else + return btVector3(0,0,0); +#endif //__SPU__ + + } + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h new file mode 100644 index 00000000000..a03af873bd3 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h @@ -0,0 +1,99 @@ + +#ifndef BT_CONVEX_INTERNAL_SHAPE_H +#define BT_CONVEX_INTERNAL_SHAPE_H + +#include "btConvexShape.h" + +///btConvexInternalShape carries some additional data, shared by most implementations +class btConvexInternalShape : public btConvexShape +{ + + protected: + + //local scaling. collisionMargin is not scaled ! + btVector3 m_localScaling; + + btVector3 m_implicitShapeDimensions; + + btScalar m_collisionMargin; + + btScalar m_padding[2]; + + + + +public: + + btConvexInternalShape(); + + virtual ~btConvexInternalShape() + { + + } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; +#ifndef __SPU__ + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; + + //notice that the vectors should be unit length + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; +#endif //#ifndef __SPU__ + + const btVector3& getImplicitShapeDimensions() const + { + return m_implicitShapeDimensions; + } + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + getAabbSlow(t,aabbMin,aabbMax); + } + + + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + const btVector3& getLocalScalingNV() const + { + return m_localScaling; + } + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + } + virtual btScalar getMargin() const + { + return m_collisionMargin; + } + + btScalar getMarginNV() const + { + return m_collisionMargin; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 0; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + (void)penetrationVector; + (void)index; + btAssert(0); + } + +}; + + +#endif //BT_CONVEX_INTERNAL_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp index 7edf1ea6db8..7afcccf8b03 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp @@ -16,62 +16,3 @@ subject to the following restrictions: #include "btConvexShape.h" -btConvexShape::btConvexShape() -: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), -m_collisionMargin(CONVEX_DISTANCE_MARGIN) -{ -} - - -void btConvexShape::setLocalScaling(const btVector3& scaling) -{ - m_localScaling = scaling; -} - - - -void btConvexShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const -{ - - btScalar margin = getMargin(); - for (int i=0;i<3;i++) - { - btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); - vec[i] = btScalar(1.); - - btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); - - btVector3 tmp = trans(sv); - maxAabb[i] = tmp[i]+margin; - vec[i] = btScalar(-1.); - tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); - minAabb[i] = tmp[i]-margin; - } -}; - - -btVector3 btConvexShape::localGetSupportingVertex(const btVector3& vec)const -{ -#ifndef __SPU__ - - btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); - - if ( getMargin()!=btScalar(0.) ) - { - btVector3 vecnorm = vec; - if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) - { - vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); - } - vecnorm.normalize(); - supVertex+= getMargin() * vecnorm; - } - return supVertex; - -#else - return btVector3(0,0,0); -#endif //__SPU__ - - } - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h index 746f383dfc7..6dfd288e05b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h @@ -18,37 +18,26 @@ subject to the following restrictions: #include "btCollisionShape.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btMatrix3x3.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" #include "btCollisionMargin.h" +#include "LinearMath/btAlignedAllocator.h" //todo: get rid of this btConvexCastResult thing! struct btConvexCastResult; #define MAX_PREFERRED_PENETRATION_DIRECTIONS 10 /// btConvexShape is an abstract shape interface. -/// The explicit part provides plane-equations, the implicit part provides GetClosestPoint interface. +/// It describes general convex shapes using the localGetSupportingVertex interface /// used in combination with GJK or btConvexCast ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape { -protected: - - //local scaling. collisionMargin is not scaled ! - btVector3 m_localScaling; - - btVector3 m_implicitShapeDimensions; - - btScalar m_collisionMargin; - - btScalar m_padding[2]; - - - public: - btConvexShape(); + + BT_DECLARE_ALIGNED_ALLOCATOR(); virtual ~btConvexShape() { @@ -56,7 +45,7 @@ public: } - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const =0; #ifndef __SPU__ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; @@ -64,63 +53,24 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; #endif //#ifndef __SPU__ - const btVector3& getImplicitShapeDimensions() const - { - return m_implicitShapeDimensions; - } ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const - { - getAabbSlow(t,aabbMin,aabbMax); - } + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + virtual void setLocalScaling(const btVector3& scaling) =0; + virtual const btVector3& getLocalScaling() const =0; + + virtual void setMargin(btScalar margin)=0; + + virtual btScalar getMargin() const=0; + + virtual int getNumPreferredPenetrationDirections() const=0; - virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0; - - virtual void setLocalScaling(const btVector3& scaling); - virtual const btVector3& getLocalScaling() const - { - return m_localScaling; - } - - const btVector3& getLocalScalingNV() const - { - return m_localScaling; - } - - virtual void setMargin(btScalar margin) - { - m_collisionMargin = margin; - } - virtual btScalar getMargin() const - { - return m_collisionMargin; - } - - btScalar getMarginNV() const - { - return m_collisionMargin; - } - - virtual int getNumPreferredPenetrationDirections() const - { - return 0; - } - - virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const - { - (void)penetrationVector; - (void)index; - btAssert(0); - } - - - -} -; +}; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp index 614ec977793..6941030b15f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp @@ -202,4 +202,4 @@ void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling) const btVector3& btConvexTriangleMeshShape::getLocalScaling() const { return m_stridingMesh->getScaling(); -} \ No newline at end of file +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h index 34ee7af744c..f3daa58368f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h @@ -3,7 +3,7 @@ #include "btPolyhedralConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types /// btConvexTriangleMeshShape is a convex hull of a triangle mesh. If you just have a point cloud, you can use btConvexHullShape instead. @@ -16,7 +16,11 @@ class btConvexTriangleMeshShape : public btPolyhedralConvexShape public: btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface); - class btStridingMeshInterface* getStridingMesh() + class btStridingMeshInterface* getMeshInterface() + { + return m_stridingMesh; + } + const class btStridingMeshInterface* getMeshInterface() const { return m_stridingMesh; } @@ -28,7 +32,7 @@ public: virtual int getShapeType()const { return CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; } //debugging - virtual char* getName()const {return "ConvexTrimesh";} + virtual const char* getName()const {return "ConvexTrimesh";} virtual int getNumVertices() const; virtual int getNumEdges() const; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp index 1666afb3b88..3afef1c7550 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp @@ -45,7 +45,7 @@ void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& } -inline btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) +SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) { const int cylinderUpAxis = 0; const int XX = 1; @@ -163,24 +163,24 @@ const int ZZ = 1; btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportX(getHalfExtents(),vec); + return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec); } btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportZ(getHalfExtents(),vec); + return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec); } btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportY(getHalfExtents(),vec); + return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec); } void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const { for (int i=0;iquantizeWithClamp(&node.m_quantizedAabbMin[0],aabbMin); m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMax[0],aabbMax); @@ -170,6 +188,13 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized subtree.m_rootNodeIndex = 0; subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + + //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary + m_quantizedLeafNodes.clear(); + m_leafNodes.clear(); } @@ -201,8 +226,9 @@ void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const b { btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; - bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); - if (overlap) + //PCK: unsigned instead of bool + unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap != 0) { updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i); @@ -479,6 +505,9 @@ void btOptimizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChild subtree.m_rootNodeIndex = rightChildNodexIndex; subtree.m_subtreeSize = rightSubTreeSize; } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); } @@ -568,7 +597,6 @@ void btOptimizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallb { //either choose recursive traversal (walkTree) or stackless (walkStacklessTree) - if (m_useQuantization) { ///quantize query AABB @@ -611,7 +639,9 @@ void btOptimizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0]; int escapeIndex, curIndex = 0; int walkIterations = 0; - bool aabbOverlap, isLeafNode; + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap; while (curIndex < m_curNodeIndex) { @@ -622,12 +652,14 @@ void btOptimizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg); isLeafNode = rootNode->m_escapeIndex == -1; - if (isLeafNode && aabbOverlap) + //PCK: unsigned instead of bool + if (isLeafNode && (aabbOverlap != 0)) { nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); } - if (aabbOverlap || isLeafNode) + //PCK: unsigned instead of bool + if ((aabbOverlap != 0) || isLeafNode) { rootNode++; curIndex++; @@ -668,12 +700,16 @@ void btOptimizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantize { btAssert(m_useQuantization); - bool aabbOverlap, isLeafNode; + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap; + //PCK: unsigned instead of bool aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax); isLeafNode = currentNode->isLeafNode(); - if (aabbOverlap) + //PCK: unsigned instead of bool + if (aabbOverlap != 0) { if (isLeafNode) { @@ -707,7 +743,9 @@ void btOptimizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallb const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; int escapeIndex; - bool aabbOverlap, isLeafNode; + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap; while (curIndex < endNodeIndex) { @@ -732,6 +770,7 @@ void btOptimizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallb assert (walkIterations < subTreeSize); walkIterations++; + //PCK: unsigned instead of bool aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); isLeafNode = rootNode->isLeafNode(); @@ -740,7 +779,8 @@ void btOptimizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallb nodeCallback->processNode(0,rootNode->getTriangleIndex()); } - if (aabbOverlap || isLeafNode) + //PCK: unsigned instead of bool + if ((aabbOverlap != 0) || isLeafNode) { rootNode++; curIndex++; @@ -768,8 +808,9 @@ void btOptimizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallba { const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; - bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); - if (overlap) + //PCK: unsigned instead of bool + unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap != 0) { walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, subtree.m_rootNodeIndex, @@ -791,20 +832,7 @@ void btOptimizedBvh::reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCal } -void btOptimizedBvh::quantizeWithClamp(unsigned short* out, const btVector3& point) const -{ - btAssert(m_useQuantization); - - btVector3 clampedPoint(point); - clampedPoint.setMax(m_bvhAabbMin); - clampedPoint.setMin(m_bvhAabbMax); - - btVector3 v = (clampedPoint - m_bvhAabbMin) * m_bvhQuantization; - out[0] = (unsigned short)(v.getX()+0.5f); - out[1] = (unsigned short)(v.getY()+0.5f); - out[2] = (unsigned short)(v.getZ()+0.5f); -} btVector3 btOptimizedBvh::unQuantize(const unsigned short* vecIn) const { @@ -843,3 +871,311 @@ void btOptimizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNod m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex]; } } + +//PCK: include +#include + +//PCK: consts +static const unsigned BVH_ALIGNMENT = 16; +static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1; + +static const unsigned BVH_ALIGNMENT_BLOCKS = 2; + + + +unsigned int btOptimizedBvh::getAlignmentSerializationPadding() +{ + return BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT; +} + +unsigned btOptimizedBvh::calculateSerializeBufferSize() +{ + unsigned baseSize = sizeof(btOptimizedBvh) + getAlignmentSerializationPadding(); + baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; + if (m_useQuantization) + { + return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode); + } + return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode); +} + +bool btOptimizedBvh::serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) +{ + assert(m_subtreeHeaderCount == m_SubtreeHeaders.size()); + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + +/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) + { + ///check alignedment for buffer? + btAssert(0); + return false; + } +*/ + + btOptimizedBvh *targetBvh = (btOptimizedBvh *)o_alignedDataBuffer; + + // construct the class so the virtual function table, etc will be set up + // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor + new (targetBvh) btOptimizedBvh; + + if (i_swapEndian) + { + targetBvh->m_curNodeIndex = btSwapEndian(m_curNodeIndex); + + + btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin); + btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax); + btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization); + + targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode); + targetBvh->m_subtreeHeaderCount = btSwapEndian(m_subtreeHeaderCount); + } + else + { + targetBvh->m_curNodeIndex = m_curNodeIndex; + targetBvh->m_bvhAabbMin = m_bvhAabbMin; + targetBvh->m_bvhAabbMax = m_bvhAabbMax; + targetBvh->m_bvhQuantization = m_bvhQuantization; + targetBvh->m_traversalMode = m_traversalMode; + targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount; + } + + targetBvh->m_useQuantization = m_useQuantization; + + unsigned char *nodeData = (unsigned char *)targetBvh; + nodeData += sizeof(btOptimizedBvh); + + unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + int nodeCount = m_curNodeIndex; + + if (m_useQuantization) + { + targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex); + } + } + else + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]; + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]; + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex; + + + } + } + nodeData += sizeof(btQuantizedBvhNode) * nodeCount; + } + else + { + targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); + btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); + + targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex); + targetBvh->m_contiguousNodes[nodeIndex].m_subPart = btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart); + targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex); + } + } + else + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg; + targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg; + + targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex; + targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart; + targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex; + } + } + nodeData += sizeof(btOptimizedBvhNode) * nodeCount; + } + + sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + // Now serialize the subtree headers + targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount); + if (i_swapEndian) + { + for (int i = 0; i < m_subtreeHeaderCount; i++) + { + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex); + targetBvh->m_SubtreeHeaders[i].m_subtreeSize = btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize); + } + } + else + { + for (int i = 0; i < m_subtreeHeaderCount; i++) + { + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex); + targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize); + targetBvh->m_SubtreeHeaders[i] = m_SubtreeHeaders[i]; + } + } + + nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; + + return true; +} + +btOptimizedBvh *btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) +{ + + if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) + { + return NULL; + } + btOptimizedBvh *bvh = (btOptimizedBvh *)i_alignedDataBuffer; + + if (i_swapEndian) + { + bvh->m_curNodeIndex = btSwapEndian(bvh->m_curNodeIndex); + + btUnSwapVector3Endian(bvh->m_bvhAabbMin); + btUnSwapVector3Endian(bvh->m_bvhAabbMax); + btUnSwapVector3Endian(bvh->m_bvhQuantization); + + bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode); + bvh->m_subtreeHeaderCount = btSwapEndian(bvh->m_subtreeHeaderCount); + } + + int calculatedBufSize = bvh->calculateSerializeBufferSize(); + btAssert(calculatedBufSize <= i_dataBufferSize); + + if (calculatedBufSize > i_dataBufferSize) + { + return NULL; + } + + unsigned char *nodeData = (unsigned char *)bvh; + nodeData += sizeof(btOptimizedBvh); + + unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + int nodeCount = bvh->m_curNodeIndex; + + // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor + // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor + new (bvh) btOptimizedBvh(*bvh, false); + + if (bvh->m_useQuantization) + { + bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); + + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); + + bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex); + } + } + nodeData += sizeof(btQuantizedBvhNode) * nodeCount; + } + else + { + bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); + btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); + + bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex); + bvh->m_contiguousNodes[nodeIndex].m_subPart = btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart); + bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex); + } + } + nodeData += sizeof(btOptimizedBvhNode) * nodeCount; + } + + sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + // Now serialize the subtree headers + bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount); + if (i_swapEndian) + { + for (int i = 0; i < bvh->m_subtreeHeaderCount; i++) + { + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + bvh->m_SubtreeHeaders[i].m_rootNodeIndex = btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex); + bvh->m_SubtreeHeaders[i].m_subtreeSize = btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize); + } + } + + return bvh; +} + +// Constructor that prevents btVector3's default constructor from being called +btOptimizedBvh::btOptimizedBvh(btOptimizedBvh &self, bool ownsMemory) : +m_bvhAabbMin(self.m_bvhAabbMin), +m_bvhAabbMax(self.m_bvhAabbMax), +m_bvhQuantization(self.m_bvhQuantization) +{ + +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h index d5159586344..bcacdbe582b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h @@ -17,7 +17,9 @@ subject to the following restrictions: #define OPTIMIZED_BVH_H -#include "../../LinearMath/btVector3.h" + +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedAllocator.h" //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp @@ -34,7 +36,8 @@ class btStridingMeshInterface; ///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode { - + BT_DECLARE_ALIGNED_ALLOCATOR(); + //12 bytes unsigned short int m_quantizedAabbMin[3]; unsigned short int m_quantizedAabbMax[3]; @@ -63,6 +66,8 @@ ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode /// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode { + BT_DECLARE_ALIGNED_ALLOCATOR(); + //32 bytes btVector3 m_aabbMinOrg; btVector3 m_aabbMaxOrg; @@ -84,6 +89,8 @@ ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo { public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + //12 bytes unsigned short int m_quantizedAabbMin[3]; unsigned short int m_quantizedAabbMax[3]; @@ -93,6 +100,11 @@ public: int m_subtreeSize; int m_padding[3]; + btBvhSubtreeInfo() + { + //memset(&m_padding[0], 0, sizeof(m_padding)); + } + void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) { @@ -115,8 +127,8 @@ public: virtual void processNode(int subPart, int triangleIndex) = 0; }; -#include "../../LinearMath/btAlignedAllocator.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btAlignedObjectArray.h" @@ -144,6 +156,8 @@ ATTRIBUTE_ALIGNED16(class) btOptimizedBvh btVector3 m_bvhAabbMin; btVector3 m_bvhAabbMax; btVector3 m_bvhQuantization; +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); enum btTraversalMode { @@ -151,14 +165,15 @@ ATTRIBUTE_ALIGNED16(class) btOptimizedBvh TRAVERSAL_STACKLESS_CACHE_FRIENDLY, TRAVERSAL_RECURSIVE }; +protected: btTraversalMode m_traversalMode; - - - BvhSubtreeInfoArray m_SubtreeHeaders; + //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray + int m_subtreeHeaderCount; + ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) ///this might be refactored into a virtual, it is usually not calculated at run-time @@ -273,7 +288,18 @@ protected: void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; - inline bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const +#define USE_BANCHLESS 1 +#ifdef USE_BANCHLESS + //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360) + SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const + { + return btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) + & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) + & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])), + 1, 0); + } +#else + SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const { bool overlap = true; overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; @@ -281,6 +307,7 @@ protected: overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; return overlap; } +#endif //USE_BANCHLESS void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); @@ -294,8 +321,22 @@ public: void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; void reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point) const + { + + btAssert(m_useQuantization); + + btVector3 clampedPoint(point); + clampedPoint.setMax(m_bvhAabbMin); + clampedPoint.setMin(m_bvhAabbMax); + + btVector3 v = (clampedPoint - m_bvhAabbMin) * m_bvhQuantization; + out[0] = (unsigned short)(v.getX()+0.5f); + out[1] = (unsigned short)(v.getY()+0.5f); + out[2] = (unsigned short)(v.getZ()+0.5f); + } - void quantizeWithClamp(unsigned short* out, const btVector3& point) const; btVector3 unQuantize(const unsigned short* vecIn) const; @@ -312,15 +353,37 @@ public: void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index); - QuantizedNodeArray& getQuantizedNodeArray() + SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray() { return m_quantizedContiguousNodes; } - BvhSubtreeInfoArray& getSubtreeInfoArray() + SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray() { return m_SubtreeHeaders; } + + /////Calculate space needed to store BVH for serialization + unsigned calculateSerializeBufferSize(); + + /// Data buffer MUST be 16 byte aligned + bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian); + + ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' + static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian); + + static unsigned int getAlignmentSerializationPadding(); + + SIMD_FORCE_INLINE bool isQuantized() + { + return m_useQuantization; + } + +private: + // Special "copy" constructor that allows for in-place deserialization + // Prevents btVector3's default constructor from being called, but doesn't inialize much else + // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need) + btOptimizedBvh(btOptimizedBvh &other, bool ownsMemory); } ; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp index bbc4ba62af6..30323deb3b5 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp @@ -95,7 +95,7 @@ void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin( -void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //not yet, return box inertia diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h index c35f7512663..9d46b991e10 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h @@ -16,13 +16,13 @@ subject to the following restrictions: #ifndef BU_SHAPE #define BU_SHAPE -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btMatrix3x3.h" -#include "btConvexShape.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btMatrix3x3.h" +#include "btConvexInternalShape.h" ///PolyhedralConvexShape is an interface class for feature based (vertex/edge/face) convex shapes. -class btPolyhedralConvexShape : public btConvexShape +class btPolyhedralConvexShape : public btConvexInternalShape { protected: @@ -38,7 +38,7 @@ public: virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp index ca65dd03f3e..15cfe432e27 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp @@ -68,7 +68,7 @@ void btSphereShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& a -void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin(); inertia.setValue(elem,elem,elem); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h index 66521664087..d89a78b08e2 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h @@ -16,15 +16,17 @@ subject to the following restrictions: #ifndef SPHERE_MINKOWSKI_H #define SPHERE_MINKOWSKI_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types ///btSphereShape implements an implicit (getSupportingVertex) Sphere -ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexShape +ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexInternalShape { public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + btSphereShape (btScalar radius); @@ -34,26 +36,26 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual int getShapeType() const { return SPHERE_SHAPE_PROXYTYPE; } - btScalar getRadius() const { return m_implicitShapeDimensions.getX();} + btScalar getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX();} //debugging - virtual char* getName()const {return "SPHERE";} + virtual const char* getName()const {return "SPHERE";} virtual void setMargin(btScalar margin) { - btConvexShape::setMargin(margin); + btConvexInternalShape::setMargin(margin); } virtual btScalar getMargin() const { //to improve gjk behaviour, use radius+margin as the full margin, so never get into the penetration case //this means, non-uniform scaling is not supported anymore - return m_localScaling.getX() * getRadius() + btConvexShape::getMargin(); + return getRadius(); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp index 4fbaafa1b93..7dd6425e0bd 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp @@ -86,7 +86,7 @@ void btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback,const } -void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { (void)mass; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h index f59cc0c3347..0cbce3abd93 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h @@ -46,14 +46,14 @@ public: virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; //debugging - virtual char* getName()const {return "STATICPLANE";} + virtual const char* getName()const {return "STATICPLANE";} }; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp index 03ca1ae7736..3129b7c83ce 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp @@ -121,4 +121,4 @@ void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVecto aabbMin = aabbCallback.m_aabbMin; aabbMax = aabbCallback.m_aabbMax; -} \ No newline at end of file +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h index d7b354b7855..4ce0bd2e2f9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef STRIDING_MESHINTERFACE_H #define STRIDING_MESHINTERFACE_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btTriangleCallback.h" /// PHY_ScalarType enumerates possible scalar types. diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h index 94bc4ec0fa5..ca1b4b42a6f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h @@ -18,7 +18,7 @@ subject to the following restrictions: #include "btPolyhedralConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" ///BU_Simplex1to4 implements feature based and implicit simplex of up to 4 vertices (tetrahedron, triangle, line, vertex). @@ -68,7 +68,7 @@ public: ///getName is for debugging - virtual char* getName()const { return "btBU_Simplex1to4";} + virtual const char* getName()const { return "btBU_Simplex1to4";} }; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.h index 3805c519d22..c97e58f121f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.h @@ -17,7 +17,7 @@ subject to the following restrictions: #define BT_TRIANGLE_BUFFER_H #include "btTriangleCallback.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" struct btTriangle { diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h index fbb87bc4fd8..7b2337498ec 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef TRIANGLE_CALLBACK_H #define TRIANGLE_CALLBACK_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" class btTriangleCallback diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp index 00847861cf1..554915a7058 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp @@ -4,8 +4,8 @@ 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, +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. @@ -18,27 +18,36 @@ subject to the following restrictions: btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride) { btIndexedMesh mesh; - + mesh.m_numTriangles = numTriangles; mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase; mesh.m_triangleIndexStride = triangleIndexStride; mesh.m_numVertices = numVertices; mesh.m_vertexBase = (const unsigned char *)vertexBase; mesh.m_vertexStride = vertexStride; - + addIndexedMesh(mesh); } +btTriangleIndexVertexArray::~btTriangleIndexVertexArray() +{ + +} + void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) { btAssert(subpart< getNumSubParts() ); - + btIndexedMesh& mesh = m_indexedMeshes[subpart]; numverts = mesh.m_numVertices; (*vertexbase) = (unsigned char *) mesh.m_vertexBase; + #ifdef BT_USE_DOUBLE_PRECISION + type = PHY_DOUBLE; + #else type = PHY_FLOAT; + #endif vertexStride = mesh.m_vertexStride; numfaces = mesh.m_numTriangles; @@ -54,7 +63,11 @@ void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned numverts = mesh.m_numVertices; (*vertexbase) = (const unsigned char *)mesh.m_vertexBase; + #ifdef BT_USE_DOUBLE_PRECISION + type = PHY_DOUBLE; + #else type = PHY_FLOAT; + #endif vertexStride = mesh.m_vertexStride; numfaces = mesh.m_numTriangles; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h index 6ab6a762b39..3441a8325e2 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h @@ -17,13 +17,17 @@ subject to the following restrictions: #define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H #include "btStridingMeshInterface.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btScalar.h" + ///IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements ///instead of the number of indices, we pass the number of triangles ///todo: explain with pictures ATTRIBUTE_ALIGNED16( struct) btIndexedMesh { + BT_DECLARE_ALIGNED_ALLOCATOR(); + int m_numTriangles; const unsigned char * m_triangleIndexBase; int m_triangleIndexStride; @@ -49,10 +53,14 @@ ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshIn public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + btTriangleIndexVertexArray() { } + virtual ~btTriangleIndexVertexArray(); + //just to be backwards compatible btTriangleIndexVertexArray(int numTriangleIndices,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h index 525f5336b48..83e5a56d16a 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h @@ -18,8 +18,8 @@ subject to the following restrictions: #define TRIANGLE_MESH_H #include "btStridingMeshInterface.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" ///TriangleMesh provides storage for a concave triangle mesh. It can be used as data for the btTriangleMeshShape. class btTriangleMesh : public btStridingMeshInterface diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp index ed81897b515..0d390c88b68 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp @@ -20,7 +20,6 @@ subject to the following restrictions: #include "LinearMath/btAabbUtil2.h" #include "BulletCollision/CollisionShapes/btCollisionMargin.h" -#include "stdio.h" btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface) : m_meshInterface(meshInterface) @@ -138,6 +137,7 @@ const btVector3& btTriangleMeshShape::getLocalScaling() const //#define DEBUG_TRIANGLE_MESH + void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const { struct FilteredCallback : public btInternalTriangleIndexCallback @@ -174,8 +174,7 @@ void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const - -void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { (void)mass; //moving concave objects not supported diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h index e6173e47640..6657fc09147 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h @@ -20,17 +20,19 @@ subject to the following restrictions: #include "btStridingMeshInterface.h" -///Concave triangle mesh. Uses an interface to access the triangles to allow for sharing graphics/physics triangles. +///Concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead. class btTriangleMeshShape : public btConcaveShape { protected: btVector3 m_localAabbMin; btVector3 m_localAabbMax; btStridingMeshInterface* m_meshInterface; - + + ///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class. + ///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead! + btTriangleMeshShape(btStridingMeshInterface* meshInterface); public: - btTriangleMeshShape(btStridingMeshInterface* meshInterface); virtual ~btTriangleMeshShape(); @@ -53,7 +55,7 @@ public: virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; @@ -70,7 +72,7 @@ public: //debugging - virtual char* getName()const {return "TRIANGLEMESH";} + virtual const char* getName()const {return "TRIANGLEMESH";} }; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h index c2e240c051c..064c64fa6ab 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h @@ -116,7 +116,7 @@ public: planeSupport = m_vertices1[0]; } - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const { (void)mass; btAssert(0); @@ -155,7 +155,7 @@ public: return false; } //debugging - virtual char* getName()const + virtual const char* getName()const { return "Triangle"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp new file mode 100644 index 00000000000..ef340286cb0 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp @@ -0,0 +1,114 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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. +*/ + +#include "btUniformScalingShape.h" + +btUniformScalingShape::btUniformScalingShape( btConvexShape* convexChildShape,btScalar uniformScalingFactor): +m_childConvexShape(convexChildShape), +m_uniformScalingFactor(uniformScalingFactor) +{ +} + +btUniformScalingShape::~btUniformScalingShape() +{ +} + + +btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + btVector3 tmpVertex; + tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec); + return tmpVertex*m_uniformScalingFactor; +} + +void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors); + int i; + for (i=0;ilocalGetSupportingVertex(vec); + return tmpVertex*m_uniformScalingFactor; +} + + +void btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + + ///this linear upscaling is not realistic, but we don't deal with large mass ratios... + btVector3 tmpInertia; + m_childConvexShape->calculateLocalInertia(mass,tmpInertia); + inertia = tmpInertia * m_uniformScalingFactor; +} + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btUniformScalingShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + m_childConvexShape->getAabb(t,aabbMin,aabbMax); + btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5); + btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor; + + aabbMin = aabbCenter - scaledAabbHalfExtends; + aabbMax = aabbCenter + scaledAabbHalfExtends; + +} + +void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax); + btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5); + btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor; + + aabbMin = aabbCenter - scaledAabbHalfExtends; + aabbMax = aabbCenter + scaledAabbHalfExtends; +} + +void btUniformScalingShape::setLocalScaling(const btVector3& scaling) +{ + m_childConvexShape->setLocalScaling(scaling); +} + +const btVector3& btUniformScalingShape::getLocalScaling() const +{ + return m_childConvexShape->getLocalScaling(); +} + +void btUniformScalingShape::setMargin(btScalar margin) +{ + m_childConvexShape->setMargin(margin); +} +btScalar btUniformScalingShape::getMargin() const +{ + return m_childConvexShape->getMargin() * m_uniformScalingFactor; +} + +int btUniformScalingShape::getNumPreferredPenetrationDirections() const +{ + return m_childConvexShape->getNumPreferredPenetrationDirections(); +} + +void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const +{ + m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h new file mode 100644 index 00000000000..3a0ecf021d3 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h @@ -0,0 +1,86 @@ +/* +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. +*/ + +#ifndef BT_UNIFORM_SCALING_SHAPE_H +#define BT_UNIFORM_SCALING_SHAPE_H + +#include "btConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + +class btUniformScalingShape : public btConvexShape +{ + btConvexShape* m_childConvexShape; + + btScalar m_uniformScalingFactor; + + public: + + btUniformScalingShape( btConvexShape* convexChildShape, btScalar uniformScalingFactor); + + virtual ~btUniformScalingShape(); + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + btScalar getUniformScalingFactor() const + { + return m_uniformScalingFactor; + } + + btConvexShape* getChildShape() + { + return m_childConvexShape; + } + + const btConvexShape* getChildShape() const + { + return m_childConvexShape; + } + + virtual const char* getName()const + { + return "UniformScalingShape"; + } + + virtual int getShapeType() const { return UNIFORM_SCALING_SHAPE_PROXYTYPE; } + + + /////////////////////////// + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void setLocalScaling(const btVector3& scaling) ; + virtual const btVector3& getLocalScaling() const ; + + virtual void setMargin(btScalar margin); + virtual btScalar getMargin() const; + + virtual int getNumPreferredPenetrationDirections() const; + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const; + + +}; + +#endif //BT_UNIFORM_SCALING_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp index 2c565734e97..c6a2b396d78 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp @@ -26,7 +26,7 @@ subject to the following restrictions: -btContinuousConvexCollision::btContinuousConvexCollision ( btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) +btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) :m_simplexSolver(simplexSolver), m_penetrationDepthSolver(penetrationDepthSolver), m_convexA(convexA),m_convexB(convexB) @@ -93,7 +93,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btGjkPairDetector::ClosestPointInput input; //we don't use margins during CCD - gjk.setIgnoreMargin(true); + // gjk.setIgnoreMargin(true); input.m_transformA = fromA; input.m_transformB = fromB; @@ -108,22 +108,26 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btScalar dist; dist = pointCollector1.m_distance; n = pointCollector1.m_normalOnBInWorld; - + + + //not close enough while (dist > radius) { numIter++; if (numIter > maxIter) + { return false; //todo: report a failure - + } btScalar dLambda = btScalar(0.); + btScalar projectedLinearVelocity = (linVelB-linVelA).dot(n); + //calculate safe moving fraction from distance / (linear+rotational velocity) //btScalar clippedDist = GEN_min(angularConservativeRadius,dist); //btScalar clippedDist = dist; - btScalar projectedLinearVelocity = (linVelB-linVelA).dot(n); dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); @@ -135,9 +139,14 @@ bool btContinuousConvexCollision::calcTimeOfImpact( if (lambda < btScalar(0.)) return false; + //todo: next check with relative epsilon if (lambda <= lastLambda) + { + return false; + //n.setValue(0,0,0); break; + } lastLambda = lambda; @@ -163,11 +172,12 @@ bool btContinuousConvexCollision::calcTimeOfImpact( { //degenerate ?! result.m_fraction = lastLambda; - result.m_normal = n; + n = pointCollector.m_normalOnBInWorld; + result.m_normal=n;//.setValue(1,1,1);// = n; return true; } c = pointCollector.m_pointInWorld; - + n = pointCollector.m_normalOnBInWorld; dist = pointCollector.m_distance; } else { diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h index 9901bab4b45..28c2b4d6156 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h @@ -30,13 +30,13 @@ class btContinuousConvexCollision : public btConvexCast { btSimplexSolverInterface* m_simplexSolver; btConvexPenetrationDepthSolver* m_penetrationDepthSolver; - btConvexShape* m_convexA; - btConvexShape* m_convexB; + const btConvexShape* m_convexA; + const btConvexShape* m_convexB; public: - btContinuousConvexCollision (btConvexShape* shapeA,btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); virtual bool calcTimeOfImpact( const btTransform& fromA, diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h index 3101b59993d..cc80f0aa8da 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h @@ -17,11 +17,11 @@ subject to the following restrictions: #ifndef CONVEX_CAST_H #define CONVEX_CAST_H -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btScalar.h" class btMinkowskiSumShape; -#include "../../LinearMath/btIDebugDraw.h" +#include "LinearMath/btIDebugDraw.h" /// btConvexCast is an interface for Casting class btConvexCast diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h index 7caeba4be45..99690921317 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h @@ -21,7 +21,7 @@ class btStackAlloc; class btVector3; #include "btSimplexSolverInterface.h" class btConvexShape; -#include "../../LinearMath/btPoint3.h" +#include "LinearMath/btPoint3.h" class btTransform; ///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation. @@ -31,7 +31,7 @@ public: virtual ~btConvexPenetrationDepthSolver() {}; virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - btConvexShape* convexA,btConvexShape* convexB, + const btConvexShape* convexA,const btConvexShape* convexB, const btTransform& transA,const btTransform& transB, btVector3& v, btPoint3& pa, btPoint3& pb, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h index 15000c1ab61..f11c8bd1290 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef DISCRETE_COLLISION_DETECTOR1_INTERFACE_H #define DISCRETE_COLLISION_DETECTOR1_INTERFACE_H -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" class btStackAlloc; /// This interface is made to be used by an iterative approach to do TimeOfImpact calculations diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp index 93edffeafd6..da2a02b9839 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp @@ -22,7 +22,7 @@ subject to the following restrictions: #include "btPointCollector.h" -btGjkConvexCast::btGjkConvexCast(btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) +btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) :m_simplexSolver(simplexSolver), m_convexA(convexA), m_convexB(convexB) diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h index 3905c45e6d6..a977c9e83f7 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h @@ -18,9 +18,9 @@ subject to the following restrictions: #ifndef GJK_CONVEX_CAST_H #define GJK_CONVEX_CAST_H -#include "../CollisionShapes/btCollisionMargin.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btConvexCast.h" class btConvexShape; class btMinkowskiSumShape; @@ -30,12 +30,12 @@ class btMinkowskiSumShape; class btGjkConvexCast : public btConvexCast { btSimplexSolverInterface* m_simplexSolver; - btConvexShape* m_convexA; - btConvexShape* m_convexB; + const btConvexShape* m_convexA; + const btConvexShape* m_convexB; public: - btGjkConvexCast(btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); + btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); /// cast a convex against another convex object virtual bool calcTimeOfImpact( diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp index 8abdfdbb7e5..f57868be044 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp @@ -580,8 +580,8 @@ using namespace gjkepa_impl; // -bool btGjkEpaSolver::Collide(btConvexShape *shape0,const btTransform &wtrs0, - btConvexShape *shape1,const btTransform &wtrs1, +bool btGjkEpaSolver::Collide(const btConvexShape *shape0,const btTransform &wtrs0, + const btConvexShape *shape1,const btTransform &wtrs1, btScalar radialmargin, btStackAlloc* stackAlloc, sResults& results) diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h index 759b30bb17f..1338e2714a8 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h @@ -21,7 +21,7 @@ Nov.2006 #ifndef _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ #define _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ -#include "../CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" class btStackAlloc; @@ -43,8 +43,8 @@ struct sResults int epa_iterations; int gjk_iterations; }; -static bool Collide(btConvexShape* shape0,const btTransform& wtrs0, - btConvexShape* shape1,const btTransform& wtrs1, +static bool Collide(const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, btScalar radialmargin, btStackAlloc* stackAlloc, sResults& results); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp index 87330493b60..9e600652333 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp @@ -20,7 +20,7 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver, - btConvexShape* pConvexA, btConvexShape* pConvexB, + const btConvexShape* pConvexA, const btConvexShape* pConvexB, const btTransform& transformA, const btTransform& transformB, btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc ) diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h index 3916ba0776c..2dc069ce5cf 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h @@ -26,7 +26,7 @@ class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver public : bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - btConvexShape* pConvexA, btConvexShape* pConvexB, + const btConvexShape* pConvexA, const btConvexShape* pConvexB, const btTransform& transformA, const btTransform& transformB, btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc ); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp index f1f3f7f7f6c..c5f50d4dd1a 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp @@ -35,7 +35,7 @@ int gNumGjkChecks = 0; -btGjkPairDetector::btGjkPairDetector(btConvexShape* objectA,btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) +btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) :m_cachedSeparatingAxis(btScalar(0.),btScalar(0.),btScalar(1.)), m_penetrationDepthSolver(penetrationDepthSolver), m_simplexSolver(simplexSolver), diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h index af0fe32f6c7..1ec51f74069 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h @@ -20,8 +20,8 @@ subject to the following restrictions: #define GJK_PAIR_DETECTOR_H #include "btDiscreteCollisionDetectorInterface.h" -#include "../../LinearMath/btPoint3.h" -#include "../CollisionShapes/btCollisionMargin.h" +#include "LinearMath/btPoint3.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" class btConvexShape; #include "btSimplexSolverInterface.h" @@ -35,8 +35,8 @@ class btGjkPairDetector : public btDiscreteCollisionDetectorInterface btVector3 m_cachedSeparatingAxis; btConvexPenetrationDepthSolver* m_penetrationDepthSolver; btSimplexSolverInterface* m_simplexSolver; - btConvexShape* m_minkowskiA; - btConvexShape* m_minkowskiB; + const btConvexShape* m_minkowskiA; + const btConvexShape* m_minkowskiB; bool m_ignoreMargin; @@ -49,7 +49,7 @@ public: int m_catchDegeneracies; - btGjkPairDetector(btConvexShape* objectA,btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); virtual ~btGjkPairDetector() {}; virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h index f6a893151da..1933d378f4f 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef MANIFOLD_CONTACT_POINT_H #define MANIFOLD_CONTACT_POINT_H -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransformUtil.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransformUtil.h" diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp index c4bab3a134a..100bc240764 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp @@ -71,7 +71,7 @@ btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver, - btConvexShape* convexA,btConvexShape* convexB, + const btConvexShape* convexA,const btConvexShape* convexB, const btTransform& transA,const btTransform& transB, btVector3& v, btPoint3& pa, btPoint3& pb, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc @@ -112,8 +112,7 @@ bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& s //just take fixed number of orientation, and sample the penetration depth in that direction btScalar minProj = btScalar(1e30); - btVector3 minNorm; - btVector3 minVertex; + btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.)); btVector3 minA,minB; btVector3 seperatingAxisInA,seperatingAxisInB; btVector3 pInA,qInB,pWorld,qWorld,w; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h index b348b21b52a..27b42c2b47e 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h @@ -25,7 +25,7 @@ class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver public: virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - btConvexShape* convexA,btConvexShape* convexB, + const btConvexShape* convexA,const btConvexShape* convexB, const btTransform& transA,const btTransform& transB, btVector3& v, btPoint3& pa, btPoint3& pb, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp index 08cb3ed334d..ee94ee01149 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp @@ -27,20 +27,12 @@ btPersistentManifold::btPersistentManifold() :m_body0(0), m_body1(0), m_cachedPoints (0), -m_index1(0) +m_index1a(0) { } -void btPersistentManifold::clearManifold() -{ - int i; - for (i=0;i @@ -198,10 +190,20 @@ btScalar btPersistentManifold::getContactBreakingThreshold() const return gContactBreakingThreshold; } + + void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB) { int i; - +#ifdef DEBUG_PERSISTENCY + printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n", + trA.getOrigin().getX(), + trA.getOrigin().getY(), + trA.getOrigin().getZ(), + trB.getOrigin().getX(), + trB.getOrigin().getY(), + trB.getOrigin().getZ()); +#endif //DEBUG_PERSISTENCY /// first refresh worldspace positions and distance for (i=getNumContacts()-1;i>=0;i--) { diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h index a5918b84db3..f0b1ce58db7 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h @@ -17,9 +17,10 @@ subject to the following restrictions: #define PERSISTENT_MANIFOLD_H -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" #include "btManifoldPoint.h" +#include "LinearMath/btAlignedAllocator.h" struct btCollisionResult; @@ -34,8 +35,13 @@ extern ContactDestroyedCallback gContactDestroyedCallback; #define MANIFOLD_CACHE_SIZE 4 -///btPersistentManifold maintains contact points, and reduces them to 4. -///It does contact filtering/contact reduction. +///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase. +///Those contact points are created by the collision narrow phase. +///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time. +///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large) +///reduces the cache to 4 points, when more then 4 points are added, using following rules: +///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points +///note that some pairs of objects might have more then one contact manifold. ATTRIBUTE_ALIGNED16( class) btPersistentManifold { @@ -55,20 +61,22 @@ ATTRIBUTE_ALIGNED16( class) btPersistentManifold public: - int m_index1; + BT_DECLARE_ALIGNED_ALLOCATOR(); + + int m_index1a; btPersistentManifold(); - btPersistentManifold(void* body0,void* body1) + btPersistentManifold(void* body0,void* body1,int bla) : m_body0(body0),m_body1(body1),m_cachedPoints(0) { } - inline void* getBody0() { return m_body0;} - inline void* getBody1() { return m_body1;} + SIMD_FORCE_INLINE void* getBody0() { return m_body0;} + SIMD_FORCE_INLINE void* getBody1() { return m_body1;} - inline const void* getBody0() const { return m_body0;} - inline const void* getBody1() const { return m_body1;} + SIMD_FORCE_INLINE const void* getBody0() const { return m_body0;} + SIMD_FORCE_INLINE const void* getBody1() const { return m_body1;} void setBodies(void* body0,void* body1) { @@ -82,15 +90,15 @@ public: void DebugPersistency(); #endif // - inline int getNumContacts() const { return m_cachedPoints;} + SIMD_FORCE_INLINE int getNumContacts() const { return m_cachedPoints;} - inline const btManifoldPoint& getContactPoint(int index) const + SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const { btAssert(index < m_cachedPoints); return m_pointCache[index]; } - inline btManifoldPoint& getContactPoint(int index) + SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index) { btAssert(index < m_cachedPoints); return m_pointCache[index]; @@ -114,6 +122,7 @@ public: m_pointCache[index] = m_pointCache[lastUsedIndex]; //get rid of duplicated userPersistentData pointer m_pointCache[lastUsedIndex].m_userPersistentData = 0; + m_pointCache[lastUsedIndex].m_lifeTime = 0; } btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0); @@ -147,7 +156,16 @@ public: /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin void refreshContactPoints( const btTransform& trA,const btTransform& trB); - void clearManifold(); + + SIMD_FORCE_INLINE void clearManifold() + { + int i; + for (i=0;i btConeTwistConstraint::btConeTwistConstraint() +:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE) { } btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame,const btTransform& rbBFrame) - :btTypedConstraint(rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), + :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), m_angularOnly(false) { // flip axis for correct angles @@ -49,7 +50,7 @@ btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, } btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) - :btTypedConstraint(rbA),m_rbAFrame(rbAFrame), + :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame), m_angularOnly(false) { m_rbBFrame = m_rbAFrame; @@ -205,7 +206,6 @@ void btConeTwistConstraint::solveConstraint(btScalar timeStep) btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); btScalar tau = btScalar(0.3); - btScalar damping = btScalar(1.); //linear part if (!m_angularOnly) @@ -247,7 +247,7 @@ void btConeTwistConstraint::solveConstraint(btScalar timeStep) // Clamp the accumulated impulse btScalar temp = m_accSwingLimitImpulse; - m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, 0.0f ); + m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); impulseMag = m_accSwingLimitImpulse - temp; btVector3 impulse = m_swingAxis * impulseMag; @@ -265,7 +265,7 @@ void btConeTwistConstraint::solveConstraint(btScalar timeStep) // Clamp the accumulated impulse btScalar temp = m_accTwistLimitImpulse; - m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, 0.0f ); + m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); impulseMag = m_accTwistLimitImpulse - temp; btVector3 impulse = m_twistAxis * impulseMag; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h index 874669c80b3..f121919c8f9 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -30,6 +30,9 @@ class btRigidBody; ///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc) class btConeTwistConstraint : public btTypedConstraint { +#ifdef IN_PARALLELL_SOLVER +public: +#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btTransform m_rbAFrame; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h index 7e8458c2c7b..addfb67a839 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef CONSTRAINT_SOLVER_H #define CONSTRAINT_SOLVER_H -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" class btPersistentManifold; class btRigidBody; @@ -26,7 +26,7 @@ struct btContactSolverInfo; struct btBroadphaseProxy; class btIDebugDraw; class btStackAlloc; - +class btDispatcher; /// btConstraintSolver provides solver interface class btConstraintSolver { @@ -35,8 +35,15 @@ public: virtual ~btConstraintSolver() {} - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) = 0; + virtual void prepareSolve (int numBodies, int numManifolds) {;} + ///solve a group of constraints + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) = 0; + + virtual void allSolved (const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) {;} + + ///clear internal cached data and reset random seed + virtual void reset() = 0; }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp index bb3fe832592..1588428503a 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp @@ -192,8 +192,8 @@ btScalar resolveSingleFriction( j1 = -vrel * cpd->m_jacDiagABInvTangent0; btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse0; cpd->m_accumulatedTangentImpulse0 = oldTangentImpulse + j1; - GEN_set_min(cpd->m_accumulatedTangentImpulse0, limit); - GEN_set_max(cpd->m_accumulatedTangentImpulse0, -limit); + btSetMin(cpd->m_accumulatedTangentImpulse0, limit); + btSetMax(cpd->m_accumulatedTangentImpulse0, -limit); j1 = cpd->m_accumulatedTangentImpulse0 - oldTangentImpulse; } @@ -206,8 +206,8 @@ btScalar resolveSingleFriction( j2 = -vrel * cpd->m_jacDiagABInvTangent1; btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse1; cpd->m_accumulatedTangentImpulse1 = oldTangentImpulse + j2; - GEN_set_min(cpd->m_accumulatedTangentImpulse1, limit); - GEN_set_max(cpd->m_accumulatedTangentImpulse1, -limit); + btSetMin(cpd->m_accumulatedTangentImpulse1, limit); + btSetMax(cpd->m_accumulatedTangentImpulse1, -limit); j2 = cpd->m_accumulatedTangentImpulse1 - oldTangentImpulse; } @@ -270,8 +270,8 @@ btScalar resolveSingleFrictionOriginal( // calculate j that moves us to zero relative velocity btScalar j = -vrel * cpd->m_jacDiagABInvTangent0; btScalar total = cpd->m_accumulatedTangentImpulse0 + j; - GEN_set_min(total, limit); - GEN_set_max(total, -limit); + btSetMin(total, limit); + btSetMax(total, -limit); j = total - cpd->m_accumulatedTangentImpulse0; cpd->m_accumulatedTangentImpulse0 = total; body1.applyImpulse(j * cpd->m_frictionWorldTangential0, rel_pos1); @@ -290,8 +290,8 @@ btScalar resolveSingleFrictionOriginal( // calculate j that moves us to zero relative velocity btScalar j = -vrel * cpd->m_jacDiagABInvTangent1; btScalar total = cpd->m_accumulatedTangentImpulse1 + j; - GEN_set_min(total, limit); - GEN_set_max(total, -limit); + btSetMin(total, limit); + btSetMax(total, -limit); j = total - cpd->m_accumulatedTangentImpulse1; cpd->m_accumulatedTangentImpulse1 = total; body1.applyImpulse(j * cpd->m_frictionWorldTangential1, rel_pos1); @@ -388,8 +388,8 @@ btScalar resolveSingleCollisionCombined( (body1.getInvMass() + body2.getInvMass() + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); btScalar normal_impulse = cpd->m_appliedImpulse * combinedFriction; - GEN_set_min(friction_impulse, normal_impulse); - GEN_set_max(friction_impulse, -normal_impulse); + btSetMin(friction_impulse, normal_impulse); + btSetMax(friction_impulse, -normal_impulse); body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1); body2.applyImpulse(lat_vel * friction_impulse, rel_pos2); } diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h index 0834deddeac..826e79f78bd 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h @@ -19,8 +19,8 @@ subject to the following restrictions: //todo: make into a proper class working with the iterative constraint solver class btRigidBody; -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btScalar.h" struct btContactSolverInfo; class btManifoldPoint; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h index c3c73e300f4..ad2c40e2107 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -16,8 +16,21 @@ subject to the following restrictions: #ifndef CONTACT_SOLVER_INFO #define CONTACT_SOLVER_INFO +struct btContactSolverInfoData +{ + btScalar m_tau; + btScalar m_damping; + btScalar m_friction; + btScalar m_timeStep; + btScalar m_restitution; + int m_numIterations; + btScalar m_maxErrorReduction; + btScalar m_sor; + btScalar m_erp; -struct btContactSolverInfo +}; + +struct btContactSolverInfo : public btContactSolverInfoData { inline btContactSolverInfo() @@ -32,16 +45,7 @@ struct btContactSolverInfo m_sor = btScalar(1.3); } - btScalar m_tau; - btScalar m_damping; - btScalar m_friction; - btScalar m_timeStep; - btScalar m_restitution; - int m_numIterations; - btScalar m_maxErrorReduction; - btScalar m_sor; - btScalar m_erp; - + }; #endif //CONTACT_SOLVER_INFO diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp index 747d10d1f8b..96d48f9f7dd 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp @@ -4,14 +4,20 @@ 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, +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. */ +/* +2007-09-09 +Refactored by Francisco León +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ #include "btGeneric6DofConstraint.h" @@ -19,371 +25,473 @@ subject to the following restrictions: #include "LinearMath/btTransformUtil.h" #include + static const btScalar kSign[] = { btScalar(1.0), btScalar(-1.0), btScalar(1.0) }; static const int kAxisA[] = { 1, 0, 0 }; static const int kAxisB[] = { 2, 2, 1 }; #define GENERIC_D6_DISABLE_WARMSTARTING 1 -btGeneric6DofConstraint::btGeneric6DofConstraint() +btScalar btGetMatrixElem(const btMatrix3x3& mat, int index) { -} - -btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB) -: btTypedConstraint(rbA, rbB) -, m_frameInA(frameInA) -, m_frameInB(frameInB) -{ - //free means upper < lower, - //locked means upper == lower - //limited means upper > lower - //so start all locked - for (int i=0; i<6;++i) - { - m_lowerLimit[i] = btScalar(0.0); - m_upperLimit[i] = btScalar(0.0); - m_accumulatedImpulse[i] = btScalar(0.0); - } - -} - - -void btGeneric6DofConstraint::buildJacobian() -{ - btVector3 localNormalInA(0,0,0); - - const btVector3& pivotInA = m_frameInA.getOrigin(); - const btVector3& pivotInB = m_frameInB.getOrigin(); - - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_frameInA.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_frameInB.getOrigin(); - - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - int i; - //linear part - for (i=0;i<3;i++) - { - if (isLimited(i)) - { - localNormalInA[i] = 1; - btVector3 normalWorld = m_rbA.getCenterOfMassTransform().getBasis() * localNormalInA; - - - // Create linear atom - new (&m_jacLinear[i]) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getCenterOfMassTransform()*pivotInA - m_rbA.getCenterOfMassPosition(), - m_rbB.getCenterOfMassTransform()*pivotInB - m_rbB.getCenterOfMassPosition(), - normalWorld, - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); - - //optionally disable warmstarting -#ifdef GENERIC_D6_DISABLE_WARMSTARTING - m_accumulatedImpulse[i] = btScalar(0.); -#endif //GENERIC_D6_DISABLE_WARMSTARTING - - // Apply accumulated impulse - btVector3 impulse_vector = m_accumulatedImpulse[i] * normalWorld; - - m_rbA.applyImpulse( impulse_vector, rel_pos1); - m_rbB.applyImpulse(-impulse_vector, rel_pos2); - - localNormalInA[i] = 0; - } - } - - // angular part - for (i=0;i<3;i++) - { - if (isLimited(i+3)) - { - btVector3 axisA = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn( kAxisA[i] ); - btVector3 axisB = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn( kAxisB[i] ); - - // Dirk: This is IMO mathematically the correct way, but we should consider axisA and axisB being near parallel maybe - btVector3 axis = kSign[i] * axisA.cross(axisB); - - // Create angular atom - new (&m_jacAng[i]) btJacobianEntry(axis, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - -#ifdef GENERIC_D6_DISABLE_WARMSTARTING - m_accumulatedImpulse[i + 3] = btScalar(0.); -#endif //GENERIC_D6_DISABLE_WARMSTARTING - - // Apply accumulated impulse - btVector3 impulse_vector = m_accumulatedImpulse[i + 3] * axis; - - m_rbA.applyTorqueImpulse( impulse_vector); - m_rbB.applyTorqueImpulse(-impulse_vector); - } - } -} - -btScalar getMatrixElem(const btMatrix3x3& mat,int index) -{ - int row = index%3; - int col = index / 3; - return mat[row][col]; + int i = index%3; + int j = index/3; + return mat[i][j]; } ///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html -bool MatrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) +bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) { - // rot = cy*cz -cy*sz sy - // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx - // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy +// // rot = cy*cz -cy*sz sy +// // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx +// // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy +// + + if (btGetMatrixElem(mat,2) < btScalar(1.0)) + { + if (btGetMatrixElem(mat,2) > btScalar(-1.0)) + { + xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); + xyz[1] = btAsin(btGetMatrixElem(mat,2)); + xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); + return true; + } + else + { + // WARNING. Not unique. XA - ZA = -atan2(r10,r11) + xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[1] = -SIMD_HALF_PI; + xyz[2] = btScalar(0.0); + return false; + } + } + else + { + // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) + xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[1] = SIMD_HALF_PI; + xyz[2] = 0.0; + + } -/// 0..8 - if (getMatrixElem(mat,2) < btScalar(1.0)) - { - if (getMatrixElem(mat,2) > btScalar(-1.0)) - { - xyz[0] = btAtan2(-getMatrixElem(mat,5),getMatrixElem(mat,8)); - xyz[1] = btAsin(getMatrixElem(mat,2)); - xyz[2] = btAtan2(-getMatrixElem(mat,1),getMatrixElem(mat,0)); - return true; - } - else - { - // WARNING. Not unique. XA - ZA = -atan2(r10,r11) - xyz[0] = -btAtan2(getMatrixElem(mat,3),getMatrixElem(mat,4)); - xyz[1] = -SIMD_HALF_PI; - xyz[2] = btScalar(0.0); - return false; - } - } - else - { - // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) - xyz[0] = btAtan2(getMatrixElem(mat,3),getMatrixElem(mat,4)); - xyz[1] = SIMD_HALF_PI; - xyz[2] = 0.0; - - } - return false; } -void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) + +//////////////////////////// btRotationalLimitMotor //////////////////////////////////// + + +int btRotationalLimitMotor::testLimitValue(btScalar test_value) { - btScalar tau = btScalar(0.1); - btScalar damping = btScalar(1.0); - - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_frameInA.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_frameInB.getOrigin(); - - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 localNormalInA(0,0,0); - int i; - - // linear - for (i=0;i<3;i++) - { - if (isLimited(i)) - { - btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); - btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); - - localNormalInA.setValue(0,0,0); - localNormalInA[i] = 1; - btVector3 normalWorld = m_rbA.getCenterOfMassTransform().getBasis() * localNormalInA; - - btScalar jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); - - //velocity error (first order error) - btScalar rel_vel = m_jacLinear[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, - m_rbB.getLinearVelocity(),angvelB); - - //positional error (zeroth order error) - btScalar depth = -(pivotAInW - pivotBInW).dot(normalWorld); - btScalar lo = btScalar(-1e30); - btScalar hi = btScalar(1e30); - - //handle the limits - if (m_lowerLimit[i] < m_upperLimit[i]) - { - { - if (depth > m_upperLimit[i]) - { - depth -= m_upperLimit[i]; - lo = btScalar(0.); - - } else - { - if (depth < m_lowerLimit[i]) - { - depth -= m_lowerLimit[i]; - hi = btScalar(0.); - } else - { - continue; - } - } - } - } - - btScalar normalImpulse= (tau*depth/timeStep - damping*rel_vel) * jacDiagABInv; - btScalar oldNormalImpulse = m_accumulatedImpulse[i]; - btScalar sum = oldNormalImpulse + normalImpulse; - m_accumulatedImpulse[i] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; - normalImpulse = m_accumulatedImpulse[i] - oldNormalImpulse; - - btVector3 impulse_vector = normalWorld * normalImpulse; - m_rbA.applyImpulse( impulse_vector, rel_pos1); - m_rbB.applyImpulse(-impulse_vector, rel_pos2); - - localNormalInA[i] = 0; - } - } - - btVector3 axis; - btScalar angle; - btTransform frameAWorld = m_rbA.getCenterOfMassTransform() * m_frameInA; - btTransform frameBWorld = m_rbB.getCenterOfMassTransform() * m_frameInB; - - btTransformUtil::calculateDiffAxisAngle(frameAWorld,frameBWorld,axis,angle); - btQuaternion diff(axis,angle); - btMatrix3x3 diffMat (diff); - btVector3 xyz; - ///this is not perfect, we can first check which axis are limited, and choose a more appropriate order - MatrixToEulerXYZ(diffMat,xyz); - - // angular - for (i=0;i<3;i++) + if(m_loLimit>m_hiLimit) { - if (isLimited(i+3)) - { - btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); - btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); - - btScalar jacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); - - //velocity error (first order error) - btScalar rel_vel = m_jacAng[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, - m_rbB.getLinearVelocity(),angvelB); - - //positional error (zeroth order error) - btVector3 axisA = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn( kAxisA[i] ); - btVector3 axisB = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn( kAxisB[i] ); - - btScalar rel_pos = kSign[i] * axisA.dot(axisB); - - btScalar lo = btScalar(-1e30); - btScalar hi = btScalar(1e30); - - //handle the twist limit - if (m_lowerLimit[i+3] < m_upperLimit[i+3]) - { - //clamp the values - btScalar loLimit = m_lowerLimit[i+3] > -3.1415 ? m_lowerLimit[i+3] : btScalar(-1e30); - btScalar hiLimit = m_upperLimit[i+3] < 3.1415 ? m_upperLimit[i+3] : btScalar(1e30); - - btScalar projAngle = btScalar(-1.)*xyz[i]; - - if (projAngle < loLimit) - { - hi = btScalar(0.); - rel_pos = (loLimit - projAngle); - } else - { - if (projAngle > hiLimit) - { - lo = btScalar(0.); - rel_pos = (hiLimit - projAngle); - } else - { - continue; - } - } - } - - //impulse - - btScalar normalImpulse= -(tau*rel_pos/timeStep + damping*rel_vel) * jacDiagABInv; - btScalar oldNormalImpulse = m_accumulatedImpulse[i+3]; - btScalar sum = oldNormalImpulse + normalImpulse; - m_accumulatedImpulse[i+3] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; - normalImpulse = m_accumulatedImpulse[i+3] - oldNormalImpulse; - - // Dirk: Not needed - we could actually project onto Jacobian entry here (same as above) - btVector3 axis = kSign[i] * axisA.cross(axisB); - btVector3 impulse_vector = axis * normalImpulse; - - m_rbA.applyTorqueImpulse( impulse_vector); - m_rbB.applyTorqueImpulse(-impulse_vector); - } + m_currentLimit = 0;//Free from violation + return 0; } + + if (test_value < m_loLimit) + { + m_currentLimit = 1;//low limit violation + m_currentLimitError = test_value - m_loLimit; + return 1; + } + else if (test_value> m_hiLimit) + { + m_currentLimit = 2;//High limit violation + m_currentLimitError = test_value - m_hiLimit; + return 2; + } + else + { + m_currentLimit = 0;//Free from violation + return 0; + } + return 0; +} + + +btScalar btRotationalLimitMotor::solveAngularLimits( + btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, + btRigidBody * body0, btRigidBody * body1) +{ + if (needApplyTorques()==false) return 0.0f; + + btScalar target_velocity = m_targetVelocity; + btScalar maxMotorForce = m_maxMotorForce; + + //current error correction + if (m_currentLimit!=0) + { + target_velocity = -m_ERP*m_currentLimitError/(timeStep); + maxMotorForce = m_maxLimitForce; + } + + maxMotorForce *= timeStep; + + // current velocity difference + btVector3 vel_diff = body0->getAngularVelocity(); + if (body1) + { + vel_diff -= body1->getAngularVelocity(); + } + + + + btScalar rel_vel = axis.dot(vel_diff); + + // correction velocity + btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel); + + + if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON ) + { + return 0.0f;//no need for applying force + } + + + // correction impulse + btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv; + + // clip correction impulse + btScalar clippedMotorImpulse; + + //todo: should clip against accumulated impulse + if (unclippedMotorImpulse>0.0f) + { + clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse; + } + else + { + clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse; + } + + + // sort with accumulated impulses + btScalar lo = btScalar(-1e30); + btScalar hi = btScalar(1e30); + + btScalar oldaccumImpulse = m_accumulatedImpulse; + btScalar sum = oldaccumImpulse + clippedMotorImpulse; + m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + + clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; + + + + btVector3 motorImp = clippedMotorImpulse * axis; + + + body0->applyTorqueImpulse(motorImp); + if (body1) body1->applyTorqueImpulse(-motorImp); + + return clippedMotorImpulse; + + +} + +//////////////////////////// End btRotationalLimitMotor //////////////////////////////////// + +//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// +btScalar btTranslationalLimitMotor::solveLinearAxis( + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1,const btVector3 &pointInA, + btRigidBody& body2,const btVector3 &pointInB, + int limit_index, + const btVector3 & axis_normal_on_a) +{ + +///find relative velocity + btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); + + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar rel_vel = axis_normal_on_a.dot(vel); + + + +/// apply displacement correction + +//positional error (zeroth order error) + btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); + btScalar lo = btScalar(-1e30); + btScalar hi = btScalar(1e30); + + btScalar minLimit = m_lowerLimit[limit_index]; + btScalar maxLimit = m_upperLimit[limit_index]; + + //handle the limits + if (minLimit < maxLimit) + { + { + if (depth > maxLimit) + { + depth -= maxLimit; + lo = btScalar(0.); + + } + else + { + if (depth < minLimit) + { + depth -= minLimit; + hi = btScalar(0.); + } + else + { + return 0.0f; + } + } + } + } + + btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; + + + + + btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; + btScalar sum = oldNormalImpulse + normalImpulse; + m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; + + btVector3 impulse_vector = axis_normal_on_a * normalImpulse; + body1.applyImpulse( impulse_vector, rel_pos1); + body2.applyImpulse(-impulse_vector, rel_pos2); + return normalImpulse; +} + +//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// + + +btGeneric6DofConstraint::btGeneric6DofConstraint() + :btTypedConstraint(D6_CONSTRAINT_TYPE), + m_useLinearReferenceFrameA(true) +{ +} + +btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) + : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB) + , m_frameInA(frameInA) + , m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) +{ + +} + + + + + +void btGeneric6DofConstraint::calculateAngleInfo() +{ + btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis(); + + matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); + + + + // in euler angle mode we do not actually constrain the angular velocity + // along the axes axis[0] and axis[2] (although we do use axis[1]) : + // + // to get constrain w2-w1 along ...not + // ------ --------------------- ------ + // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] + // d(angle[1])/dt = 0 ax[1] + // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] + // + // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. + // to prove the result for angle[0], write the expression for angle[0] from + // GetInfo1 then take the derivative. to prove this for angle[2] it is + // easier to take the euler rate expression for d(angle[2])/dt with respect + // to the components of w and set that to 0. + + btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0); + btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2); + + m_calculatedAxis[1] = axis2.cross(axis0); + m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2); + m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); + + +// if(m_debugDrawer) +// { +// +// char buff[300]; +// sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", +// m_calculatedAxisAngleDiff[0], +// m_calculatedAxisAngleDiff[1], +// m_calculatedAxisAngleDiff[2]); +// m_debugDrawer->reportErrorWarning(buff); +// } + +} + +void btGeneric6DofConstraint::calculateTransforms() +{ + m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; + m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; + + calculateAngleInfo(); +} + + +void btGeneric6DofConstraint::buildLinearJacobian( + btJacobianEntry & jacLinear,const btVector3 & normalWorld, + const btVector3 & pivotAInW,const btVector3 & pivotBInW) +{ + new (&jacLinear) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normalWorld, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + +} + +void btGeneric6DofConstraint::buildAngularJacobian( + btJacobianEntry & jacAngular,const btVector3 & jointAxisW) +{ + new (&jacAngular) btJacobianEntry(jointAxisW, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + +} + +bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index) +{ + btScalar angle = m_calculatedAxisAngleDiff[axis_index]; + + //test limits + m_angularLimits[axis_index].testLimitValue(angle); + return m_angularLimits[axis_index].needApplyTorques(); +} + +void btGeneric6DofConstraint::buildJacobian() +{ + //calculates transform + calculateTransforms(); + + const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); + const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); + + + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 normalWorld; + int i; + //linear part + for (i=0;i<3;i++) + { + if (m_linearLimits.isLimited(i)) + { + if (m_useLinearReferenceFrameA) + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + else + normalWorld = m_calculatedTransformB.getBasis().getColumn(i); + + buildLinearJacobian( + m_jacLinear[i],normalWorld , + pivotAInW,pivotBInW); + + } + } + + // angular part + for (i=0;i<3;i++) + { + //calculates error angle + if (testAngularLimitMotor(i)) + { + normalWorld = this->getAxis(i); + // Create angular atom + buildAngularJacobian(m_jacAng[i],normalWorld); + } + } + + +} + + +void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) +{ + m_timeStep = timeStep; + + //calculateTransforms(); + + int i; + + // linear + + btVector3 pointInA = m_calculatedTransformA.getOrigin(); + btVector3 pointInB = m_calculatedTransformB.getOrigin(); + + btScalar jacDiagABInv; + btVector3 linear_axis; + for (i=0;i<3;i++) + { + if (m_linearLimits.isLimited(i)) + { + jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); + + if (m_useLinearReferenceFrameA) + linear_axis = m_calculatedTransformA.getBasis().getColumn(i); + else + linear_axis = m_calculatedTransformB.getBasis().getColumn(i); + + m_linearLimits.solveLinearAxis( + m_timeStep, + jacDiagABInv, + m_rbA,pointInA, + m_rbB,pointInB, + i,linear_axis); + + } + } + + // angular + btVector3 angular_axis; + btScalar angularJacDiagABInv; + for (i=0;i<3;i++) + { + if (m_angularLimits[i].needApplyTorques()) + { + + // get axis + angular_axis = getAxis(i); + + angularJacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); + + m_angularLimits[i].solveAngularLimits(m_timeStep,angular_axis,angularJacDiagABInv, &m_rbA,&m_rbB); + } + } } void btGeneric6DofConstraint::updateRHS(btScalar timeStep) { - (void)timeStep; + (void)timeStep; } -btScalar btGeneric6DofConstraint::computeAngle(int axis) const - { - btScalar angle = btScalar(0.f); +btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const +{ + return m_calculatedAxis[axis_index]; +} - switch (axis) - { - case 0: - { - btVector3 v1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(1); - btVector3 v2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(1); - btVector3 w2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(2); +btScalar btGeneric6DofConstraint::getAngle(int axis_index) const +{ + return m_calculatedAxisAngleDiff[axis_index]; +} - btScalar s = v1.dot(w2); - btScalar c = v1.dot(v2); - - angle = btAtan2( s, c ); - } - break; - - case 1: - { - btVector3 w1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(2); - btVector3 w2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(2); - btVector3 u2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(0); - - btScalar s = w1.dot(u2); - btScalar c = w1.dot(w2); - - angle = btAtan2( s, c ); - } - break; - - case 2: - { - btVector3 u1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(0); - btVector3 u2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(0); - btVector3 v2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(1); - - btScalar s = u1.dot(v2); - btScalar c = u1.dot(u2); - - angle = btAtan2( s, c ); - } - break; - default: - btAssert ( 0 ) ; - - break ; - } - - return angle; - } diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h index b114e54fa69..e4683b91b9e 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h @@ -4,116 +4,429 @@ 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, +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. */ +/* +2007-09-09 +btGeneric6DofConstraint Refactored by Francisco León +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ + #ifndef GENERIC_6DOF_CONSTRAINT_H #define GENERIC_6DOF_CONSTRAINT_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" class btRigidBody; +//! Rotation Limit structure for generic joints +class btRotationalLimitMotor +{ +public: + //! limit_parameters + //!@{ + btScalar m_loLimit;//!< joint limit + btScalar m_hiLimit;//!< joint limit + btScalar m_targetVelocity;//!< target motor velocity + btScalar m_maxMotorForce;//!< max force on motor + btScalar m_maxLimitForce;//!< max force on limit + btScalar m_damping;//!< Damping. + btScalar m_limitSoftness;//! Relaxation factor + btScalar m_ERP;//!< Error tolerance factor when joint is at limit + btScalar m_bounce;//!< restitution factor + bool m_enableMotor; + + //!@} + + //! temp_variables + //!@{ + btScalar m_currentLimitError;//! How much is violated this limit + int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit + btScalar m_accumulatedImpulse; + //!@} + + btRotationalLimitMotor() + { + m_accumulatedImpulse = 0.f; + m_targetVelocity = 0; + m_maxMotorForce = 0.1f; + m_maxLimitForce = 300.0f; + m_loLimit = -SIMD_INFINITY; + m_hiLimit = SIMD_INFINITY; + m_ERP = 0.5f; + m_bounce = 0.0f; + m_damping = 1.0f; + m_limitSoftness = 0.5f; + m_currentLimit = 0; + m_currentLimitError = 0; + m_enableMotor = false; + } + + btRotationalLimitMotor(const btRotationalLimitMotor & limot) + { + m_targetVelocity = limot.m_targetVelocity; + m_maxMotorForce = limot.m_maxMotorForce; + m_limitSoftness = limot.m_limitSoftness; + m_loLimit = limot.m_loLimit; + m_hiLimit = limot.m_hiLimit; + m_ERP = limot.m_ERP; + m_bounce = limot.m_bounce; + m_currentLimit = limot.m_currentLimit; + m_currentLimitError = limot.m_currentLimitError; + m_enableMotor = limot.m_enableMotor; + } + + + + //! Is limited + bool isLimited() + { + if(m_loLimit>=m_hiLimit) return false; + return true; + } + + //! Need apply correction + bool needApplyTorques() + { + if(m_currentLimit == 0 && m_enableMotor == false) return false; + return true; + } + + //! calculates error + /*! + calculates m_currentLimit and m_currentLimitError. + */ + int testLimitValue(btScalar test_value); + + //! apply the correction impulses for two bodies + btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1); + + +}; + + + +class btTranslationalLimitMotor +{ +public: + btVector3 m_lowerLimit;//!< the constraint lower limits + btVector3 m_upperLimit;//!< the constraint upper limits + btVector3 m_accumulatedImpulse; + //! Linear_Limit_parameters + //!@{ + btScalar m_limitSoftness;//!< Softness for linear limit + btScalar m_damping;//!< Damping for linear limit + btScalar m_restitution;//! Bounce parameter for linear limit + //!@} + + btTranslationalLimitMotor() + { + m_lowerLimit.setValue(0.f,0.f,0.f); + m_upperLimit.setValue(0.f,0.f,0.f); + m_accumulatedImpulse.setValue(0.f,0.f,0.f); + + m_limitSoftness = 0.7f; + m_damping = btScalar(1.0f); + m_restitution = btScalar(0.5f); + } + + btTranslationalLimitMotor(const btTranslationalLimitMotor & other ) + { + m_lowerLimit = other.m_lowerLimit; + m_upperLimit = other.m_upperLimit; + m_accumulatedImpulse = other.m_accumulatedImpulse; + + m_limitSoftness = other.m_limitSoftness ; + m_damping = other.m_damping; + m_restitution = other.m_restitution; + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + inline bool isLimited(int limitIndex) + { + return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); + } + + + btScalar solveLinearAxis( + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1,const btVector3 &pointInA, + btRigidBody& body2,const btVector3 &pointInB, + int limit_index, + const btVector3 & axis_normal_on_a); + + +}; /// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space -/// btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked' -/// Work in progress (is still a Hinge actually) +/*! +btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'. +currently this limit supports rotational motors
+
    +
  • For Linear limits, use btGeneric6DofConstraint.setLinearUpperLimit, btGeneric6DofConstraint.setLinearLowerLimit. You can set the parameters with the btTranslationalLimitMotor structure accsesible through the btGeneric6DofConstraint.getTranslationalLimitMotor method. +At this moment translational motors are not supported. May be in the future.
  • + +
  • For Angular limits, use the btRotationalLimitMotor structure for configuring the limit. +This is accessible through btGeneric6DofConstraint.getLimitMotor method, +This brings support for limit parameters and motors.
  • + +
  • Angulars limits have these possible ranges: + +AXIS + + + + + + + + + + + + +
    MIN ANGLEMAX ANGLEX-PIPIY-PI/2PI/2Z-PI/2PI/2
    +
  • +
+ +*/ class btGeneric6DofConstraint : public btTypedConstraint { - btJacobianEntry m_jacLinear[3]; // 3 orthogonal linear constraints - btJacobianEntry m_jacAng[3]; // 3 orthogonal angular constraints +protected: - btTransform m_frameInA; // the constraint space w.r.t body A - btTransform m_frameInB; // the constraint space w.r.t body B + //! relative_frames + //!@{ + btTransform m_frameInA;//!< the constraint space w.r.t body A + btTransform m_frameInB;//!< the constraint space w.r.t body B + //!@} + + //! Jacobians + //!@{ + btJacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints + btJacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints + //!@} + + //! Linear_Limit_parameters + //!@{ + btTranslationalLimitMotor m_linearLimits; + //!@} + + + //! hinge_parameters + //!@{ + btRotationalLimitMotor m_angularLimits[3]; + //!@} + + +protected: + //! temporal variables + //!@{ + btScalar m_timeStep; + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; + btVector3 m_calculatedAxisAngleDiff; + btVector3 m_calculatedAxis[3]; + + bool m_useLinearReferenceFrameA; + + //!@} + + btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) + { + btAssert(0); + (void) other; + return *this; + } + + + + void buildLinearJacobian( + btJacobianEntry & jacLinear,const btVector3 & normalWorld, + const btVector3 & pivotAInW,const btVector3 & pivotBInW); + + void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW); + + + //! calcs the euler angles between the two bodies. + void calculateAngleInfo(); - btScalar m_lowerLimit[6]; // the constraint lower limits - btScalar m_upperLimit[6]; // the constraint upper limits - btScalar m_accumulatedImpulse[6]; - btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) - { - btAssert(0); - (void) other; - return *this; - } - public: - btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ); + btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); - btGeneric6DofConstraint(); + btGeneric6DofConstraint(); - - virtual void buildJacobian(); + //! Calcs global transform of the offsets + /*! + Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies. + \sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo + */ + void calculateTransforms(); - virtual void solveConstraint(btScalar timeStep); + //! Gets the global transform of the offset for body A + /*! + \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. + */ + const btTransform & getCalculatedTransformA() const + { + return m_calculatedTransformA; + } - void updateRHS(btScalar timeStep); + //! Gets the global transform of the offset for body B + /*! + \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. + */ + const btTransform & getCalculatedTransformB() const + { + return m_calculatedTransformB; + } - btScalar computeAngle(int axis) const; + const btTransform & getFrameOffsetA() const + { + return m_frameInA; + } - void setLinearLowerLimit(const btVector3& linearLower) - { - m_lowerLimit[0] = linearLower.getX(); - m_lowerLimit[1] = linearLower.getY(); - m_lowerLimit[2] = linearLower.getZ(); - } + const btTransform & getFrameOffsetB() const + { + return m_frameInB; + } - void setLinearUpperLimit(const btVector3& linearUpper) - { - m_upperLimit[0] = linearUpper.getX(); - m_upperLimit[1] = linearUpper.getY(); - m_upperLimit[2] = linearUpper.getZ(); - } - void setAngularLowerLimit(const btVector3& angularLower) - { - m_lowerLimit[3] = angularLower.getX(); - m_lowerLimit[4] = angularLower.getY(); - m_lowerLimit[5] = angularLower.getZ(); - } + btTransform & getFrameOffsetA() + { + return m_frameInA; + } - void setAngularUpperLimit(const btVector3& angularUpper) - { - m_upperLimit[3] = angularUpper.getX(); - m_upperLimit[4] = angularUpper.getY(); - m_upperLimit[5] = angularUpper.getZ(); - } + btTransform & getFrameOffsetB() + { + return m_frameInB; + } - //first 3 are linear, next 3 are angular - void SetLimit(int axis, btScalar lo, btScalar hi) - { - m_lowerLimit[axis] = lo; - m_upperLimit[axis] = hi; - } - //free means upper < lower, - //locked means upper == lower - //limited means upper > lower - //limitIndex: first 3 are linear, next 3 are angular - bool isLimited(int limitIndex) - { - return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); - } + //! performs Jacobian calculation, and also calculates angle differences and axis + virtual void buildJacobian(); + + virtual void solveConstraint(btScalar timeStep); + + void updateRHS(btScalar timeStep); + + //! Get the rotation axis in global coordinates + /*! + \pre btGeneric6DofConstraint.buildJacobian must be called previously. + */ + btVector3 getAxis(int axis_index) const; + + //! Get the relative Euler angle + /*! + \pre btGeneric6DofConstraint.buildJacobian must be called previously. + */ + btScalar getAngle(int axis_index) const; + + //! Test angular limit. + /*! + Calculates angular correction and returns true if limit needs to be corrected. + \pre btGeneric6DofConstraint.buildJacobian must be called previously. + */ + bool testAngularLimitMotor(int axis_index); + + void setLinearLowerLimit(const btVector3& linearLower) + { + m_linearLimits.m_lowerLimit = linearLower; + } + + void setLinearUpperLimit(const btVector3& linearUpper) + { + m_linearLimits.m_upperLimit = linearUpper; + } + + void setAngularLowerLimit(const btVector3& angularLower) + { + m_angularLimits[0].m_loLimit = angularLower.getX(); + m_angularLimits[1].m_loLimit = angularLower.getY(); + m_angularLimits[2].m_loLimit = angularLower.getZ(); + } + + void setAngularUpperLimit(const btVector3& angularUpper) + { + m_angularLimits[0].m_hiLimit = angularUpper.getX(); + m_angularLimits[1].m_hiLimit = angularUpper.getY(); + m_angularLimits[2].m_hiLimit = angularUpper.getZ(); + } + + //! Retrieves the angular limit informacion + btRotationalLimitMotor * getRotationalLimitMotor(int index) + { + return &m_angularLimits[index]; + } + + //! Retrieves the limit informacion + btTranslationalLimitMotor * getTranslationalLimitMotor() + { + return &m_linearLimits; + } + + //first 3 are linear, next 3 are angular + void setLimit(int axis, btScalar lo, btScalar hi) + { + if(axis<3) + { + m_linearLimits.m_lowerLimit[axis] = lo; + m_linearLimits.m_upperLimit[axis] = hi; + } + else + { + m_angularLimits[axis-3].m_loLimit = lo; + m_angularLimits[axis-3].m_hiLimit = hi; + } + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + bool isLimited(int limitIndex) + { + if(limitIndex<3) + { + return m_linearLimits.isLimited(limitIndex); + + } + return m_angularLimits[limitIndex-3].isLimited(); + } + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } - const btRigidBody& getRigidBodyA() const - { - return m_rbA; - } - const btRigidBody& getRigidBodyB() const - { - return m_rbB; - } - }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp index 27e30987549..f71698fa6ee 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -17,58 +17,180 @@ subject to the following restrictions: #include "btHingeConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" +#include "LinearMath/btMinMax.h" #include -btHingeConstraint::btHingeConstraint(): + +btHingeConstraint::btHingeConstraint() +: btTypedConstraint (HINGE_CONSTRAINT_TYPE), m_enableAngularMotor(false) { } btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, - btVector3& axisInA,btVector3& axisInB) -:btTypedConstraint(rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB), -m_axisInA(axisInA), -m_axisInB(-axisInB), -m_angularOnly(false), -m_enableAngularMotor(false) + btVector3& axisInA,btVector3& axisInB) + :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB), + m_angularOnly(false), + m_enableAngularMotor(false) { + m_rbAFrame.getOrigin() = pivotInA; + + // since no frame is given, assume this to be zero angle and just pick rb transform axis + btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); + btScalar projection = rbAxisA1.dot(axisInA); + if (projection > SIMD_EPSILON) + rbAxisA1 = rbAxisA1*projection - axisInA; + else + rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + + btVector3 rbAxisA2 = rbAxisA1.cross(axisInA); + + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = rbAxisB1.cross(axisInB); + + + m_rbBFrame.getOrigin() = pivotInB; + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),-axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),-axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),-axisInB.getZ() ); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; } btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA) -:btTypedConstraint(rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), -m_axisInA(axisInA), -//fixed axis in worldspace -m_axisInB(rbA.getCenterOfMassTransform().getBasis() * -axisInA), +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false) +{ + + // since no frame is given, assume this to be zero angle and just pick rb transform axis + // fixed axis in worldspace + btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); + btScalar projection = rbAxisA1.dot(axisInA); + if (projection > SIMD_EPSILON) + rbAxisA1 = rbAxisA1*projection - axisInA; + else + rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + + btVector3 rbAxisA2 = axisInA.cross(rbAxisA1); + + m_rbAFrame.getOrigin() = pivotInA; + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + + btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * -axisInA; + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + + m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA); + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +} + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, + const btTransform& rbAFrame, const btTransform& rbBFrame) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), m_angularOnly(false), m_enableAngularMotor(false) { - + // flip axis + m_rbBFrame.getBasis()[0][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +} + + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame), +m_angularOnly(false), +m_enableAngularMotor(false) +{ + ///not providing rigidbody B means implicitly using worldspace for body B + + // flip axis + m_rbBFrame.getBasis()[0][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); + + m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin()); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; } void btHingeConstraint::buildJacobian() { m_appliedImpulse = btScalar(0.); - btVector3 normal(0,0,0); - if (!m_angularOnly) { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 relPos = pivotBInW - pivotAInW; + + btVector3 normal[3]; + if (relPos.length2() > SIMD_EPSILON) + { + normal[0] = relPos.normalized(); + } + else + { + normal[0].setValue(btScalar(1.0),0,0); + } + + btPlaneSpace1(normal[0], normal[1], normal[2]); + for (int i=0;i<3;i++) { - normal[i] = 1; new (&m_jac[i]) btJacobianEntry( m_rbA.getCenterOfMassTransform().getBasis().transpose(), m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(), - m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(), - normal, + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normal[i], m_rbA.getInvInertiaDiagLocal(), m_rbA.getInvMass(), m_rbB.getInvInertiaDiagLocal(), m_rbB.getInvMass()); - normal[i] = 0; } } @@ -79,12 +201,12 @@ void btHingeConstraint::buildJacobian() btVector3 jointAxis0local; btVector3 jointAxis1local; - btPlaneSpace1(m_axisInA,jointAxis0local,jointAxis1local); + btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); - getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; + getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local; btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local; - btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; + btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); new (&m_jacAng[0]) btJacobianEntry(jointAxis0, m_rbA.getCenterOfMassTransform().getBasis().transpose(), @@ -105,44 +227,70 @@ void btHingeConstraint::buildJacobian() m_rbB.getInvInertiaDiagLocal()); + // Compute limit information + btScalar hingeAngle = getHingeAngle(); + + //set bias, sign, clear accumulator + m_correction = btScalar(0.); + m_limitSign = btScalar(0.); + m_solveLimit = false; + m_accLimitImpulse = btScalar(0.); + + if (m_lowerLimit < m_upperLimit) + { + if (hingeAngle <= m_lowerLimit*m_limitSoftness) + { + m_correction = (m_lowerLimit - hingeAngle); + m_limitSign = 1.0f; + m_solveLimit = true; + } + else if (hingeAngle >= m_upperLimit*m_limitSoftness) + { + m_correction = m_upperLimit - hingeAngle; + m_limitSign = -1.0f; + m_solveLimit = true; + } + } + + //Compute K = J*W*J' for hinge axis + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) + + getRigidBodyB().computeAngularImpulseDenominator(axisA)); } void btHingeConstraint::solveConstraint(btScalar timeStep) { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB; + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - btVector3 normal(0,0,0); btScalar tau = btScalar(0.3); - btScalar damping = btScalar(1.); -//linear part + //linear part if (!m_angularOnly) { + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + for (int i=0;i<3;i++) { - normal[i] = 1; + const btVector3& normal = m_jac[i].m_linearJointAxis; btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; btScalar rel_vel; rel_vel = normal.dot(vel); //positional error (zeroth order error) btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - btScalar impulse = depth*tau/timeStep * jacDiagABInv - damping * rel_vel * jacDiagABInv * damping; + btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; m_appliedImpulse += impulse; btVector3 impulse_vector = normal * impulse; m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); - - normal[i] = 0; } } @@ -151,8 +299,8 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) ///solve angular part // get axes in world space - btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; - btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_axisInB; + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(2); const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); @@ -174,7 +322,7 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) getRigidBodyB().computeAngularImpulseDenominator(normal); // scale for mass and relaxation //todo: expose this 0.9 factor to developer - velrelOrthog *= (btScalar(1.)/denom) * btScalar(0.9); + velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor; } //solve angular positional correction @@ -190,10 +338,28 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) m_rbA.applyTorqueImpulse(-velrelOrthog+angularError); m_rbB.applyTorqueImpulse(velrelOrthog-angularError); + + // solve limit + if (m_solveLimit) + { + btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor ) * m_limitSign; + + btScalar impulseMag = amplitude * m_kHinge; + + // Clamp the accumulated impulse + btScalar temp = m_accLimitImpulse; + m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) ); + impulseMag = m_accLimitImpulse - temp; + + + btVector3 impulse = axisA * impulseMag * m_limitSign; + m_rbA.applyTorqueImpulse(impulse); + m_rbB.applyTorqueImpulse(-impulse); + } } //apply motor - if (m_enableAngularMotor) + if (m_enableAngularMotor) { //todo: add limits too btVector3 angularLimit(0,0,0); @@ -204,10 +370,7 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) btScalar desiredMotorVel = m_motorTargetVelocity; btScalar motor_relvel = desiredMotorVel - projRelVel; - btScalar denom3 = getRigidBodyA().computeAngularImpulseDenominator(axisA) + - getRigidBodyB().computeAngularImpulseDenominator(axisA); - - btScalar unclippedMotorImpulse = (btScalar(1.)/denom3) * motor_relvel;; + btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;; //todo: should clip against accumulated impulse btScalar clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse; clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse; @@ -227,3 +390,11 @@ void btHingeConstraint::updateRHS(btScalar timeStep) } +btScalar btHingeConstraint::getHingeAngle() +{ + const btVector3 refAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0); + const btVector3 refAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1); + const btVector3 swingAxis = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(1); + + return btAtan2Fast( swingAxis.dot(refAxis0), swingAxis.dot(refAxis1) ); +} diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h index 5c1ceafbc5b..8d8adfe9250 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -13,39 +13,61 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ +/* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */ + #ifndef HINGECONSTRAINT_H #define HINGECONSTRAINT_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" class btRigidBody; - /// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space /// axis defines the orientation of the hinge axis class btHingeConstraint : public btTypedConstraint { +#ifdef IN_PARALLELL_SOLVER +public: +#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor - btVector3 m_pivotInA; - btVector3 m_pivotInB; - btVector3 m_axisInA; - btVector3 m_axisInB; + btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransform m_rbBFrame; + + btScalar m_motorTargetVelocity; + btScalar m_maxMotorImpulse; + + btScalar m_limitSoftness; + btScalar m_biasFactor; + btScalar m_relaxationFactor; + + btScalar m_lowerLimit; + btScalar m_upperLimit; + + btScalar m_kHinge; + + btScalar m_limitSign; + btScalar m_correction; + + btScalar m_accLimitImpulse; bool m_angularOnly; - - btScalar m_motorTargetVelocity; - btScalar m_maxMotorImpulse; bool m_enableAngularMotor; + bool m_solveLimit; + public: - btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,btVector3& axisInA,btVector3& axisInB); + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, btVector3& axisInA,btVector3& axisInB); btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA); + + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame); + + btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame); btHingeConstraint(); @@ -76,6 +98,33 @@ public: m_maxMotorImpulse = maxMotorImpulse; } + void setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) + { + m_lowerLimit = low; + m_upperLimit = high; + + m_limitSoftness = _softness; + m_biasFactor = _biasFactor; + m_relaxationFactor = _relaxationFactor; + + } + + btScalar getHingeAngle(); + + + const btTransform& getAFrame() { return m_rbAFrame; }; + const btTransform& getBFrame() { return m_rbBFrame; }; + + inline int getSolveLimit() + { + return m_solveLimit; + } + + inline btScalar getLimitSign() + { + return m_limitSign; + } + }; #endif //HINGECONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h index aae3ed0373f..bfeb24c2dfb 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef JACOBIAN_ENTRY_H #define JACOBIAN_ENTRY_H -#include "../../LinearMath/btVector3.h" -#include "../Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" //notes: diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp index aacb0a3ea66..ff918ea5625 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp @@ -21,18 +21,19 @@ subject to the following restrictions: btPoint2PointConstraint::btPoint2PointConstraint() +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE) { } btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB) -:btTypedConstraint(rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB) { } btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) -:btTypedConstraint(rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) { } diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h index 71da8ac0347..27872b9c8aa 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef POINT2POINTCONSTRAINT_H #define POINT2POINTCONSTRAINT_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" @@ -36,6 +36,9 @@ struct btConstraintSetting /// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space class btPoint2PointConstraint : public btTypedConstraint { +#ifdef IN_PARALLELL_SOLVER +public: +#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btVector3 m_pivotInA; @@ -70,6 +73,15 @@ public: m_pivotInB = pivotB; } + const btVector3& getPivotInA() const + { + return m_pivotInA; + } + + const btVector3& getPivotInB() const + { + return m_pivotInB; + } }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index 14b36ad44fd..7d4ed7856c3 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -13,6 +13,9 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ +//#define COMPUTE_IMPULSE_DENOM 1 +//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms. +//#define FORCE_REFESH_CONTACT_MANIFOLDS 1 #include "btSequentialImpulseConstraintSolver.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" @@ -96,7 +99,7 @@ bool MyContactDestroyedCallback(void* userPersistentData) { assert (userPersistentData); btConstraintPersistentData* cpd = (btConstraintPersistentData*)userPersistentData; - delete cpd; + btAlignedFree(cpd); totalCpd--; //printf("totalCpd = %i. DELETED Ptr %x\n",totalCpd,userPersistentData); return true; @@ -121,6 +124,10 @@ m_btSeed2(0) } } +btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() +{ + +} void initSolverBody(btSolverBody* solverBody, btRigidBody* rigidbody) { @@ -155,64 +162,62 @@ btScalar restitutionCurve(btScalar rel_vel, btScalar restitution) //velocity + friction //response between two dynamic objects with friction -SIMD_FORCE_INLINE btScalar resolveSingleCollisionCombinedCacheFriendly( +//SIMD_FORCE_INLINE +btScalar resolveSingleCollisionCombinedCacheFriendly( btSolverBody& body1, btSolverBody& body2, - btSolverConstraint& contactConstraint, + const btSolverConstraint& contactConstraint, const btContactSolverInfo& solverInfo) { (void)solverInfo; - btScalar normalImpulse(0.f); - { - if (contactConstraint.m_penetration < 0.f) - return 0.f; - + btScalar normalImpulse; + // Optimized version of projected relative velocity, use precomputed cross products with normal // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); // btVector3 vel = vel1 - vel2; // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); - btScalar rel_vel; - btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) - + contactConstraint.m_relpos1CrossNormal.dot(body1.m_angularVelocity); - btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_linearVelocity) - + contactConstraint.m_relpos2CrossNormal.dot(body2.m_angularVelocity); + btScalar rel_vel; + btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) + + contactConstraint.m_relpos1CrossNormal.dot(body1.m_angularVelocity); + btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_linearVelocity) + + contactConstraint.m_relpos2CrossNormal.dot(body2.m_angularVelocity); - rel_vel = vel1Dotn-vel2Dotn; + rel_vel = vel1Dotn-vel2Dotn; - btScalar positionalError = contactConstraint.m_penetration; - btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; + btScalar positionalError = contactConstraint.m_penetration; + btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; - btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; - btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; - btScalar normalImpulse = penetrationImpulse+velocityImpulse; - - // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse - btScalar oldNormalImpulse = contactConstraint.m_appliedImpulse; - btScalar sum = oldNormalImpulse + normalImpulse; - contactConstraint.m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; + btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; + normalImpulse = penetrationImpulse+velocityImpulse; + + // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse + btScalar oldNormalImpulse = contactConstraint.m_appliedImpulse; + btScalar sum = oldNormalImpulse + normalImpulse; + contactConstraint.m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; - btScalar oldVelocityImpulse = contactConstraint.m_appliedVelocityImpulse; - btScalar velocitySum = oldVelocityImpulse + velocityImpulse; - contactConstraint.m_appliedVelocityImpulse = btScalar(0.) > velocitySum ? btScalar(0.): velocitySum; + btScalar oldVelocityImpulse = contactConstraint.m_appliedVelocityImpulse; + btScalar velocitySum = oldVelocityImpulse + velocityImpulse; + contactConstraint.m_appliedVelocityImpulse = btScalar(0.) > velocitySum ? btScalar(0.): velocitySum; - normalImpulse = contactConstraint.m_appliedImpulse - oldNormalImpulse; - - if (body1.m_invMass) - { - body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, - contactConstraint.m_angularComponentA,normalImpulse); - } - if (body2.m_invMass) - { - body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, - contactConstraint.m_angularComponentB,-normalImpulse); - } + normalImpulse = contactConstraint.m_appliedImpulse - oldNormalImpulse; + if (body1.m_invMass) + { + body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, + contactConstraint.m_angularComponentA,normalImpulse); } + if (body2.m_invMass) + { + body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, + contactConstraint.m_angularComponentB,-normalImpulse); + } + + @@ -222,10 +227,11 @@ SIMD_FORCE_INLINE btScalar resolveSingleCollisionCombinedCacheFriendly( #ifndef NO_FRICTION_TANGENTIALS -SIMD_FORCE_INLINE btScalar resolveSingleFrictionCacheFriendly( +//SIMD_FORCE_INLINE +btScalar resolveSingleFrictionCacheFriendly( btSolverBody& body1, btSolverBody& body2, - btSolverConstraint& contactConstraint, + const btSolverConstraint& contactConstraint, const btContactSolverInfo& solverInfo, btScalar appliedNormalImpulse) { @@ -252,11 +258,36 @@ SIMD_FORCE_INLINE btScalar resolveSingleFrictionCacheFriendly( // calculate j that moves us to zero relative velocity j1 = -rel_vel * contactConstraint.m_jacDiagABInv; +#define CLAMP_ACCUMULATED_FRICTION_IMPULSE 1 +#ifdef CLAMP_ACCUMULATED_FRICTION_IMPULSE btScalar oldTangentImpulse = contactConstraint.m_appliedImpulse; contactConstraint.m_appliedImpulse = oldTangentImpulse + j1; - GEN_set_min(contactConstraint.m_appliedImpulse, limit); - GEN_set_max(contactConstraint.m_appliedImpulse, -limit); + + if (limit < contactConstraint.m_appliedImpulse) + { + contactConstraint.m_appliedImpulse = limit; + } else + { + if (contactConstraint.m_appliedImpulse < -limit) + contactConstraint.m_appliedImpulse = -limit; + } j1 = contactConstraint.m_appliedImpulse - oldTangentImpulse; +#else + if (limit < j1) + { + j1 = limit; + } else + { + if (j1 < -limit) + j1 = -limit; + } + +#endif //CLAMP_ACCUMULATED_FRICTION_IMPULSE + + //GEN_set_min(contactConstraint.m_appliedImpulse, limit); + //GEN_set_max(contactConstraint.m_appliedImpulse, -limit); + + } @@ -333,12 +364,56 @@ btScalar resolveSingleFrictionCacheFriendly( #endif //NO_FRICTION_TANGENTIALS -btAlignedObjectArray tmpSolverBodyPool; -btAlignedObjectArray tmpSolverConstraintPool; -btAlignedObjectArray tmpSolverFrictionConstraintPool; -btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) + + +void btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btRigidBody* rb0,btRigidBody* rb1, btScalar relaxation) +{ + + btSolverConstraint& solverConstraint = m_tmpSolverFrictionConstraintPool.expand(); + solverConstraint.m_contactNormal = normalAxis; + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; + solverConstraint.m_frictionIndex = frictionIndex; + + solverConstraint.m_friction = cp.m_combinedFriction; + + solverConstraint.m_appliedImpulse = btScalar(0.); + solverConstraint.m_appliedVelocityImpulse = 0.f; + solverConstraint.m_penetration = 0.f; + { + btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis1; + } + { + btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis1; + } + +#ifdef COMPUTE_IMPULSE_DENOM + btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); + btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); +#else + btVector3 vec; + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + btScalar denom0 = rb0->getInvMass() + normalAxis.dot(vec); + vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2); + btScalar denom1 = rb1->getInvMass() + normalAxis.dot(vec); + + +#endif //COMPUTE_IMPULSE_DENOM + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + +} + + +btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) { (void)stackAlloc; (void)debugDrawer; @@ -348,21 +423,31 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio // printf("empty\n"); return 0.f; } + btPersistentManifold* manifold = 0; + btRigidBody* rb0=0,*rb1=0; + +#ifdef FORCE_REFESH_CONTACT_MANIFOLDS BEGIN_PROFILE("refreshManifolds"); int i; + + + for (i=0;igetBody0(); - btRigidBody* rb1 = (btRigidBody*)manifold->getBody1(); - + manifold = manifoldPtr[i]; + rb1 = (btRigidBody*)manifold->getBody1(); + rb0 = (btRigidBody*)manifold->getBody0(); + manifold->refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); } - + END_PROFILE("refreshManifolds"); +#endif //FORCE_REFESH_CONTACT_MANIFOLDS + + btVector3 color(0,1,0); BEGIN_PROFILE("gatherSolverData"); @@ -384,8 +469,10 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio //todo: use stack allocator for this temp memory int minReservation = numManifolds*2; - tmpSolverBodyPool.reserve(minReservation); + //m_tmpSolverBodyPool.reserve(minReservation); + //don't convert all bodies, only the one we need so solver the constraints +/* { for (int i=0;igetIslandTag() >= 0)) { btAssert(rb->getCompanionId() < 0); - int solverBodyId = tmpSolverBodyPool.size(); - btSolverBody& solverBody = tmpSolverBodyPool.expand(); + int solverBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); initSolverBody(&solverBody,rb); rb->setCompanionId(solverBodyId); } } } - +*/ - tmpSolverConstraintPool.reserve(minReservation); - tmpSolverFrictionConstraintPool.reserve(minReservation); + //m_tmpSolverConstraintPool.reserve(minReservation); + //m_tmpSolverFrictionConstraintPool.reserve(minReservation); + { int i; for (i=0;igetBody0(); - btRigidBody* rb1 = (btRigidBody*)manifold->getBody1(); + manifold = manifoldPtr[i]; + rb1 = (btRigidBody*)manifold->getBody1(); + rb0 = (btRigidBody*)manifold->getBody0(); + int solverBodyIdA=-1; int solverBodyIdB=-1; @@ -424,59 +513,98 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio if (rb0->getIslandTag() >= 0) { - solverBodyIdA = rb0->getCompanionId(); + if (rb0->getCompanionId() >= 0) + { + //body has already been converted + solverBodyIdA = rb0->getCompanionId(); + } else + { + solverBodyIdA = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,rb0); + rb0->setCompanionId(solverBodyIdA); + } } else { //create a static body - solverBodyIdA = tmpSolverBodyPool.size(); - btSolverBody& solverBody = tmpSolverBodyPool.expand(); + solverBodyIdA = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); initSolverBody(&solverBody,rb0); } if (rb1->getIslandTag() >= 0) { - solverBodyIdB = rb1->getCompanionId(); + if (rb1->getCompanionId() >= 0) + { + solverBodyIdB = rb1->getCompanionId(); + } else + { + solverBodyIdB = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,rb1); + rb1->setCompanionId(solverBodyIdB); + } } else { //create a static body - solverBodyIdB = tmpSolverBodyPool.size(); - btSolverBody& solverBody = tmpSolverBodyPool.expand(); + solverBodyIdB = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); initSolverBody(&solverBody,rb1); } } + btVector3 rel_pos1; + btVector3 rel_pos2; + btScalar relaxation; + for (int j=0;jgetNumContacts();j++) { btManifoldPoint& cp = manifold->getContactPoint(j); + + if (debugDrawer) + debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); - int frictionIndex = tmpSolverConstraintPool.size(); - + if (cp.getDistance() <= btScalar(0.)) { const btVector3& pos1 = cp.getPositionWorldOnA(); const btVector3& pos2 = cp.getPositionWorldOnB(); - btVector3 rel_pos1 = pos1 - rb0->getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - rb1->getCenterOfMassPosition(); + rel_pos1 = pos1 - rb0->getCenterOfMassPosition(); + rel_pos2 = pos2 - rb1->getCenterOfMassPosition(); - btScalar relaxation = 1.f; + relaxation = 1.f; + btScalar rel_vel; + btVector3 vel; + + int frictionIndex = m_tmpSolverConstraintPool.size(); { - btSolverConstraint& solverConstraint = tmpSolverConstraintPool.expand(); + btSolverConstraint& solverConstraint = m_tmpSolverConstraintPool.expand(); solverConstraint.m_solverBodyIdA = solverBodyIdA; solverConstraint.m_solverBodyIdB = solverBodyIdB; solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_CONTACT_1D; - - + btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*torqueAxis0; + btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*torqueAxis1; { - //can be optimized, the cross products are already calculated +#ifdef COMPUTE_IMPULSE_DENOM btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB); btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB); +#else + btVector3 vec; + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + btScalar denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec); + vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2); + btScalar denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec); +#endif //COMPUTE_IMPULSE_DENOM + btScalar denom = relaxation/(denom0+denom1); solverConstraint.m_jacDiagABInv = denom; } @@ -489,109 +617,57 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio btVector3 vel1 = rb0->getVelocityInLocalPoint(rel_pos1); btVector3 vel2 = rb1->getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; + vel = vel1 - vel2; + rel_vel = cp.m_normalWorldOnB.dot(vel); solverConstraint.m_penetration = cp.getDistance();///btScalar(infoGlobal.m_numIterations); solverConstraint.m_friction = cp.m_combinedFriction; - btScalar rest = restitutionCurve(rel_vel, cp.m_combinedRestitution); - if (rest <= btScalar(0.)) + solverConstraint.m_restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); + if (solverConstraint.m_restitution <= btScalar(0.)) { - rest = 0.f; + solverConstraint.m_restitution = 0.f; }; btScalar penVel = -solverConstraint.m_penetration/infoGlobal.m_timeStep; - if (rest > penVel) - { - rest = btScalar(0.); - } - solverConstraint.m_restitution = rest; - solverConstraint.m_penetration *= -(infoGlobal.m_erp/infoGlobal.m_timeStep); + if (solverConstraint.m_restitution > penVel) + { + solverConstraint.m_penetration = btScalar(0.); + } + + + solverConstraint.m_appliedImpulse = 0.f; solverConstraint.m_appliedVelocityImpulse = 0.f; - btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*torqueAxis0; - btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*torqueAxis1; - } - - //create 2 '1d axis' constraints for 2 tangential friction directions - - //re-calculate friction direction every frame, todo: check if this is really needed - btVector3 frictionTangential0a, frictionTangential1b; - - btPlaneSpace1(cp.m_normalWorldOnB,frictionTangential0a,frictionTangential1b); - - { - btSolverConstraint& solverConstraint = tmpSolverFrictionConstraintPool.expand(); - solverConstraint.m_contactNormal = frictionTangential0a; - - solverConstraint.m_solverBodyIdA = solverBodyIdA; - solverConstraint.m_solverBodyIdB = solverBodyIdB; - solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; - solverConstraint.m_frictionIndex = frictionIndex; - - solverConstraint.m_friction = cp.m_combinedFriction; - - solverConstraint.m_appliedImpulse = btScalar(0.); - solverConstraint.m_appliedVelocityImpulse = 0.f; - - btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); - btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); - btScalar denom = relaxation/(denom0+denom1); - solverConstraint.m_jacDiagABInv = denom; - - { - btVector3 ftorqueAxis0 = rel_pos1.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos1CrossNormal = ftorqueAxis0; - solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis0; - } - { - btVector3 ftorqueAxis0 = rel_pos2.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos2CrossNormal = ftorqueAxis0; - solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis0; - } - - } - - - { - - btSolverConstraint& solverConstraint = tmpSolverFrictionConstraintPool.expand(); - solverConstraint.m_contactNormal = frictionTangential1b; - - solverConstraint.m_solverBodyIdA = solverBodyIdA; - solverConstraint.m_solverBodyIdB = solverBodyIdB; - solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; - solverConstraint.m_frictionIndex = frictionIndex; - - solverConstraint.m_friction = cp.m_combinedFriction; - - solverConstraint.m_appliedImpulse = btScalar(0.); - solverConstraint.m_appliedVelocityImpulse = 0.f; - btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); - btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); - btScalar denom = relaxation/(denom0+denom1); - solverConstraint.m_jacDiagABInv = denom; + } + + + { + btVector3 frictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; + btScalar lat_rel_vel = frictionDir1.length2(); + if (lat_rel_vel > SIMD_EPSILON)//0.0f) { - btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis1; - } + frictionDir1 /= btSqrt(lat_rel_vel); + addFrictionConstraint(frictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation); + btVector3 frictionDir2 = frictionDir1.cross(cp.m_normalWorldOnB); + frictionDir2.normalize();//?? + addFrictionConstraint(frictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation); + } else { - btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis1; - } + //re-calculate friction direction every frame, todo: check if this is really needed + btVector3 frictionDir1,frictionDir2; + btPlaneSpace1(cp.m_normalWorldOnB,frictionDir1,frictionDir2); + addFrictionConstraint(frictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation); + addFrictionConstraint(frictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation); } + } } } } @@ -612,24 +688,23 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio } } - btAlignedObjectArray gOrderTmpConstraintPool; - btAlignedObjectArray gOrderFrictionConstraintPool; + - int numConstraintPool = tmpSolverConstraintPool.size(); - int numFrictionPool = tmpSolverFrictionConstraintPool.size(); + int numConstraintPool = m_tmpSolverConstraintPool.size(); + int numFrictionPool = m_tmpSolverFrictionConstraintPool.size(); ///todo: use stack allocator for such temporarily memory, same for solver bodies/constraints - gOrderTmpConstraintPool.resize(numConstraintPool); - gOrderFrictionConstraintPool.resize(numFrictionPool); + m_orderTmpConstraintPool.resize(numConstraintPool); + m_orderFrictionConstraintPool.resize(numFrictionPool); { int i; for (i=0;igetRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].writebackVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].writebackVelocity(); } if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); } - constraint->solveConstraint(info.m_timeStep); + constraint->solveConstraint(infoGlobal.m_timeStep); if ((constraint->getRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].readVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].readVelocity(); } if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); } } { - int numPoolConstraints = tmpSolverConstraintPool.size(); + int numPoolConstraints = m_tmpSolverConstraintPool.size(); for (j=0;jgetBody0(), (btRigidBody*)manifold->getBody1(),manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); } + } } @@ -878,8 +977,9 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol //only necessary to refresh the manifold once (first iteration). The integration is done outside the loop { +#ifdef FORCE_REFESH_CONTACT_MANIFOLDS manifoldPtr->refreshContactPoints(body0->getCenterOfMassTransform(),body1->getCenterOfMassTransform()); - +#endif //FORCE_REFESH_CONTACT_MANIFOLDS int numpoints = manifoldPtr->getNumContacts(); gTotalContactPoints += numpoints; @@ -925,7 +1025,9 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol } else { - cpd = new btConstraintPersistentData; + //todo: should this be in a pool? + void* mem = btAlignedAlloc(sizeof(btConstraintPersistentData),16); + cpd = new (mem)btConstraintPersistentData; assert(cpd); totalCpd ++; @@ -972,7 +1074,6 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol cpd->m_penetration = btScalar(0.); } - btScalar relaxation = info.m_damping; if (m_solverMode & SOLVER_USE_WARMSTARTING) @@ -1156,3 +1257,10 @@ btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,b } return btScalar(0.); } + + +void btSequentialImpulseConstraintSolver::reset() +{ + m_btSeed2 = 0; +} + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h index 13e70c41be4..83a96d4dc44 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -19,7 +19,8 @@ subject to the following restrictions: #include "btConstraintSolver.h" class btIDebugDraw; #include "btContactConstraint.h" - +#include "btSolverBody.h" +#include "btSolverConstraint.h" /// btSequentialImpulseConstraintSolver uses a Propagation Method and Sequentially applies impulses @@ -29,10 +30,18 @@ class btIDebugDraw; class btSequentialImpulseConstraintSolver : public btConstraintSolver { + btAlignedObjectArray m_tmpSolverBodyPool; + btAlignedObjectArray m_tmpSolverConstraintPool; + btAlignedObjectArray m_tmpSolverFrictionConstraintPool; + btAlignedObjectArray m_orderTmpConstraintPool; + btAlignedObjectArray m_orderFrictionConstraintPool; + + protected: btScalar solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); btScalar solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); void prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer); + void addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btRigidBody* rb0,btRigidBody* rb1, btScalar relaxation); ContactSolverFunc m_contactDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; ContactSolverFunc m_frictionDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; @@ -68,11 +77,17 @@ public: m_frictionDispatch[type0][type1] = func; } - virtual ~btSequentialImpulseConstraintSolver() {} + virtual ~btSequentialImpulseConstraintSolver(); - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc); + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher); virtual btScalar solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + + + ///clear internal cached data and reset random seed + virtual void reset(); btScalar solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); @@ -102,7 +117,9 @@ public: }; - +#ifndef BT_PREFER_SIMD +typedef btSequentialImpulseConstraintSolver btSequentialImpulseConstraintSolverPrefered; +#endif #endif //SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h index e7d26645c6a..057d3fac827 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef SOLVE_2LINEAR_CONSTRAINT_H #define SOLVE_2LINEAR_CONSTRAINT_H -#include "../../LinearMath/btMatrix3x3.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btVector3.h" class btRigidBody; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h index 0ab536f42b3..21305b3164e 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h @@ -19,30 +19,33 @@ subject to the following restrictions: class btRigidBody; #include "LinearMath/btVector3.h" #include "LinearMath/btMatrix3x3.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btAlignedAllocator.h" - - +///btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance. ATTRIBUTE_ALIGNED16 (struct) btSolverBody { - btVector3 m_centerOfMassPosition; - btVector3 m_linearVelocity; + BT_DECLARE_ALIGNED_ALLOCATOR(); + btVector3 m_angularVelocity; - btRigidBody* m_originalBody; + float m_angularFactor; float m_invMass; float m_friction; - float m_angularFactor; - - inline void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const + btRigidBody* m_originalBody; + btVector3 m_linearVelocity; + btVector3 m_centerOfMassPosition; + + SIMD_FORCE_INLINE void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const { velocity = m_linearVelocity + m_angularVelocity.cross(rel_pos); } //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - inline void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) { m_linearVelocity += linearComponent*impulseMagnitude; - m_angularVelocity += angularComponent*impulseMagnitude*m_angularFactor; + m_angularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); } void writebackVelocity() @@ -51,6 +54,7 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody { m_originalBody->setLinearVelocity(m_linearVelocity); m_originalBody->setAngularVelocity(m_angularVelocity); + //m_originalBody->setCompanionId(-1); } } @@ -69,3 +73,4 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody }; #endif //BT_SOLVER_BODY_H + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h index f1f40ffdf19..a750560d33c 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h @@ -27,21 +27,27 @@ class btRigidBody; ///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints. ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint { - btVector3 m_relpos1CrossNormal; - btVector3 m_relpos2CrossNormal; - btVector3 m_contactNormal; - btVector3 m_angularComponentA; - btVector3 m_angularComponentB; + BT_DECLARE_ALIGNED_ALLOCATOR(); - btScalar m_appliedVelocityImpulse; + btVector3 m_relpos1CrossNormal; + btVector3 m_contactNormal; + + btVector3 m_relpos2CrossNormal; + btVector3 m_angularComponentA; + + btVector3 m_angularComponentB; + mutable btScalar m_appliedVelocityImpulse; + mutable btScalar m_appliedImpulse; int m_solverBodyIdA; int m_solverBodyIdB; + btScalar m_friction; btScalar m_restitution; btScalar m_jacDiagABInv; btScalar m_penetration; - btScalar m_appliedImpulse; + + int m_constraintType; int m_frictionIndex; int m_unusedPadding[2]; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp index a15b3e026cd..6e8b552dbbc 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp @@ -19,18 +19,20 @@ subject to the following restrictions: static btRigidBody s_fixed(0, 0,0); -btTypedConstraint::btTypedConstraint() -: m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint(btTypedConstraintType type) +:m_userConstraintType(-1), m_userConstraintId(-1), +m_constraintType (type), m_rbA(s_fixed), m_rbB(s_fixed), m_appliedImpulse(btScalar(0.)) { s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); } -btTypedConstraint::btTypedConstraint(btRigidBody& rbA) -: m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA) +:m_userConstraintType(-1), m_userConstraintId(-1), +m_constraintType (type), m_rbA(rbA), m_rbB(s_fixed), m_appliedImpulse(btScalar(0.)) @@ -40,9 +42,10 @@ m_appliedImpulse(btScalar(0.)) } -btTypedConstraint::btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB) -: m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB) +:m_userConstraintType(-1), m_userConstraintId(-1), +m_constraintType (type), m_rbA(rbA), m_rbB(rbB), m_appliedImpulse(btScalar(0.)) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h index dfee6e80d0e..745d0afde6d 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -17,7 +17,16 @@ subject to the following restrictions: #define TYPED_CONSTRAINT_H class btRigidBody; -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" + +enum btTypedConstraintType +{ + POINT2POINT_CONSTRAINT_TYPE, + HINGE_CONSTRAINT_TYPE, + CONETWIST_CONSTRAINT_TYPE, + D6_CONSTRAINT_TYPE, + VEHICLE_CONSTRAINT_TYPE +}; ///TypedConstraint is the baseclass for Bullet constraints and vehicles class btTypedConstraint @@ -25,6 +34,8 @@ class btTypedConstraint int m_userConstraintType; int m_userConstraintId; + btTypedConstraintType m_constraintType; + btTypedConstraint& operator=(btTypedConstraint& other) { btAssert(0); @@ -40,11 +51,11 @@ protected: public: - btTypedConstraint(); + btTypedConstraint(btTypedConstraintType type); virtual ~btTypedConstraint() {}; - btTypedConstraint(btRigidBody& rbA); + btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA); - btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB); + btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); virtual void buildJacobian() = 0; @@ -59,7 +70,7 @@ public: return m_rbB; } - btRigidBody& getRigidBodyA() + btRigidBody& getRigidBodyA() { return m_rbA; } @@ -83,14 +94,19 @@ public: m_userConstraintId = uid; } - int getUserConstraintId() + int getUserConstraintId() const { return m_userConstraintId; } - btScalar getAppliedImpulse() + btScalar getAppliedImpulse() const { return m_appliedImpulse; } + + btTypedConstraintType getConstraintType () const + { + return m_constraintType; + } }; #endif //TYPED_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp new file mode 100644 index 00000000000..3f1c8e1a13b --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp @@ -0,0 +1,402 @@ +/* +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 +*/ + +#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" + + +/* + Create and Delete a Physics SDK +*/ + +struct btPhysicsSdk +{ + +// btDispatcher* m_dispatcher; +// btOverlappingPairCache* m_pairCache; +// btConstraintSolver* m_constraintSolver + + btVector3 m_worldAabbMin; + btVector3 m_worldAabbMax; + + + //todo: version, hardware/optimization settings etc? + btPhysicsSdk() + :m_worldAabbMin(-1000,-1000,-1000), + m_worldAabbMax(1000,1000,1000) + { + + } + + +}; + +plPhysicsSdkHandle plNewBulletSdk() +{ + void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16); + return (plPhysicsSdkHandle)new (mem)btPhysicsSdk; +} + +void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk) +{ + btPhysicsSdk* phys = reinterpret_cast(physicsSdk); + btAlignedFree(phys); +} + + +/* Dynamics World */ +plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdkHandle) +{ + btPhysicsSdk* physicsSdk = reinterpret_cast(physicsSdkHandle); + void* mem = btAlignedAlloc(sizeof(btDefaultCollisionConfiguration),16); + btDefaultCollisionConfiguration* collisionConfiguration = new (mem)btDefaultCollisionConfiguration(); + mem = btAlignedAlloc(sizeof(btCollisionDispatcher),16); + btDispatcher* dispatcher = new (mem)btCollisionDispatcher(collisionConfiguration); + mem = btAlignedAlloc(sizeof(btAxisSweep3),16); + btBroadphaseInterface* pairCache = new (mem)btAxisSweep3(physicsSdk->m_worldAabbMin,physicsSdk->m_worldAabbMax); + mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); + btConstraintSolver* constraintSolver = new(mem) btSequentialImpulseConstraintSolver(); + + mem = btAlignedAlloc(sizeof(btDiscreteDynamicsWorld),16); + return (plDynamicsWorldHandle) new (mem)btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration); +} +void plDeleteDynamicsWorld(plDynamicsWorldHandle world) +{ + //todo: also clean up the other allocations, axisSweep, pairCache,dispatcher,constraintSolver,collisionConfiguration + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAlignedFree(dynamicsWorld); +} + +void plStepSimulation(plDynamicsWorldHandle world, plReal timeStep) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + dynamicsWorld->stepSimulation(timeStep); +} + +void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + assert(body); + + dynamicsWorld->addRigidBody(body); +} + +void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + assert(body); + + dynamicsWorld->removeRigidBody(body); +} + +/* Rigid Body */ + +plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ) +{ + btTransform trans; + trans.setIdentity(); + btVector3 localInertia(0,0,0); + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + if (mass) + { + shape->calculateLocalInertia(mass,localInertia); + } + void* mem = btAlignedAlloc(sizeof(btRigidBody),16); + btRigidBody* body = new (mem)btRigidBody(mass, 0,shape,localInertia); + body->setWorldTransform(trans); + body->setUserPointer(user_data); + return (plRigidBodyHandle) body; +} + +void plDeleteRigidBody(plRigidBodyHandle cbody) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody); + assert(body); + btAlignedFree( body); +} + + +/* Collision Shape definition */ + +plCollisionShapeHandle plNewSphereShape(plReal radius) +{ + void* mem = btAlignedAlloc(sizeof(btSphereShape),16); + return (plCollisionShapeHandle) new (mem)btSphereShape(radius); + +} + +plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z) +{ + void* mem = btAlignedAlloc(sizeof(btBoxShape),16); + return (plCollisionShapeHandle) new (mem)btBoxShape(btVector3(x,y,z)); +} + +plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height) +{ + //capsule is convex hull of 2 spheres, so use btMultiSphereShape + btVector3 inertiaHalfExtents(radius,height,radius); + const int numSpheres = 2; + btVector3 positions[numSpheres] = {btVector3(0,height,0),btVector3(0,-height,0)}; + btScalar radi[numSpheres] = {radius,radius}; + void* mem = btAlignedAlloc(sizeof(btMultiSphereShape),16); + return (plCollisionShapeHandle) new (mem)btMultiSphereShape(inertiaHalfExtents,positions,radi,numSpheres); +} +plCollisionShapeHandle plNewConeShape(plReal radius, plReal height) +{ + void* mem = btAlignedAlloc(sizeof(btConeShape),16); + return (plCollisionShapeHandle) new (mem)btConeShape(radius,height); +} + +plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height) +{ + void* mem = btAlignedAlloc(sizeof(btCylinderShape),16); + return (plCollisionShapeHandle) new (mem)btCylinderShape(btVector3(radius,height,radius)); +} + +/* Convex Meshes */ +plCollisionShapeHandle plNewConvexHullShape() +{ + void* mem = btAlignedAlloc(sizeof(btConvexHullShape),16); + return (plCollisionShapeHandle) new (mem)btConvexHullShape(); +} + + +/* Concave static triangle meshes */ +plMeshInterfaceHandle plNewMeshInterface() +{ + return 0; +} + +plCollisionShapeHandle plNewCompoundShape() +{ + void* mem = btAlignedAlloc(sizeof(btCompoundShape),16); + return (plCollisionShapeHandle) new (mem)btCompoundShape(); +} + +void plAddChildShape(plCollisionShapeHandle compoundShapeHandle,plCollisionShapeHandle childShapeHandle, plVector3 childPos,plQuaternion childOrn) +{ + btCollisionShape* colShape = reinterpret_cast(compoundShapeHandle); + btAssert(colShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE); + btCompoundShape* compoundShape = reinterpret_cast(colShape); + btCollisionShape* childShape = reinterpret_cast(childShapeHandle); + btTransform localTrans; + localTrans.setIdentity(); + localTrans.setOrigin(btVector3(childPos[0],childPos[1],childPos[2])); + localTrans.setRotation(btQuaternion(childOrn[0],childOrn[1],childOrn[2],childOrn[3])); + compoundShape->addChildShape(localTrans,childShape); +} + +void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient) +{ + btQuaternion orn; + orn.setEuler(yaw,pitch,roll); + orient[0] = orn.getX(); + orient[1] = orn.getY(); + orient[2] = orn.getZ(); + orient[3] = orn.getW(); + +} + + +// extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); +// extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); + + +void plAddVertex(plCollisionShapeHandle cshape, plReal x,plReal y,plReal z) +{ + btCollisionShape* colShape = reinterpret_cast( cshape); + btAssert(colShape->getShapeType()==CONVEX_HULL_SHAPE_PROXYTYPE); + btConvexHullShape* convexHullShape = reinterpret_cast( cshape); + convexHullShape->addPoint(btPoint3(x,y,z)); + +} + +void plDeleteShape(plCollisionShapeHandle cshape) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + btAlignedFree(shape); +} +void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]); + shape->setLocalScaling(scaling); +} + + + +void plSetPosition(plRigidBodyHandle object, const plVector3 position) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btVector3 pos(position[0],position[1],position[2]); + btTransform worldTrans = body->getWorldTransform(); + worldTrans.setOrigin(pos); + body->setWorldTransform(worldTrans); +} + +void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btQuaternion orn(orientation[0],orientation[1],orientation[2],orientation[3]); + btTransform worldTrans = body->getWorldTransform(); + worldTrans.setRotation(orn); + body->setWorldTransform(worldTrans); +} + +void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + body->getWorldTransform().getOpenGLMatrix(matrix); + +} + +void plGetPosition(plRigidBodyHandle object,plVector3 position) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + const btVector3& pos = body->getWorldTransform().getOrigin(); + position[0] = pos.getX(); + position[1] = pos.getY(); + position[2] = pos.getZ(); +} + +void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + const btQuaternion& orn = body->getWorldTransform().getRotation(); + orientation[0] = orn.getX(); + orientation[1] = orn.getY(); + orientation[2] = orn.getZ(); + orientation[3] = orn.getW(); +} + + + +//plRigidBodyHandle plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); + +// extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); + + + + +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; +} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp new file mode 100644 index 00000000000..5e330cb64f2 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp @@ -0,0 +1,194 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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. +*/ + + +#include "btContinuousDynamicsWorld.h" +#include "LinearMath/btQuickprof.h" + +//collision detection +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" + +//rigidbody & constraints +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" + + + +#include + +btContinuousDynamicsWorld::btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) +:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) +{ +} + +btContinuousDynamicsWorld::~btContinuousDynamicsWorld() +{ +} + + +void btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) +{ + + startProfiling(timeStep); + + ///update aabbs information + updateAabbs(); + //static int frame=0; +// printf("frame %d\n",frame++); + + ///apply gravity, predict motion + predictUnconstraintMotion(timeStep); + + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + + dispatchInfo.m_timeStep = timeStep; + dispatchInfo.m_stepCount = 0; + dispatchInfo.m_debugDraw = getDebugDrawer(); + + ///perform collision detection + performDiscreteCollisionDetection(); + + calculateSimulationIslands(); + + + getSolverInfo().m_timeStep = timeStep; + + + + ///solve contact and other joint constraints + solveConstraints(getSolverInfo()); + + ///CallbackTriggers(); + + calculateTimeOfImpacts(timeStep); + + btScalar toi = dispatchInfo.m_timeOfImpact; +// if (toi < 1.f) +// printf("toi = %f\n",toi); + if (toi < 0.f) + printf("toi = %f\n",toi); + + + ///integrate transforms + integrateTransforms(timeStep * toi); + + ///update vehicle simulation + updateVehicles(timeStep); + + + updateActivationState( timeStep ); + +} + +void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep) +{ + ///these should be 'temporal' aabbs! + updateTemporalAabbs(timeStep); + + ///'toi' is the global smallest time of impact. However, we just calculate the time of impact for each object individually. + ///so we handle the case moving versus static properly, and we cheat for moving versus moving + float toi = 1.f; + + + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + dispatchInfo.m_timeStep = timeStep; + dispatchInfo.m_timeOfImpact = 1.f; + dispatchInfo.m_stepCount = 0; + dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_CONTINUOUS; + + ///calculate time of impact for overlapping pairs + + BEGIN_PROFILE("performContinuousCollisionDetection"); + + btDispatcher* dispatcher = getDispatcher(); + if (dispatcher) + dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); + + END_PROFILE("performContinuousCollisionDetection"); + + toi = dispatchInfo.m_timeOfImpact; + + dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE; + +} + +void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep) +{ + BEGIN_PROFILE("perform Temporal Broadphase Collision Detection"); + + btVector3 temporalAabbMin,temporalAabbMax; + + for ( int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),temporalAabbMin,temporalAabbMax); + const btVector3& linvel = body->getLinearVelocity(); + + //make the AABB temporal + float temporalAabbMaxx = temporalAabbMax.getX(); + float temporalAabbMaxy = temporalAabbMax.getY(); + float temporalAabbMaxz = temporalAabbMax.getZ(); + float temporalAabbMinx = temporalAabbMin.getX(); + float temporalAabbMiny = temporalAabbMin.getY(); + float temporalAabbMinz = temporalAabbMin.getZ(); + + // add linear motion + btVector3 linMotion = linvel*timeStep; + + if (linMotion.x() > 0.f) + temporalAabbMaxx += linMotion.x(); + else + temporalAabbMinx += linMotion.x(); + if (linMotion.y() > 0.f) + temporalAabbMaxy += linMotion.y(); + else + temporalAabbMiny += linMotion.y(); + if (linMotion.z() > 0.f) + temporalAabbMaxz += linMotion.z(); + else + temporalAabbMinz += linMotion.z(); + + //add conservative angular motion + btScalar angularMotion(0);// = angvel.length() * GetAngularMotionDisc() * timeStep; + btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion); + temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz); + temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz); + + temporalAabbMin -= angularMotion3d; + temporalAabbMax += angularMotion3d; + + m_broadphasePairCache->setAabb(body->getBroadphaseHandle(),temporalAabbMin,temporalAabbMax,m_dispatcher1); + } + } + + //update aabb (of all moved objects) + + m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); + + END_PROFILE("perform Temporal Broadphase Collision Detection"); + + +} + + diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h new file mode 100644 index 00000000000..61c8dea03eb --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 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. +*/ + +#ifndef BT_CONTINUOUS_DYNAMICS_WORLD_H +#define BT_CONTINUOUS_DYNAMICS_WORLD_H + +#include "btDiscreteDynamicsWorld.h" + +///btContinuousDynamicsWorld adds optional (per object) continuous collision detection for fast moving objects to the btDiscreteDynamicsWorld. +///This copes with fast moving objects that otherwise would tunnel/miss collisions. +///Under construction, don't use yet! Please use btDiscreteDynamicsWorld instead. +class btContinuousDynamicsWorld : public btDiscreteDynamicsWorld +{ + + void updateTemporalAabbs(btScalar timeStep); + + public: + + btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + virtual ~btContinuousDynamicsWorld(); + + ///time stepping with calculation of time of impact for selected fast moving objects + virtual void internalSingleStepSimulation( btScalar timeStep); + + virtual void calculateTimeOfImpacts(btScalar timeStep); + + virtual btDynamicsWorldType getWorldType() const + { + return BT_CONTINUOUS_DYNAMICS_WORLD; + } + +}; + +#endif //BT_CONTINUOUS_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index 29719ec9a3e..88b11c878c5 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -57,17 +57,30 @@ subject to the following restrictions: -btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) -:btDynamicsWorld(dispatcher,pairCache), -m_constraintSolver(constraintSolver? constraintSolver: new btSequentialImpulseConstraintSolver), +btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration) +:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), +m_constraintSolver(constraintSolver), m_debugDrawer(0), m_gravity(0,-10,0), m_localTime(btScalar(1.)/btScalar(60.)), m_profileTimings(0) { - m_islandManager = new btSimulationIslandManager(); + if (!m_constraintSolver) + { + void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); + m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver; + m_ownsConstraintSolver = true; + } else + { + m_ownsConstraintSolver = false; + } + + { + void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16); + m_islandManager = new (mem) btSimulationIslandManager(); + } + m_ownsIslandManager = true; - m_ownsConstraintSolver = (constraintSolver==0); } @@ -75,9 +88,16 @@ btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld() { //only delete it when we created it if (m_ownsIslandManager) - delete m_islandManager; + { + m_islandManager->~btSimulationIslandManager(); + btAlignedFree( m_islandManager); + } if (m_ownsConstraintSolver) - delete m_constraintSolver; + { + + m_constraintSolver->~btConstraintSolver(); + btAlignedFree(m_constraintSolver); + } } void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) @@ -412,7 +432,7 @@ void btDiscreteDynamicsWorld::removeVehicle(btRaycastVehicle* vehicle) m_vehicles.remove(vehicle); } -inline int btGetConstraintIslandId(const btTypedConstraint* lhs) +SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs) { int islandId; @@ -452,7 +472,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) int m_numConstraints; btIDebugDraw* m_debugDrawer; btStackAlloc* m_stackAlloc; - + btDispatcher* m_dispatcher; InplaceSolverIslandCallback( btContactSolverInfo& solverInfo, @@ -460,13 +480,15 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer, - btStackAlloc* stackAlloc) + btStackAlloc* stackAlloc, + btDispatcher* dispatcher) :m_solverInfo(solverInfo), m_solver(solver), m_sortedConstraints(sortedConstraints), m_numConstraints(numConstraints), m_debugDrawer(debugDrawer), - m_stackAlloc(stackAlloc) + m_stackAlloc(stackAlloc), + m_dispatcher(dispatcher) { } @@ -479,30 +501,38 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) } virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId) { - //also add all non-contact constraints/joints for this island - btTypedConstraint** startConstraint = 0; - int numCurConstraints = 0; - int i; - - //find the first constraint for this island - for (i=0;isolveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + } else { - if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId) + //also add all non-contact constraints/joints for this island + btTypedConstraint** startConstraint = 0; + int numCurConstraints = 0; + int i; + + //find the first constraint for this island + for (i=0;isolveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc); + m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + + } } }; @@ -524,14 +554,14 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) btTypedConstraint** constraintsPtr = getNumConstraints() ? &sortedConstraints[0] : 0; - InplaceSolverIslandCallback solverCallback( solverInfo, m_constraintSolver, constraintsPtr,sortedConstraints.size(), m_debugDrawer,m_stackAlloc); - + InplaceSolverIslandCallback solverCallback( solverInfo, m_constraintSolver, constraintsPtr,sortedConstraints.size(), m_debugDrawer,m_stackAlloc,m_dispatcher1); + m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); /// solve all the constraints for this island m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld()->getCollisionObjectArray(),&solverCallback); - + m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc); } @@ -596,7 +626,7 @@ void btDiscreteDynamicsWorld::updateAabbs() //moving objects should be moderately sized, probably something wrong if not if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) { - bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb); + bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); } else { //something went wrong, investigate @@ -856,10 +886,24 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, btScalar radius = coneShape->getRadius();//+coneShape->getMargin(); btScalar height = coneShape->getHeight();//+coneShape->getMargin(); btVector3 start = worldTransform.getOrigin(); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(radius,btScalar(0.),btScalar(-0.5)*height),color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(-radius,btScalar(0.),btScalar(-0.5)*height),color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),radius,btScalar(-0.5)*height),color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),-radius,btScalar(-0.5)*height),color); + + int upAxis= coneShape->getConeUpIndex(); + + + btVector3 offsetHeight(0,0,0); + offsetHeight[upAxis] = height * btScalar(0.5); + btVector3 offsetRadius(0,0,0); + offsetRadius[(upAxis+1)%3] = radius; + btVector3 offset2Radius(0,0,0); + offset2Radius[(upAxis+2)%3] = radius; + + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offsetRadius),color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offset2Radius),color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offset2Radius),color); + + + break; } @@ -868,7 +912,7 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, const btCylinderShape* cylinder = static_cast(shape); int upAxis = cylinder->getUpAxis(); btScalar radius = cylinder->getRadius(); - btScalar halfHeight = cylinder->getHalfExtents()[upAxis]; + btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; btVector3 start = worldTransform.getOrigin(); btVector3 offsetHeight(0,0,0); offsetHeight[upAxis] = halfHeight; @@ -902,7 +946,7 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); //DebugDrawcallback drawCallback; DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); - convexMesh->getStridingMesh()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); + convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); } @@ -934,12 +978,18 @@ void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) { if (m_ownsConstraintSolver) { - delete m_constraintSolver; + btAlignedFree( m_constraintSolver); } m_ownsConstraintSolver = false; m_constraintSolver = solver; } +btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver() +{ + return m_constraintSolver; +} + + int btDiscreteDynamicsWorld::getNumConstraints() const { return int(m_constraints.size()); diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h index 83b90bfeebc..7364c4cd6b9 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -23,11 +23,11 @@ class btOverlappingPairCache; class btConstraintSolver; class btSimulationIslandManager; class btTypedConstraint; -#include "../ConstraintSolver/btContactSolverInfo.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" class btRaycastVehicle; class btIDebugDraw; -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" ///btDiscreteDynamicsWorld provides discrete rigid body simulation @@ -86,7 +86,7 @@ public: ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those - btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); + btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); virtual ~btDiscreteDynamicsWorld(); @@ -139,6 +139,8 @@ public: void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color); virtual void setConstraintSolver(btConstraintSolver* solver); + + virtual btConstraintSolver* getConstraintSolver(); virtual int getNumConstraints() const; @@ -151,6 +153,11 @@ public: return m_solverInfo; } + virtual btDynamicsWorldType getWorldType() const + { + return BT_DISCRETE_DYNAMICS_WORLD; + } + }; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h index 65b63fad4b5..a4c8bf3c559 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -16,20 +16,27 @@ subject to the following restrictions: #ifndef BT_DYNAMICS_WORLD_H #define BT_DYNAMICS_WORLD_H -#include "../../BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" class btTypedConstraint; class btRaycastVehicle; class btConstraintSolver; +enum btDynamicsWorldType +{ + BT_SIMPLE_DYNAMICS_WORLD=1, + BT_DISCRETE_DYNAMICS_WORLD=2, + BT_CONTINUOUS_DYNAMICS_WORLD=3 +}; + ///btDynamicsWorld is the baseclass for several dynamics implementation, basic, discrete, parallel, and continuous class btDynamicsWorld : public btCollisionWorld { public: - btDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache) - :btCollisionWorld(dispatcher,pairCache) + btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration) + :btCollisionWorld(dispatcher,broadphase,collisionConfiguration) { } @@ -65,6 +72,8 @@ class btDynamicsWorld : public btCollisionWorld virtual void removeRigidBody(btRigidBody* body) = 0; virtual void setConstraintSolver(btConstraintSolver* solver) = 0; + + virtual btConstraintSolver* getConstraintSolver() = 0; virtual int getNumConstraints() const { return 0; } @@ -72,6 +81,8 @@ class btDynamicsWorld : public btCollisionWorld virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; } + virtual btDynamicsWorldType getWorldType() const=0; + }; #endif //BT_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp index 02cf44d0cfa..03e60acdb19 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -39,6 +39,8 @@ btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionS m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), m_linearDamping(btScalar(0.)), m_angularDamping(btScalar(0.5)), + m_linearSleepingThreshold(gLinearSleepingThreshold), + m_angularSleepingThreshold(gAngularSleepingThreshold), m_optionalMotionState(motionState), m_contactSolverType(0), m_frictionSolverType(0) @@ -79,12 +81,15 @@ btRigidBody::btRigidBody( btScalar mass,const btTransform& worldTransform,btColl m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), + m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), + m_linearSleepingThreshold(gLinearSleepingThreshold), + m_angularSleepingThreshold(gAngularSleepingThreshold), m_linearDamping(btScalar(0.)), m_angularDamping(btScalar(0.5)), m_optionalMotionState(0), m_contactSolverType(0), m_frictionSolverType(0) + { m_worldTransform = worldTransform; @@ -113,7 +118,7 @@ btRigidBody::btRigidBody( btScalar mass,const btTransform& worldTransform,btColl -//#define EXPERIMENTAL_JITTER_REMOVAL 1 +#define EXPERIMENTAL_JITTER_REMOVAL 1 #ifdef EXPERIMENTAL_JITTER_REMOVAL //Bullet 2.20b has experimental damping code to reduce jitter just before objects fall asleep/deactivate //doesn't work very well yet (value 0 disabled this damping) @@ -342,4 +347,4 @@ void btRigidBody::removeConstraintRef(btTypedConstraint* c) { m_constraintRefs.remove(c); m_checkCollideWith = m_constraintRefs.size() > 0; -} \ No newline at end of file +} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h index 0707595d48e..b11f9f76d7d 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h @@ -16,11 +16,11 @@ subject to the following restrictions: #ifndef RIGIDBODY_H #define RIGIDBODY_H -#include "../../LinearMath/btAlignedObjectArray.h" -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btTransform.h" -#include "../../BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "../../BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btTransform.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" class btCollisionShape; class btMotionState; @@ -53,7 +53,10 @@ class btRigidBody : public btCollisionObject btScalar m_linearDamping; btScalar m_angularDamping; - + + btScalar m_linearSleepingThreshold; + btScalar m_angularSleepingThreshold; + //m_optionalMotionState allows to automatic synchronize the world transform for active objects btMotionState* m_optionalMotionState; @@ -70,6 +73,14 @@ public: btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); + virtual ~btRigidBody() + { + //No constraints should point to this rigidbody + //Remove constraints from the dynamics world before you delete the related rigidbodies. + btAssert(m_constraintRefs.size()==0); + } + + void proceedToTransform(const btTransform& newTrans); ///to keep collision detection and dynamics separate we don't store a rigidbody pointer @@ -100,11 +111,11 @@ public: void setDamping(btScalar lin_damping, btScalar ang_damping); - inline const btCollisionShape* getCollisionShape() const { + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_collisionShape; } - inline btCollisionShape* getCollisionShape() { + SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() { return m_collisionShape; } @@ -134,6 +145,12 @@ public: m_invInertiaLocal = diagInvInertia; } + void setSleepingThresholds(btScalar linear,btScalar angular) + { + m_linearSleepingThreshold = linear; + m_angularSleepingThreshold = angular; + } + void applyTorque(const btVector3& torque) { m_totalTorque += torque; @@ -168,7 +185,7 @@ public: } //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - inline void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) { if (m_inverseMass != btScalar(0.)) { @@ -238,7 +255,7 @@ public: - inline btScalar computeImpulseDenominator(const btPoint3& pos, const btVector3& normal) const + SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btPoint3& pos, const btVector3& normal) const { btVector3 r0 = pos - getCenterOfMassPosition(); @@ -250,19 +267,19 @@ public: } - inline btScalar computeAngularImpulseDenominator(const btVector3& axis) const + SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const { btVector3 vec = axis * getInvInertiaTensorWorld(); return axis.dot(vec); } - inline void updateDeactivation(btScalar timeStep) + SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep) { if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION)) return; - if ((getLinearVelocity().length2() < gLinearSleepingThreshold*gLinearSleepingThreshold) && - (getAngularVelocity().length2() < gAngularSleepingThreshold*gAngularSleepingThreshold)) + if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) && + (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold)) { m_deactivationTime += timeStep; } else @@ -273,7 +290,7 @@ public: } - inline bool wantsSleeping() + SIMD_FORCE_INLINE bool wantsSleeping() { if (getActivationState() == DISABLE_DEACTIVATION) @@ -348,6 +365,17 @@ public: void addConstraintRef(btTypedConstraint* c); void removeConstraintRef(btTypedConstraint* c); + btTypedConstraint* getConstraintRef(int index) + { + return m_constraintRefs[index]; + } + + int getNumConstraintRefs() + { + return m_constraintRefs.size(); + } + + int m_debugBodyId; }; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp index 4ebcb8e7517..3a78ec54f1c 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp @@ -32,8 +32,8 @@ extern "C" void btBulletDynamicsProbe () {} -btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) -:btDynamicsWorld(dispatcher,pairCache), +btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) +:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), m_constraintSolver(constraintSolver), m_ownsConstraintSolver(false), m_debugDrawer(0), @@ -46,7 +46,7 @@ m_gravity(0,0,-10) btSimpleDynamicsWorld::~btSimpleDynamicsWorld() { if (m_ownsConstraintSolver) - delete m_constraintSolver; + btAlignedFree( m_constraintSolver); } int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) @@ -74,8 +74,9 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b btContactSolverInfo infoGlobal; infoGlobal.m_timeStep = timeStep; - - m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc); + m_constraintSolver->prepareSolve(0,numManifolds); + m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc,m_dispatcher1); + m_constraintSolver->allSolved(infoGlobal,m_debugDrawer, m_stackAlloc); } ///integrate transforms @@ -133,7 +134,7 @@ void btSimpleDynamicsWorld::updateAabbs() btPoint3 minAabb,maxAabb; colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); btBroadphaseInterface* bp = getBroadphase(); - bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb); + bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); } } } @@ -204,8 +205,13 @@ void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) { if (m_ownsConstraintSolver) { - delete m_constraintSolver; + btAlignedFree(m_constraintSolver); } m_ownsConstraintSolver = false; m_constraintSolver = solver; } + +btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver() +{ + return m_constraintSolver; +} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h index 25f4ccd8e68..4e38f74a731 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h @@ -22,11 +22,8 @@ class btDispatcher; class btOverlappingPairCache; class btConstraintSolver; -///btSimpleDynamicsWorld demonstrates very basic usage of Bullet rigid body dynamics -///It can be used for basic simulations, and as a starting point for porting Bullet -///btSimpleDynamicsWorld lacks object deactivation, island management and other concepts. -///For more complicated simulations, btDiscreteDynamicsWorld and btContinuousDynamicsWorld are recommended -///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController +///btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds. +///Please use btDiscreteDynamicsWorld instead (or btContinuousDynamicsWorld once it is finished). class btSimpleDynamicsWorld : public btDynamicsWorld { protected: @@ -48,7 +45,7 @@ public: ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver - btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); + btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); virtual ~btSimpleDynamicsWorld(); @@ -77,6 +74,13 @@ public: virtual void setConstraintSolver(btConstraintSolver* solver); + virtual btConstraintSolver* getConstraintSolver(); + + virtual btDynamicsWorldType getWorldType() const + { + return BT_SIMPLE_DYNAMICS_WORLD; + } + }; #endif //BT_SIMPLE_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp index d53de7f3687..8dcd6d895e4 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp @@ -28,7 +28,8 @@ static btRigidBody s_fixedObject( 0,0,0); btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ) -:m_vehicleRaycaster(raycaster), +: btTypedConstraint(VEHICLE_CONSTRAINT_TYPE), +m_vehicleRaycaster(raycaster), m_pitchControl(btScalar(0.)) { m_chassisBody = chassis; @@ -507,8 +508,8 @@ btScalar calcRollingFriction(btWheelContactPoint& contactPoint) // calculate j that moves us to zero relative velocity j1 = -vrel * contactPoint.m_jacDiagABInv; - GEN_set_min(j1, maxImpulse); - GEN_set_max(j1, -maxImpulse); + btSetMin(j1, maxImpulse); + btSetMax(j1, -maxImpulse); return j1; } @@ -526,10 +527,14 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) return; - btVector3* forwardWS = new btVector3[numWheel]; - btVector3* axle = new btVector3[numWheel]; - btScalar* forwardImpulse = new btScalar[numWheel]; - btScalar* sideImpulse = new btScalar[numWheel]; + void* mem = btAlignedAlloc(numWheel*sizeof(btVector3),16); + btVector3* forwardWS = new (mem)btVector3[numWheel]; + mem = btAlignedAlloc(numWheel*sizeof(btVector3),16); + btVector3* axle = new (mem)btVector3[numWheel]; + mem = btAlignedAlloc(numWheel*sizeof(btScalar),16); + btScalar* forwardImpulse = new (mem)btScalar[numWheel]; + mem = btAlignedAlloc(numWheel*sizeof(btScalar),16); + btScalar* sideImpulse = new(mem) btScalar[numWheel]; int numWheelsOnGround = 0; @@ -701,10 +706,10 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) } } - delete []forwardWS; - delete [] axle; - delete[]forwardImpulse; - delete[] sideImpulse; + btAlignedFree(forwardWS); + btAlignedFree(axle); + btAlignedFree(forwardImpulse); + btAlignedFree(sideImpulse); } diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h index f4249599615..a84b185e947 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -11,11 +11,11 @@ #ifndef RAYCASTVEHICLE_H #define RAYCASTVEHICLE_H -#include "../Dynamics/btRigidBody.h" -#include "../ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" #include "btVehicleRaycaster.h" class btDynamicsWorld; -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" #include "btWheelInfo.h" class btVehicleTuning; diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h index 64a47fcaada..5112ce6d420 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h @@ -11,7 +11,7 @@ #ifndef VEHICLE_RAYCASTER_H #define VEHICLE_RAYCASTER_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" /// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting struct btVehicleRaycaster diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h index 2e349b3fde4..ac2729f4fd7 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h @@ -11,8 +11,8 @@ #ifndef WHEEL_INFO_H #define WHEEL_INFO_H -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" class btRigidBody; diff --git a/extern/bullet2/src/BulletDynamics/ibmsdk/Makefile b/extern/bullet2/src/BulletDynamics/ibmsdk/Makefile new file mode 100644 index 00000000000..b599a0fd9a1 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ibmsdk/Makefile @@ -0,0 +1,45 @@ +#### Source code Dirs +VPATH = \ +../ConstraintSolver \ +../Dynamics \ +../Vehicle + +ROOT = ../../.. + +#### Library +LIBRARY_ppu = bulletdynamics.a + +#### Compiler flags +CPPFLAGS = \ +-DUSE_LIBSPE2 \ +-I../ConstraintSolver \ +-I../Dynamics \ +-I../Vehicle \ +-I$(ROOT)/src \ +-I$(SDKINC) + +#### Optimization level flags +#CC_OPT_LEVEL = $(CC_OPT_LEVEL_DEBUG) +CC_OPT_LEVEL = -O3 + +##### Objects to be archived in lib + +OBJS = \ +btContactConstraint.o \ +btGeneric6DofConstraint.o \ +btHingeConstraint.o \ +btPoint2PointConstraint.o \ +btSequentialImpulseConstraintSolver.o \ +btSolve2LinearConstraint.o \ +btTypedConstraint.o \ +btDiscreteDynamicsWorld.o \ +btRigidBody.o \ +btSimpleDynamicsWorld.o \ +btRaycastVehicle.o \ +btWheelInfo.o +#### Install directories +INSTALL_DIR = $(ROOT)/lib/ibmsdk +INSTALL_FILES = $(LIBRARY_ppu) +CELL_TOP ?= /opt/ibm/cell-sdk/prototype + +include $(CELL_TOP)/make.footer diff --git a/extern/bullet2/src/LinearMath/CMakeLists.txt b/extern/bullet2/src/LinearMath/CMakeLists.txt index 207eed94a3e..82393547bfb 100644 --- a/extern/bullet2/src/LinearMath/CMakeLists.txt +++ b/extern/bullet2/src/LinearMath/CMakeLists.txt @@ -6,5 +6,6 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ADD_LIBRARY(LibLinearMath btQuickprof.cpp btGeometryUtil.cpp +btAlignedAllocator.cpp ) diff --git a/extern/bullet2/src/LinearMath/btAabbUtil2.h b/extern/bullet2/src/LinearMath/btAabbUtil2.h index 429163c8138..9b320961ba1 100644 --- a/extern/bullet2/src/LinearMath/btAabbUtil2.h +++ b/extern/bullet2/src/LinearMath/btAabbUtil2.h @@ -18,11 +18,9 @@ subject to the following restrictions: #define AABB_UTIL2 #include "btVector3.h" -#include "btSimdMinMax.h" +#include "btMinMax.h" -#define btMin(a,b) ((a < b ? a : b)) -#define btMax(a,b) ((a > b ? a : b)) /// conservative test for overlap between two aabbs diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp index 1f5877fa37e..6b33ddbb8cf 100644 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp @@ -15,17 +15,83 @@ subject to the following restrictions: #include "btAlignedAllocator.h" +int gNumAlignedAllocs = 0; +int gNumAlignedFree = 0; +int gTotalBytesAlignedAllocs = 0;//detect memory leaks -#if defined (BT_HAS_ALIGNED_ALOCATOR) +#ifdef BT_DEBUG_MEMORY_ALLOCATIONS +//this generic allocator provides the total allocated number of bytes +#include -#include -void* btAlignedAlloc (int size, int alignment) +void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename) { - return _aligned_malloc(size,alignment); + void *ret; + char *real; + unsigned long offset; + + gTotalBytesAlignedAllocs += size; + gNumAlignedAllocs++; + + printf("allocation#%d from %s,line %d, size %d\n",gNumAlignedAllocs,filename,line,size); + real = (char *)malloc(size + 2*sizeof(void *) + (alignment-1)); + if (real) { + offset = (alignment - (unsigned long)(real + 2*sizeof(void *))) & +(alignment-1); + ret = (void *)((real + 2*sizeof(void *)) + offset); + *((void **)(ret)-1) = (void *)(real); + *((int*)(ret)-2) = size; + + } else { + ret = (void *)(real);//?? + } + int* ptr = (int*)ret; + *ptr = 12; + return (ret); +} +#include +void btAlignedFreeInternal (void* ptr,int line,char* filename) +{ + + void* real; + gNumAlignedFree++; + + if (ptr) { + real = *((void **)(ptr)-1); + int size = *((int*)(ptr)-2); + gTotalBytesAlignedAllocs -= size; + + printf("free #%d from %s,line %d, size %d\n",gNumAlignedFree,filename,line,size); + + free(real); + } else + { + printf("NULL ptr\n"); + } } -void btAlignedFree (void* ptr) +#else //BT_DEBUG_MEMORY_ALLOCATIONS + + +#if defined (BT_HAS_ALIGNED_ALLOCATOR) + + + + + +#include +void* btAlignedAllocInternal (size_t size, int alignment) { + gNumAlignedAllocs++; + + void* ptr = _aligned_malloc(size,alignment); +// printf("btAlignedAllocInternal %d, %x\n",size,ptr); + return ptr; +} + +void btAlignedFreeInternal (void* ptr) +{ + gNumAlignedFree++; +// printf("btAlignedFreeInternal %x\n",ptr); _aligned_free(ptr); } @@ -35,36 +101,55 @@ void btAlignedFree (void* ptr) #include -int numAllocs = 0; -int numFree = 0; -void* btAlignedAlloc (int size, int alignment) + +void* btAlignedAllocInternal (size_t size, int alignment) { - numAllocs++; + gNumAlignedAllocs++; return memalign(alignment, size); } -void btAlignedFree (void* ptr) +void btAlignedFreeInternal (void* ptr) { - numFree++; + gNumAlignedFree++; free(ptr); } #else -///todo -///will add some multi-platform version that works without _aligned_malloc/_aligned_free -void* btAlignedAlloc (int size, int alignment) +void* btAlignedAllocInternal (size_t size, int alignment) { - return new char[size]; + void *ret; + char *real; + unsigned long offset; + + gNumAlignedAllocs++; + + real = (char *)malloc(size + sizeof(void *) + (alignment-1)); + if (real) { + offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); + ret = (void *)((real + sizeof(void *)) + offset); + *((void **)(ret)-1) = (void *)(real); + } else { + ret = (void *)(real); + } + return (ret); } -void btAlignedFree (void* ptr) +void btAlignedFreeInternal (void* ptr) { - delete [] (char*) ptr; + + void* real; + gNumAlignedFree++; + + if (ptr) { + real = *((void **)(ptr)-1); + free(real); + } } #endif // #endif +#endif //BT_DEBUG_MEMORY_ALLOCATIONS diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.h b/extern/bullet2/src/LinearMath/btAlignedAllocator.h index 07585717f45..2b48e79e497 100644 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.h +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.h @@ -21,12 +21,26 @@ subject to the following restrictions: ///that is better portable and more predictable #include "btScalar.h" +//#define BT_DEBUG_MEMORY_ALLOCATIONS 1 +#ifdef BT_DEBUG_MEMORY_ALLOCATIONS -void* btAlignedAlloc (int size, int alignment); +#define btAlignedAlloc(a,b) \ + btAlignedAllocInternal(a,b,__LINE__,__FILE__) -void btAlignedFree (void* ptr); +#define btAlignedFree(ptr) \ + btAlignedFreeInternal(ptr,__LINE__,__FILE__) +void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename); +void btAlignedFreeInternal (void* ptr,int line,char* filename); + +#else + void* btAlignedAllocInternal (size_t size, int alignment); + void btAlignedFreeInternal (void* ptr); + + #define btAlignedAlloc(a,b) btAlignedAllocInternal(a,b) + #define btAlignedFree(ptr) btAlignedFreeInternal(ptr) +#endif typedef int size_type; diff --git a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h index 8bef5eb5d06..66911316fbb 100644 --- a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h +++ b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h @@ -50,6 +50,8 @@ class btAlignedObjectArray int m_size; int m_capacity; T* m_data; + //PCK: added this line + bool m_ownsMemory; protected: SIMD_FORCE_INLINE int allocSize(int size) @@ -69,6 +71,8 @@ class btAlignedObjectArray SIMD_FORCE_INLINE void init() { + //PCK: added this line + m_ownsMemory = true; m_data = 0; m_size = 0; m_capacity = 0; @@ -92,7 +96,11 @@ class btAlignedObjectArray SIMD_FORCE_INLINE void deallocate() { if(m_data) { - m_allocator.deallocate(m_data); + //PCK: enclosed the deallocation in this block + if (m_ownsMemory) + { + m_allocator.deallocate(m_data); + } m_data = 0; } } @@ -223,6 +231,9 @@ class btAlignedObjectArray destroy(0,size()); deallocate(); + + //PCK: added this line + m_ownsMemory = true; m_data = s; @@ -360,8 +371,16 @@ class btAlignedObjectArray } } + //PCK: whole function + void initializeFromBuffer(void *buffer, int size, int capacity) + { + clear(); + m_ownsMemory = false; + m_data = (T*)buffer; + m_size = size; + m_capacity = capacity; + } + }; #endif //BT_OBJECT_ARRAY__ - - diff --git a/extern/bullet2/src/LinearMath/btIDebugDraw.h b/extern/bullet2/src/LinearMath/btIDebugDraw.h index 5f40ca39157..2d96cff5055 100644 --- a/extern/bullet2/src/LinearMath/btIDebugDraw.h +++ b/extern/bullet2/src/LinearMath/btIDebugDraw.h @@ -60,6 +60,8 @@ class btIDebugDraw virtual void reportErrorWarning(const char* warningString) = 0; + virtual void draw3dText(const btVector3& location,const char* textString) = 0; + virtual void setDebugMode(int debugMode) =0; virtual int getDebugMode() const = 0; diff --git a/extern/bullet2/src/LinearMath/btMatrix3x3.h b/extern/bullet2/src/LinearMath/btMatrix3x3.h index 94f53c3c0a5..59680ff460d 100644 --- a/extern/bullet2/src/LinearMath/btMatrix3x3.h +++ b/extern/bullet2/src/LinearMath/btMatrix3x3.h @@ -356,7 +356,7 @@ class btMatrix3x3 { m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(), m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(), m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(), - m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].x()); + m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z()); } SIMD_FORCE_INLINE btMatrix3x3 diff --git a/extern/bullet2/src/LinearMath/btMinMax.h b/extern/bullet2/src/LinearMath/btMinMax.h index 1b8a3633f38..5e27d62a4a4 100644 --- a/extern/bullet2/src/LinearMath/btMinMax.h +++ b/extern/bullet2/src/LinearMath/btMinMax.h @@ -18,15 +18,15 @@ subject to the following restrictions: #define GEN_MINMAX_H template -SIMD_FORCE_INLINE const T& GEN_min(const T& a, const T& b) +SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) { - return b < a ? b : a; + return a < b ? a : b ; } template -SIMD_FORCE_INLINE const T& GEN_max(const T& a, const T& b) +SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) { - return a < b ? b : a; + return a > b ? a : b; } template @@ -36,7 +36,7 @@ SIMD_FORCE_INLINE const T& GEN_clamped(const T& a, const T& lb, const T& ub) } template -SIMD_FORCE_INLINE void GEN_set_min(T& a, const T& b) +SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) { if (b < a) { @@ -45,7 +45,7 @@ SIMD_FORCE_INLINE void GEN_set_min(T& a, const T& b) } template -SIMD_FORCE_INLINE void GEN_set_max(T& a, const T& b) +SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) { if (a < b) { diff --git a/extern/bullet2/src/LinearMath/btPoolAllocator.h b/extern/bullet2/src/LinearMath/btPoolAllocator.h new file mode 100755 index 00000000000..ad772ae123f --- /dev/null +++ b/extern/bullet2/src/LinearMath/btPoolAllocator.h @@ -0,0 +1,94 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + +#ifndef _BT_POOL_ALLOCATOR_H +#define _BT_POOL_ALLOCATOR_H + +#include "btScalar.h" +#include "btAlignedAllocator.h" + +class btPoolAllocator +{ + int m_elemSize; + int m_maxElements; + int m_freeCount; + void* m_firstFree; + unsigned char* m_pool; + +public: + + btPoolAllocator(int elemSize, int maxElements) + :m_elemSize(elemSize), + m_maxElements(maxElements) + { + m_pool = (unsigned char*) btAlignedAlloc(m_elemSize*m_maxElements,16); + + unsigned char* p = m_pool; + m_firstFree = p; + m_freeCount = m_maxElements; + int count = m_maxElements; + while (--count) { + *(void**)p = (p + m_elemSize); + p += m_elemSize; + } + *(void**)p = 0; + } + + ~btPoolAllocator() + { + btAlignedFree( m_pool); + } + + int getFreeCount() const + { + return m_freeCount; + } + + void* allocate(int size) + { + btAssert(!size || size<=m_elemSize); + btAssert(m_freeCount>0); + void* result = m_firstFree; + m_firstFree = *(void**)m_firstFree; + --m_freeCount; + return result; + } + + bool validPtr(void* ptr) + { + if (ptr) { + if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize)) + { + return true; + } + } + return false; + } + + void free(void* ptr) + { + if (ptr) { + btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize); + + *(void**)ptr = m_firstFree; + m_firstFree = ptr; + ++m_freeCount; + } + } + + +}; + +#endif //_BT_POOL_ALLOCATOR_H diff --git a/extern/bullet2/src/LinearMath/btQuadWord.h b/extern/bullet2/src/LinearMath/btQuadWord.h index 961ac484d20..2e5950ebd5d 100644 --- a/extern/bullet2/src/LinearMath/btQuadWord.h +++ b/extern/bullet2/src/LinearMath/btQuadWord.h @@ -17,19 +17,24 @@ subject to the following restrictions: #define SIMD_QUADWORD_H #include "btScalar.h" +#include "btMinMax.h" +//ATTRIBUTE_ALIGNED16(class) btQuadWordStorage +//some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword. todo: look into this +class btQuadWordStorage +{ +protected: + btScalar m_x; + btScalar m_y; + btScalar m_z; + btScalar m_unusedW; +}; ///btQuadWord is base-class for vectors, points -class btQuadWord +class btQuadWord : public btQuadWordStorage { - protected: - btScalar m_x; - btScalar m_y; - btScalar m_z; - btScalar m_unusedW; - public: // SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_x)[i]; } @@ -61,6 +66,8 @@ class btQuadWord SIMD_FORCE_INLINE operator btScalar *() { return &m_x; } SIMD_FORCE_INLINE operator const btScalar *() const { return &m_x; } + + SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) { m_x=x; @@ -89,47 +96,36 @@ class btQuadWord { } - SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z) - :m_x(x),m_y(y),m_z(z) - //todo, remove this in release/simd ? - ,m_unusedW(btScalar(0.)) + SIMD_FORCE_INLINE btQuadWord(const btQuadWordStorage& q) { + *((btQuadWordStorage*)this) = q; + } + + SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z) + { + m_x = x, m_y = y, m_z = z, m_unusedW = 0.0f; } SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) - :m_x(x),m_y(y),m_z(z),m_unusedW(w) { + m_x = x, m_y = y, m_z = z, m_unusedW = w; } SIMD_FORCE_INLINE void setMax(const btQuadWord& other) { - if (other.m_x > m_x) - m_x = other.m_x; - - if (other.m_y > m_y) - m_y = other.m_y; - - if (other.m_z > m_z) - m_z = other.m_z; - - if (other.m_unusedW > m_unusedW) - m_unusedW = other.m_unusedW; + btSetMax(m_x, other.m_x); + btSetMax(m_y, other.m_y); + btSetMax(m_z, other.m_z); + btSetMax(m_unusedW, other.m_unusedW); } SIMD_FORCE_INLINE void setMin(const btQuadWord& other) { - if (other.m_x < m_x) - m_x = other.m_x; - - if (other.m_y < m_y) - m_y = other.m_y; - - if (other.m_z < m_z) - m_z = other.m_z; - - if (other.m_unusedW < m_unusedW) - m_unusedW = other.m_unusedW; + btSetMin(m_x, other.m_x); + btSetMin(m_y, other.m_y); + btSetMin(m_z, other.m_z); + btSetMin(m_unusedW, other.m_unusedW); } diff --git a/extern/bullet2/src/LinearMath/btQuaternion.h b/extern/bullet2/src/LinearMath/btQuaternion.h index 50334970ba6..27ab1fcd2c3 100644 --- a/extern/bullet2/src/LinearMath/btQuaternion.h +++ b/extern/bullet2/src/LinearMath/btQuaternion.h @@ -285,7 +285,7 @@ slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) } SIMD_FORCE_INLINE btVector3 -quatRotate(btQuaternion& rotation, btVector3& v) +quatRotate(const btQuaternion& rotation, const btVector3& v) { btQuaternion q = rotation * v; q *= rotation.inverse(); @@ -293,7 +293,7 @@ quatRotate(btQuaternion& rotation, btVector3& v) } SIMD_FORCE_INLINE btQuaternion -shortestArcQuat(btVector3& v0,btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized +shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized { btVector3 c = v0.cross(v1); btScalar d = v0.dot(v1); @@ -308,7 +308,7 @@ shortestArcQuat(btVector3& v0,btVector3& v1) // Game Programming Gems 2.10. make } SIMD_FORCE_INLINE btQuaternion -shortestArcQuatNormalize(btVector3& v0,btVector3& v1) +shortestArcQuatNormalize2(btVector3& v0,btVector3& v1) { v0.normalize(); v1.normalize(); diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h index 01ad93e786a..85dfaf3eb83 100644 --- a/extern/bullet2/src/LinearMath/btScalar.h +++ b/extern/bullet2/src/LinearMath/btScalar.h @@ -23,20 +23,33 @@ subject to the following restrictions: #include #include + +inline int btGetVersion() +{ + return 264; +} + #ifdef WIN32 #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) + #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a + #define ATTRIBUTE_ALIGNED128(a) a #else - #define BT_HAS_ALIGNED_ALOCATOR + #define BT_HAS_ALIGNED_ALLOCATOR #pragma warning(disable:4530) #pragma warning(disable:4996) #pragma warning(disable:4786) #define SIMD_FORCE_INLINE __forceinline #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a + #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a #ifdef _XBOX #define BT_USE_VMX128 + + #include + #define BT_HAVE_NATIVE_FSEL + #define btFsel(a,b,c) __fsel((a),(b),(c)) #else #define BT_USE_SSE #endif @@ -46,29 +59,61 @@ subject to the following restrictions: #define btAssert assert //btFullAssert is optional, slows down a lot #define btFullAssert(x) + + #define btLikely(_c) _c + #define btUnlikely(_c) _c + #else #if defined (__CELLOS_LV2__) #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) #ifndef assert #include #endif #define btAssert assert //btFullAssert is optional, slows down a lot #define btFullAssert(x) + + #define btLikely(_c) _c + #define btUnlikely(_c) _c + #else +#ifdef USE_LIBSPE2 + + #define SIMD_FORCE_INLINE __inline + #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) + #ifndef assert + #include + #endif + #define btAssert assert + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + + + #define btLikely(_c) __builtin_expect((_c), 1) + #define btUnlikely(_c) __builtin_expect((_c), 0) + + +#else //non-windows systems #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a + #define ATTRIBUTE_ALIGNED128(a) a #ifndef assert #include #endif #define btAssert assert //btFullAssert is optional, slows down a lot #define btFullAssert(x) + + +#endif // LIBSPE2 + #endif //__CELLOS_LV2__ #endif @@ -88,6 +133,14 @@ typedef float btScalar; #endif +#define BT_DECLARE_ALIGNED_ALLOCATOR() \ + SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ + SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ + SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ + SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ + + + #if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS) SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); } @@ -105,12 +158,34 @@ SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } #else -SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrtf(x); } +SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) +{ +#ifdef USE_APPROXIMATION + double x, z, tempf; + unsigned long *tfptr = ((unsigned long *)&tempf) + 1; + + tempf = y; + *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ + x = tempf; + z = y*btScalar(0.5); /* hoist out the “/2” */ + x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */ + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + return x*y; +#else + return sqrtf(y); +#endif +} SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); } SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } -SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acosf(x); } +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { + btAssert(x <= btScalar(1.)); + return acosf(x); +} SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); } SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } @@ -159,14 +234,6 @@ SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) { return (!((a) <= eps)); } -/*SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } -SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } -SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } -SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acosf(x); } -SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); } -SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } -SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } -*/ SIMD_FORCE_INLINE int btIsNegative(btScalar x) { return x < btScalar(0.0) ? 1 : 0; @@ -177,5 +244,151 @@ SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; #define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name +#ifndef btFsel +SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c) +{ + return a >= 0 ? b : c; +} +#endif +#define btFsels(a,b,c) (btScalar)btFsel(a,b,c) + + +SIMD_FORCE_INLINE bool btMachineIsLittleEndian() +{ + long int i = 1; + const char *p = (const char *) &i; + if (p[0] == 1) // Lowest address contains the least significant byte + return true; + else + return false; +} + + + +///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360 +///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html +SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) +{ + // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero + // Rely on positive value or'ed with its negative having sign bit on + // and zero value or'ed with its negative (which is still zero) having sign bit off + // Use arithmetic shift right, shifting the sign bit through all 32 bits + unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); + unsigned testEqz = ~testNz; + return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); +} +SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero) +{ + unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); + unsigned testEqz = ~testNz; + return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); +} +SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero) +{ +#ifdef BT_HAVE_NATIVE_FSEL + return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero); +#else + return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; +#endif +} + +template SIMD_FORCE_INLINE void btSwap(T& a, T& b) +{ + T tmp = a; + a = b; + b = tmp; +} + + +//PCK: endian swapping functions +SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val) +{ + return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); +} + +SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val) +{ + return (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)); +} + +SIMD_FORCE_INLINE unsigned btSwapEndian(int val) +{ + return btSwapEndian((unsigned)val); +} + +SIMD_FORCE_INLINE unsigned short btSwapEndian(short val) +{ + return btSwapEndian((unsigned short) val); +} + +///btSwapFloat uses using char pointers to swap the endianness +////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values +///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754. +///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception. +///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you. +///so instead of returning a float/double, we return integer/long long integer +SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d) +{ + unsigned int a; + unsigned char *dst = (unsigned char *)&a; + unsigned char *src = (unsigned char *)&d; + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; + return a; +} + +// unswap using char pointers +SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) +{ + float d; + unsigned char *src = (unsigned char *)&a; + unsigned char *dst = (unsigned char *)&d; + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; + + return d; +} + + +// swap using char pointers +SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst) +{ + unsigned char *src = (unsigned char *)&d; + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; + +} + +// unswap using char pointers +SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) +{ + double d; + unsigned char *dst = (unsigned char *)&d; + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; + + return d; +} + #endif //SIMD___SCALAR_H diff --git a/extern/bullet2/src/LinearMath/btStackAlloc.h b/extern/bullet2/src/LinearMath/btStackAlloc.h index d219b453537..ac940cd2edd 100644 --- a/extern/bullet2/src/LinearMath/btStackAlloc.h +++ b/extern/bullet2/src/LinearMath/btStackAlloc.h @@ -21,6 +21,7 @@ Nov.2006 #define BT_STACK_ALLOC #include "btScalar.h" //for btAssert +#include "btAlignedAllocator.h" struct btBlock { @@ -39,7 +40,7 @@ public: inline void create(unsigned int size) { destroy(); - data = new unsigned char[size]; + data = (unsigned char*) btAlignedAlloc(size,16); totalsize = size; } inline void destroy() @@ -49,12 +50,20 @@ public: if(usedsize==0) { - if(!ischild) delete[] data; + if(!ischild && data) + btAlignedFree(data); + data = 0; usedsize = 0; } } + + int getAvailableMemory() const + { + return totalsize - usedsize; + } + unsigned char* allocate(unsigned int size) { const unsigned int nus(usedsize+size); @@ -68,7 +77,7 @@ public: return(0); } - inline btBlock* beginBlock() + SIMD_FORCE_INLINE btBlock* beginBlock() { btBlock* pb = (btBlock*)allocate(sizeof(btBlock)); pb->previous = current; @@ -76,7 +85,7 @@ public: current = pb; return(pb); } - inline void endBlock(btBlock* block) + SIMD_FORCE_INLINE void endBlock(btBlock* block) { btAssert(block==current); //Raise(L"Unmatched blocks"); diff --git a/extern/bullet2/src/LinearMath/btTransform.h b/extern/bullet2/src/LinearMath/btTransform.h index 2d55fec83a4..883b3a5d2b7 100644 --- a/extern/bullet2/src/LinearMath/btTransform.h +++ b/extern/bullet2/src/LinearMath/btTransform.h @@ -92,13 +92,7 @@ public: m_basis.getRotation(q); return q; } - template - void setValue(const Scalar2 *m) - { - m_basis.setValue(m); - m_origin.setValue(&m[12]); - } - + void setFromOpenGLMatrix(const btScalar *m) { diff --git a/extern/bullet2/src/LinearMath/btTransformUtil.h b/extern/bullet2/src/LinearMath/btTransformUtil.h index bc42fd166b6..d39e2e10074 100644 --- a/extern/bullet2/src/LinearMath/btTransformUtil.h +++ b/extern/bullet2/src/LinearMath/btTransformUtil.h @@ -25,7 +25,7 @@ subject to the following restrictions: #define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */ -inline btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) +SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) { return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), @@ -33,7 +33,7 @@ inline btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& sup } -inline void btPlaneSpace1 (const btVector3& n, btVector3& p, btVector3& q) +SIMD_FORCE_INLINE void btPlaneSpace1 (const btVector3& n, btVector3& p, btVector3& q) { if (btFabs(n.z()) > SIMDSQRT12) { // choose p in y-z plane @@ -121,6 +121,10 @@ public: dmat.getRotation(dorn); #endif//USE_QUATERNION_DIFF + ///floating point inaccuracy can lead to w component > 1..., which breaks + + dorn.normalize(); + angle = dorn.getAngle(); axis = btVector3(dorn.x(),dorn.y(),dorn.z()); axis[3] = btScalar(0.); diff --git a/extern/bullet2/src/LinearMath/btVector3.h b/extern/bullet2/src/LinearMath/btVector3.h index 74d41ad2a19..1e331272dd8 100644 --- a/extern/bullet2/src/LinearMath/btVector3.h +++ b/extern/bullet2/src/LinearMath/btVector3.h @@ -27,6 +27,10 @@ class btVector3 : public btQuadWord { public: SIMD_FORCE_INLINE btVector3() {} + SIMD_FORCE_INLINE btVector3(const btQuadWordStorage& q) + : btQuadWord(q) + { + } SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z) @@ -399,4 +403,50 @@ public: }; + +///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal) +{ + #ifdef BT_USE_DOUBLE_PRECISION + unsigned char* dest = (unsigned char*) &destVal; + unsigned char* src = (unsigned char*) &sourceVal; + dest[0] = src[7]; + dest[1] = src[6]; + dest[2] = src[5]; + dest[3] = src[4]; + dest[4] = src[3]; + dest[5] = src[2]; + dest[6] = src[1]; + dest[7] = src[0]; +#else + unsigned char* dest = (unsigned char*) &destVal; + unsigned char* src = (unsigned char*) &sourceVal; + dest[0] = src[3]; + dest[1] = src[2]; + dest[2] = src[1]; + dest[3] = src[0]; +#endif //BT_USE_DOUBLE_PRECISION +} +///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec) +{ + for (int i=0;i<4;i++) + { + btSwapScalarEndian(sourceVec[i],destVec[i]); + } + +} + +///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector) +{ + + btVector3 swappedVec; + for (int i=0;i<4;i++) + { + btSwapScalarEndian(vector[i],swappedVec[i]); + } + vector = swappedVec; +} + #endif //SIMD__VECTOR3_H diff --git a/extern/bullet2/src/LinearMath/ibmsdk/Makefile b/extern/bullet2/src/LinearMath/ibmsdk/Makefile new file mode 100644 index 00000000000..2ad26576241 --- /dev/null +++ b/extern/bullet2/src/LinearMath/ibmsdk/Makefile @@ -0,0 +1,30 @@ +#### Source code Dirs +VPATH = ../ + +ROOT = ../../.. + +#### Library +LIBRARY_ppu = bulletmath.a + +#### Compiler flags +CPPFLAGS = \ +-DUSE_LIBSPE2 \ +-I$(ROOT)/src \ +-I$(SDKINC) + +#### Optimization level flags +#CC_OPT_LEVEL = $(CC_OPT_LEVEL_DEBUG) +CC_OPT_LEVEL = -O3 + +##### Objects to be archived in lib + +OBJS = \ +btAlignedAllocator.o \ +btGeometryUtil.o \ +btQuickprof.o + +#### Install directories +INSTALL_DIR = $(ROOT)/lib/ibmsdk +INSTALL_FILES = $(LIBRARY_ppu) +CELL_TOP ?= /opt/ibm/cell-sdk/prototype +include $(CELL_TOP)/make.footer diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index 127752777c8..7697a58d81b 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -22,74 +22,8 @@ elif sys.platform=='darwin': cflags += ['-O2','-pipe', '-fPIC', '-funsigned-char', '-ffast-math'] linearmath_src = env.Glob("LinearMath/*.cpp") -bulletdyn_src = ["BulletDynamics/ConstraintSolver/btContactConstraint.cpp", - "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp", - "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp", - "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp", - "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp", - "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp", - "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp", - "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp", - "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp", - "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp", - "BulletDynamics/Dynamics/btRigidBody.cpp", - "BulletDynamics/Dynamics/Bullet-C-Api.cpp", - "BulletDynamics/Vehicle/btRaycastVehicle.cpp", - "BulletDynamics/Vehicle/btWheelInfo.cpp"] -collision_src = ["BulletCollision/BroadphaseCollision/btAxisSweep3.cpp", - "BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp", - "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp", - "BulletCollision/BroadphaseCollision/btDispatcher.cpp", - "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", - "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", - "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp", - "BulletCollision/CollisionDispatch/btCollisionObject.cpp", - "BulletCollision/CollisionDispatch/btCollisionWorld.cpp", - "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btManifoldResult.cpp", - "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp", - "BulletCollision/CollisionDispatch/btUnionFind.cpp", - "BulletCollision/CollisionShapes/btBoxShape.cpp", - "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btCollisionShape.cpp", - "BulletCollision/CollisionShapes/btCompoundShape.cpp", - "BulletCollision/CollisionShapes/btConcaveShape.cpp", - "BulletCollision/CollisionShapes/btConeShape.cpp", - "BulletCollision/CollisionShapes/btConvexHullShape.cpp", - "BulletCollision/CollisionShapes/btConvexShape.cpp", - "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btCylinderShape.cpp", - "BulletCollision/CollisionShapes/btEmptyShape.cpp", - "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp", - "BulletCollision/CollisionShapes/btMultiSphereShape.cpp", - "BulletCollision/CollisionShapes/btOptimizedBvh.cpp", - "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp", - "BulletCollision/CollisionShapes/btTetrahedronShape.cpp", - "BulletCollision/CollisionShapes/btSphereShape.cpp", - "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp", - "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp", - "BulletCollision/CollisionShapes/btTriangleCallback.cpp", - "BulletCollision/CollisionShapes/btTriangleBuffer.cpp", - "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp", - "BulletCollision/CollisionShapes/btTriangleMesh.cpp", - "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp", - "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp", - "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp", - "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp", - "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp", - "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp", - "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp"] +bulletdyn_src = env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.cpp") + env.Glob("BulletDynamics/Vehicle/*.cpp") +collision_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp") + env.Glob("BulletCollision/CollisionDispatch/*.cpp") + env.Glob("BulletCollision/CollisionShapes/*.cpp") + env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp") incs = '. BulletCollision BulletDynamics LinearMath' diff --git a/extern/bullet2/src/btBulletCollisionCommon.h b/extern/bullet2/src/btBulletCollisionCommon.h index 8417ccc671f..a309f7d76d2 100644 --- a/extern/bullet2/src/btBulletCollisionCommon.h +++ b/extern/bullet2/src/btBulletCollisionCommon.h @@ -32,17 +32,19 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btConvexHullShape.h" #include "BulletCollision/CollisionShapes/btTriangleMesh.h" #include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/CollisionShapes/btTetrahedronShape.h" #include "BulletCollision/CollisionShapes/btEmptyShape.h" -#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" ///Narrowphase Collision Detector #include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" ///Dispatching and generation of collision pairs (broadphase) #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" diff --git a/extern/bullet2/src/btBulletDynamicsCommon.h b/extern/bullet2/src/btBulletDynamicsCommon.h index 25f016cba8a..5d08dac0c0d 100644 --- a/extern/bullet2/src/btBulletDynamicsCommon.h +++ b/extern/bullet2/src/btBulletDynamicsCommon.h @@ -20,6 +20,8 @@ subject to the following restrictions: #include "btBulletCollisionCommon.h" #include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "BulletDynamics/Dynamics/btContinuousDynamicsWorld.h" + #include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h" #include "BulletDynamics/Dynamics/btRigidBody.h" diff --git a/extern/bullet2/src/ibmsdk/Makefile b/extern/bullet2/src/ibmsdk/Makefile new file mode 100644 index 00000000000..768fffd35a4 --- /dev/null +++ b/extern/bullet2/src/ibmsdk/Makefile @@ -0,0 +1,10 @@ +#### Visit Bullet library ibmsdk dirs and build code +CELL_TOP ?= /opt/ibm/cell-sdk/prototype + +DIRS := \ +../BulletCollision/ibmsdk \ +../BulletDynamics/ibmsdk \ +../LinearMath/ibmsdk + + +include $(CELL_TOP)/make.footer From e14457b921060b73491a306aee012e468116710c Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 6 Nov 2007 14:27:06 +0000 Subject: [PATCH 049/101] updated bullet to version 2.64 and hopefully didn't break too much things in CcdPhysicsEnvironment.cpp, but it compiles and works for me --- source/blender/blenkernel/intern/cloth.c | 2 +- source/blender/blenkernel/intern/implicit.c | 55 ++----------------- .../Converter/KX_BlenderSceneConverter.cpp | 2 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 29 +++++----- .../Physics/Bullet/CcdPhysicsEnvironment.h | 2 +- 5 files changed, 21 insertions(+), 69 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 9720ec6b141..3b065fc16f5 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -171,7 +171,7 @@ void cloth_init (ClothModifierData *clmd) // also from softbodies clmd->sim_parms.maxgoal = 1.0; clmd->sim_parms.mingoal = 0.0; - clmd->sim_parms.defgoal = 0.7; + clmd->sim_parms.defgoal = 0.0; clmd->sim_parms.goalspring = 100.0; clmd->sim_parms.goalfrict = 0.0; diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 41cc9e8cef4..a72887d7eb9 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -2165,55 +2165,6 @@ void collisions_collision_moving_tris(ClothModifierData *clmd, ClothModifierData */ } - -// move collision objects forward in time and update static bounding boxes -void collisions_update_collision_objects(float step) -{ - Base *base=NULL; - ClothModifierData *coll_clmd=NULL; - Object *coll_ob=NULL; - unsigned int i=0; - /* - // search all objects for collision object - for (base = G.scene->base.first; base; base = base->next) - { - - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - if (!coll_clmd) - continue; - - // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) - { - if (coll_clmd->clothObject && coll_clmd->clothObject->tree) - { - Cloth *coll_cloth = coll_clmd->clothObject; - BVH *coll_bvh = coll_clmd->clothObject->tree; - unsigned int coll_numverts = coll_cloth->numverts; - - // update position of collision object - for(i = 0; i < coll_numverts; i++) - { - VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx); - - VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step); - - // no dt here because of float rounding errors - VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold); - } - - // update BVH of collision object - // bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING - } - else - printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } - } - */ -} - - void collisions_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) { /* @@ -2251,7 +2202,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, //////////////////////////////////////////////////////////// // static collisions //////////////////////////////////////////////////////////// - /* + // update cloth bvh bvh_update_from_float3(bvh1, cloth->current_xold, cloth->numverts, cloth->current_x, 0); // 0 means STATIC, 1 means MOVING (see later in this function) @@ -2276,6 +2227,8 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, // fill collision list collisions += bvh_traverse(bvh1->root, bvh2->root, &collision_list); + // call static collision response + // free collision list if(collision_list) { @@ -2303,7 +2256,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, VECADD(cloth->current_x[i], cloth->current_xold[i], cloth->current_v[i]); } ////////////////////////////////////////////// - */ + // Test on *simple* selfcollisions collisions = 1; count = 0; diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 47d8f186653..01289113bf1 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -307,7 +307,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename, case UseBullet: { CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment(); - ccdPhysEnv->setDebugDrawer(new BlenderDebugDraw()); + // ccdPhysEnv->setDebugDrawer(new BlenderDebugDraw()); ccdPhysEnv->setDeactivationLinearTreshold(0.8f); // default, can be overridden by Python ccdPhysEnv->setDeactivationAngularTreshold(1.0f); // default, can be overridden by Python diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 99c3e5f77c7..db82dde9663 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -295,7 +295,7 @@ static void DrawAabb(btIDebugDraw* debugDrawer,const btVector3& from,const btVec -CcdPhysicsEnvironment::CcdPhysicsEnvironment(btDispatcher* dispatcher,btOverlappingPairCache* pairCache) +CcdPhysicsEnvironment::CcdPhysicsEnvironment(btDispatcher* dispatcher,btBroadphaseInterface* broadphase) :m_scalingPropagated(false), m_numIterations(10), m_numTimeSubSteps(1), @@ -303,32 +303,31 @@ m_ccdMode(0), m_solverType(-1), m_profileTimings(0), m_enableSatCollisionDetection(false) -{ - +{ for (int i=0;isetGravity(m_gravity); @@ -620,7 +619,7 @@ int CcdPhysicsEnvironment::createUniversalD6Constraint( genericConstraint = new btGeneric6DofConstraint( *rb0,*rb1, - frameInA,frameInB); + frameInA,frameInB, 1); genericConstraint->setLinearLowerLimit(linearMinLimits); genericConstraint->setLinearUpperLimit(linearMaxLimits); genericConstraint->setAngularLowerLimit(angularMinLimits); @@ -687,8 +686,8 @@ struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResul //ignore client... if (curHit != m_ignoreClient) { - //if valid - return ClosestRayResultCallback::AddSingleResult(rayResult); + //if valid; also return normal in world space + return ClosestRayResultCallback::AddSingleResult(rayResult, 1); } return m_closestHitFraction; } @@ -805,7 +804,7 @@ void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float { //param = 1..12, min0,max0,min1,max1...min6,max6 btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint; - genCons->SetLimit(param,value0,value1); + genCons->setLimit(param,value0,value1); break; }; default: @@ -1099,7 +1098,7 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl genericConstraint = new btGeneric6DofConstraint( *rb0,*rb1, - frameInA,frameInB); + frameInA,frameInB, 1); } else @@ -1122,7 +1121,7 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl genericConstraint = new btGeneric6DofConstraint( *rb0,s_fixedObject2, - frameInA,frameInB); + frameInA,frameInB, 1); } if (genericConstraint) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 66a6ed59c17..8d2b961db85 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -71,7 +71,7 @@ protected: public: - CcdPhysicsEnvironment(btDispatcher* dispatcher=0, btOverlappingPairCache* pairCache=0); + CcdPhysicsEnvironment(btDispatcher* dispatcher=0, btBroadphaseInterface* broadphase=0); virtual ~CcdPhysicsEnvironment(); From d4e881761dc3e7649f62d92a96648c2f2b69925d Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 8 Nov 2007 03:31:52 +0000 Subject: [PATCH 050/101] Introduced a selfmade AIMEX (adaptive implicit-explicit condition into force calculation for jacobi matrices -->results in ca. 15% speedup --- source/blender/blenkernel/intern/implicit.c | 73 ++++++++++--------- source/blender/blenkernel/intern/kdop.c | 4 +- source/blender/blenkernel/intern/pointcache.c | 2 +- source/blender/src/buttons_object.c | 2 +- 4 files changed, 44 insertions(+), 37 deletions(-) diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index a72887d7eb9..ee8a440735a 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -691,7 +691,7 @@ static float I[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; static float ZERO[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}; typedef struct Implicit_Data { - lfVector *X, *V, *Xnew, *Vnew, *olddV, *F, *B, *dV, *z; + lfVector *X, *V, *Xnew, *Vnew, *F, *B, *dV, *z; fmatrix3x3 *A, *dFdV, *dFdX, *S, *P, *Pinv, *bigI; } Implicit_Data; @@ -727,11 +727,10 @@ int implicit_init (Object *ob, ClothModifierData *clmd) id->Xnew = create_lfvector(cloth->numverts); id->V = create_lfvector(cloth->numverts); id->Vnew = create_lfvector(cloth->numverts); - id->olddV = create_lfvector(cloth->numverts); - zero_lfvector(id->olddV, cloth->numverts); id->F = create_lfvector(cloth->numverts); id->B = create_lfvector(cloth->numverts); id->dV = create_lfvector(cloth->numverts); + zero_lfvector(id->dV, cloth->numverts); id->z = create_lfvector(cloth->numverts); for(i=0;inumverts;i++) @@ -799,7 +798,6 @@ int implicit_free (ClothModifierData *clmd) del_lfvector(id->Xnew); del_lfvector(id->V); del_lfvector(id->Vnew); - del_lfvector(id->olddV); del_lfvector(id->F); del_lfvector(id->B); del_lfvector(id->dV); @@ -924,8 +922,6 @@ int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatr d = create_lfvector(numverts); tmp = create_lfvector(numverts); r = create_lfvector(numverts); - - // zero_lfvector(ldV, CLOTHPARTICLES); filter(ldV, S); add_lfvector_lfvector(ldV, ldV, z, numverts); @@ -1174,7 +1170,7 @@ DO_INLINE void dfdx_damp(float to[3][3], float dir[3],float length,const float } -DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) +DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt) { float extent[3]; float length = 0; @@ -1229,19 +1225,23 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, { s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = clmd->sim_parms.structural; + k = (clmd->sim_parms.structural*(length-L)); - mul_fvector_S(stretch_force, dir, (k*(length-L))); + mul_fvector_S(stretch_force, dir, k); VECADD(s->f, s->f, stretch_force); // Ascher & Boxman, p.21: Damping only during elonglation - mul_fvector_S(damping_force, extent, clmd->sim_parms.Cdis * ((INPR(vel,extent)/length))); + mul_fvector_S(damping_force, extent, clmd->sim_parms.Cdis * 0.01 * ((INPR(vel,extent)/length))); VECADD(s->f, s->f, damping_force); - - dfdx_spring_type1(s->dfdx, dir,length,L,k); - - dfdv_damp(s->dfdv, dir,clmd->sim_parms.Cdis); + + // Formula from Ascher / Boxman, Speeding up cloth simulation + if((dt * (k*dt + 2 * clmd->sim_parms.Cdis * 0.01)) > 0.01 ) + { + dfdx_spring_type1(s->dfdx, dir,length,L,clmd->sim_parms.structural); + dfdv_damp(s->dfdv, dir,clmd->sim_parms.Cdis * 0.01); + } + // printf("(dt*k*dt) ): %f, k: %f\n", (dt * (k*dt + 2 * clmd->sim_parms.Cdis * 0.01) ), k); } } else // calculate force of bending springs @@ -1252,17 +1252,19 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = clmd->sim_parms.bending; + k = fbstar(length, L, clmd->sim_parms.bending, cb); - mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); + mul_fvector_S(bending_force, dir, k); VECADD(s->f, s->f, bending_force); - if(INPR(bending_force,bending_force) > 0.13*0.13) + // DG: My formula to handle bending for the AIMEX scheme + // multiply with 1000 because of numerical problems + if( ((k*1000)*dt*dt) < -0.18 ) { + dfdx_spring_type2(s->dfdx, dir,length,L,clmd->sim_parms.bending, cb); clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; } - - dfdx_spring_type2(s->dfdx, dir,length,L,k, cb); + // printf("(dt*k*dt) ): %f, k: %f\n", (dt*dt*k*-1.0), k); } } } @@ -1333,7 +1335,7 @@ DO_INLINE void calc_triangle_force(ClothModifierData *clmd, MFace mface, lfVecto } -void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time) +void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, float dt) { /* Collect forces and derivatives: F,dFdX,dFdV */ Cloth *cloth = clmd->clothObject; @@ -1417,7 +1419,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec { // only handle active springs // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)){} - cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); + cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX, dt); search = search->next; } @@ -1452,13 +1454,13 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec } -void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv) +void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, fmatrix3x3 *P, fmatrix3x3 *Pinv) { unsigned int numverts = dFdV[0].vcount; lfVector *dFdXmV = create_lfvector(numverts); initdiag_bfmatrix(A, I); - zero_lfvector(dV, numverts); + // zero_lfvector(dV, numverts); subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); @@ -1469,17 +1471,16 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto itstart(); cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */ - // cg_filtered_pre(dV, A, B, z, olddV, P, Pinv, dt); + // cg_filtered_pre(dV, A, B, z, dV, P, Pinv, dt); itend(); // printf("cg_filtered calc time: %f\n", (float)itval()); - cp_lfvector(olddV, dV, numverts); + // advance velocities add_lfvector_lfvector(Vnew, lV, dV, numverts); - del_lfvector(dFdXmV); } @@ -1514,12 +1515,12 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase effectors= pdInitEffectors(ob,NULL); // calculate - cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); + cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, dt ); // check for sleeping if(!(clmd->coll_parms.flags & CLOTH_SIMSETTINGS_FLAG_SLEEP)) { - simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->P, id->Pinv); add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); } @@ -1592,8 +1593,8 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase cp_lfvector(id->V, id->Vnew, numverts); // calculate - cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); - simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); + cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, dt); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->P, id->Pinv); } } @@ -1781,7 +1782,7 @@ int collisions_collision_response_moving_edges(ClothModifierData *clmd, ClothMod return 0; } -void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) +void cloth_collision_static(ClothModifierData *clmd, LinkNode *collision_list) { /* CollPair *collpair = NULL; @@ -1794,7 +1795,7 @@ void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clm for(i = 0; i < 4; i++) { - collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); + collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); cloth1 = clmd->clothObject; cloth2 = coll_clmd->clothObject; @@ -1865,8 +1866,7 @@ void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clm else i++; } - - // calc SIPcode (?) + if(i < 4) { @@ -2320,6 +2320,11 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, } } } + /* + // does not compile with OpenMP + if(!collisions) + break; + */ } ////////////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index f39d5465b87..e168d3a9954 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -802,7 +802,9 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio VECCOPY(collpair->point_indexB, tree2->point_index); collpair->point_indexB[3] = tree2->point_index[3]; - BLI_linklist_append(&collision_list[0], collpair); + // we use prepend because lots of insertions at end + // of list are horrible slow! + BLI_linklist_prepend(&collision_list[0], collpair); return 1; } diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index b87a43c30c3..b9e6cd53f8d 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -104,7 +104,7 @@ FILE *PTCache_id_fopen(struct ID *id, char mode, int cfra, int stack_index) if (mode=='r') { if (!BLI_exists(filename)) { - printf("Error, file does not exist '%s'\n", filename); + // printf("Error, file does not exist '%s'\n", filename); return NULL; } fp = fopen(filename, "rb"); diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 70559d29f40..2d5b54ac1c2 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3176,7 +3176,7 @@ static void object_panel_cloth(Object *ob) uiBlockBeginAlign(block); uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility"); - uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=>better=>slower)"); + uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 3.0, 10.0, 5, 0, "Quality of the simulation (higher=>better=>slower)"); uiBlockEndAlign(block); uiBlockBeginAlign(block); uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Spring damping"); From 057060967e07b052c70010b4c6d7d38dd03f6925 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 16 Nov 2007 14:24:43 +0000 Subject: [PATCH 051/101] Fixed DNA issue, some optional SSE stuff in (experimental, only 2 functions => not likely to be ever in trunk), BE AWARE: not compatible with old cloth files, many fixes in general, deactivated selfcollisions due to WIP --- source/blender/blenkernel/BKE_cloth.h | 57 +- source/blender/blenkernel/BKE_collisions.h | 5 + source/blender/blenkernel/intern/cloth.c | 130 ++- source/blender/blenkernel/intern/implicit.c | 933 ++++++++++++------- source/blender/blenkernel/intern/kdop.c | 141 ++- source/blender/blenkernel/intern/modifier.c | 16 +- source/blender/blenloader/intern/readfile.c | 11 +- source/blender/blenloader/intern/writefile.c | 42 +- source/blender/makesdna/DNA_cloth_types.h | 91 +- source/blender/makesdna/DNA_modifier_types.h | 10 +- source/blender/src/buttons_object.c | 96 +- 11 files changed, 910 insertions(+), 622 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 83891cc74d3..f3f566d2832 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -57,6 +57,49 @@ struct DerivedMesh; #define CLOTH_MAX_THREAD 2 +typedef struct ClothVertex { + int flags; /* General flags per vertex. */ + float mass; /* mass / weight of the vertex */ + float goal; /* goal, from SB */ + float impulse[3]; /* used in collision.c */ + unsigned int impulse_count; /* same as above */ +} ClothVertex; + +typedef struct ClothSpring { + int ij; /* Pij from the paper, one end of the spring. */ + int kl; /* Pkl from the paper, one end of the spring. */ + float restlen; /* The original length of the spring. */ + int matrix_index; /* needed for implicit solver (fast lookup) */ + int type; /* types defined in BKE_cloth.h ("springType") */ + int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ + float dfdx[3][4]; + float dfdv[3][4]; + float f[3]; +} ClothSpring; + +typedef struct Cloth { + struct ClothVertex *verts; /* The vertices that represent this cloth. */ + struct LinkNode *springs; /* The springs connecting the mesh. */ + struct BVH *tree; /* collision tree for this cloth object */ + struct BVH *selftree; /* self collision tree for this cloth object */ + struct MFace *mfaces; + struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ + struct EdgeHash *edgehash; /* used for fast checking adjacent points */ + unsigned int numverts; /* The number of verts == m * n. */ + unsigned int numsprings; /* The count of springs. */ + unsigned int numfaces; + unsigned int numothersprings; + unsigned int numspringssave; + unsigned int old_solver_type; + float (*x)[4]; /* The current position of all vertices.*/ + float (*xold)[4]; /* The previous position of all vertices.*/ + float (*current_x)[4]; /* The TEMPORARY current position of all vertices.*/ + float (*current_xold)[4]; /* The TEMPORARY previous position of all vertices.*/ + float (*v)[4]; /* the current velocity of all vertices */ + float (*current_v)[4]; + float (*xconst)[4]; +} Cloth; + /* goal defines */ #define SOFTGOALSNAP 0.999f @@ -138,7 +181,6 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, //////////////////////////////////////////////// void cloth_free_modifier ( ClothModifierData *clmd ); void cloth_init ( ClothModifierData *clmd ); -void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int totface ); //////////////////////////////////////////////// @@ -178,19 +220,6 @@ int verlet_init ( Object *ob, ClothModifierData *clmd ); int verlet_free ( ClothModifierData *clmd ); int verlet_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors ); -/* used for caching in implicit.c */ -typedef struct Frame -{ - ClothVertex *verts; - ClothSpring *springs; - unsigned int numverts, numsprings; - float time; /* we need float since we want to support sub-frames */ - float (*x)[3]; - float (*xold)[3]; - float (*v)[3]; - float (*current_xold)[3]; -} -Frame; /* used for collisions in collision.c */ /* diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h index fa5956c5bec..f358bd629e6 100644 --- a/source/blender/blenkernel/BKE_collisions.h +++ b/source/blender/blenkernel/BKE_collisions.h @@ -73,6 +73,7 @@ typedef struct BVH CollisionTree *leaf_root; /* Head of the leaf linked list. */ float epsilon; /* epslion is used for inflation of the k-dop */ int flags; /* bvhFlags */ + } BVH; @@ -80,6 +81,8 @@ BVH; typedef struct CollisionPair { int point_indexA[4], point_indexB[4]; + float vector[3]; + float pa[3], pb[3]; } CollisionPair; @@ -93,6 +96,7 @@ CollisionPair; // builds bounding volume hierarchy BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon); BVH *bvh_build_from_float3 (MFace *mfaces, unsigned int numfaces, float (*x)[3], unsigned int numverts, float epsilon); +BVH *bvh_build_from_float4 (MFace *mfaces, unsigned int numfaces, float (*x)[4], unsigned int numverts, float epsilon); // frees the same void bvh_free ( BVH *bvh ); @@ -103,6 +107,7 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio // 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_from_float3(BVH * bvh, float (*x)[3], unsigned int numverts, float (*xnew)[3], int moving); +void bvh_update_from_float4(BVH * bvh, float (*x)[4], unsigned int numverts, float (*xnew)[4], int moving); LinkNode *BLI_linklist_append_fast (LinkNode **listp, void *ptr); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 3b065fc16f5..ea3c8dec0c0 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -141,41 +141,39 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v void cloth_init (ClothModifierData *clmd) { /* Initialize our new data structure to reasonable values. */ - clmd->sim_parms.gravity [0] = 0.0; - clmd->sim_parms.gravity [1] = 0.0; - clmd->sim_parms.gravity [2] = -9.81; - clmd->sim_parms.structural = 100.0; - clmd->sim_parms.shear = 100.0; - clmd->sim_parms.bending = 1.0; - clmd->sim_parms.Cdis = 5.0; - clmd->sim_parms.Cvi = 1.0; - clmd->sim_parms.mass = 1.0f; - clmd->sim_parms.stepsPerFrame = 5; - clmd->sim_parms.sim_time = 1.0; - clmd->sim_parms.flags = CLOTH_SIMSETTINGS_FLAG_RESET; - clmd->sim_parms.solver_type = 0; - clmd->sim_parms.preroll = 0; - clmd->sim_parms.maxspringlen = 10; - clmd->coll_parms.self_friction = 5.0; - clmd->coll_parms.friction = 10.0; - clmd->coll_parms.loop_count = 1; - clmd->coll_parms.epsilon = 0.01; - clmd->coll_parms.selfepsilon = 0.1; + clmd->sim_parms->gravity [0] = 0.0; + clmd->sim_parms->gravity [1] = 0.0; + clmd->sim_parms->gravity [2] = -9.81; + clmd->sim_parms->structural = 100.0; + clmd->sim_parms->shear = 100.0; + clmd->sim_parms->bending = 1.0; + clmd->sim_parms->Cdis = 5.0; + clmd->sim_parms->Cvi = 1.0; + clmd->sim_parms->mass = 1.0f; + clmd->sim_parms->stepsPerFrame = 5; + clmd->sim_parms->sim_time = 1.0; + clmd->sim_parms->flags = CLOTH_SIMSETTINGS_FLAG_RESET; + clmd->sim_parms->solver_type = 0; + clmd->sim_parms->preroll = 0; + clmd->sim_parms->maxspringlen = 10; + clmd->coll_parms->self_friction = 5.0; + clmd->coll_parms->friction = 10.0; + clmd->coll_parms->loop_count = 1; + clmd->coll_parms->epsilon = 0.01; + clmd->coll_parms->selfepsilon = 0.1; /* These defaults are copied from softbody.c's * softbody_calc_forces() function. */ - clmd->sim_parms.eff_force_scale = 1000.0; - clmd->sim_parms.eff_wind_scale = 250.0; + clmd->sim_parms->eff_force_scale = 1000.0; + clmd->sim_parms->eff_wind_scale = 250.0; // also from softbodies - clmd->sim_parms.maxgoal = 1.0; - clmd->sim_parms.mingoal = 0.0; - clmd->sim_parms.defgoal = 0.0; - clmd->sim_parms.goalspring = 100.0; - clmd->sim_parms.goalfrict = 0.0; - - clmd->sim_parms.cache = NULL; + clmd->sim_parms->maxgoal = 1.0; + clmd->sim_parms->mingoal = 0.0; + clmd->sim_parms->defgoal = 0.0; + clmd->sim_parms->goalspring = 100.0; + clmd->sim_parms->goalfrict = 0.0; } // unused in the moment, cloth needs quads from mesh @@ -410,7 +408,7 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) { int stack_index = -1; - if(!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) + if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) { stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); @@ -434,9 +432,9 @@ static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr for(a = 0; a < cloth->numverts; a++) { - fwrite(&cloth->x[a], sizeof(float),3,fp); - fwrite(&cloth->xconst[a], sizeof(float),3,fp); - fwrite(&cloth->v[a], sizeof(float),3,fp); + fwrite(&cloth->x[a], sizeof(float),4,fp); + fwrite(&cloth->xconst[a], sizeof(float),4,fp); + fwrite(&cloth->v[a], sizeof(float),4,fp); } fclose(fp); @@ -459,17 +457,17 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) else { for(a = 0; a < cloth->numverts; a++) { - if(fread(&cloth->x[a], sizeof(float), 3, fp) != 3) + if(fread(&cloth->x[a], sizeof(float), 4, fp) != 4) { ret = 0; break; } - if(fread(&cloth->xconst[a], sizeof(float), 3, fp) != 3) + if(fread(&cloth->xconst[a], sizeof(float), 4, fp) != 4) { ret = 0; break; } - if(fread(&cloth->v[a], sizeof(float), 3, fp) != 3) + if(fread(&cloth->v[a], sizeof(float), 4, fp) != 4) { ret = 0; break; @@ -501,9 +499,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d unsigned int framenr = (float)G.scene->r.cfra; float current_time = bsystem_time(ob, (float)G.scene->r.cfra, 0.0); ListBase *effectors = NULL; - float deltaTime = current_time - clmd->sim_parms.sim_time; + float deltaTime = current_time - clmd->sim_parms->sim_time; - clmd->sim_parms.dt = 1.0f / (clmd->sim_parms.stepsPerFrame * G.scene->r.frs_sec); + clmd->sim_parms->dt = 1.0f / (clmd->sim_parms->stepsPerFrame * G.scene->r.frs_sec); result = CDDM_copy(dm); @@ -519,9 +517,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d medge = CDDM_get_edges(result); mface = CDDM_get_faces(result); - clmd->sim_parms.sim_time = current_time; + clmd->sim_parms->sim_time = current_time; - if ( current_time < clmd->sim_parms.firstframe ) + if ( current_time < clmd->sim_parms->firstframe ) return result; // only be active during a specific period: @@ -529,9 +527,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d /* if ( clmd->clothObject ) { - if ( clmd->sim_parms.cache ) + if ( clmd->sim_parms->cache ) { - if ( current_time < clmd->sim_parms.firstframe ) + if ( current_time < clmd->sim_parms->firstframe ) { int frametime = cloth_cache_first_frame ( clmd ); if ( cloth_cache_search_frame ( clmd, frametime ) ) @@ -541,7 +539,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d } return result; } - else if ( current_time > clmd->sim_parms.lastframe ) + else if ( current_time > clmd->sim_parms->lastframe ) { int frametime = cloth_cache_last_frame ( clmd ); if ( cloth_cache_search_frame ( clmd, frametime ) ) @@ -558,7 +556,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d cloth_cache_get_frame ( clmd, framenr ); cloth_to_object ( ob, result, clmd ); } - clmd->sim_parms.sim_time = current_time; + clmd->sim_parms->sim_time = current_time; return result; } } @@ -578,7 +576,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d cloth = clmd->clothObject; } - clmd->clothObject->old_solver_type = clmd->sim_parms.solver_type; + clmd->clothObject->old_solver_type = clmd->sim_parms->solver_type; // Insure we have a clmd->clothObject, in case allocation failed. if (clmd->clothObject != NULL) @@ -600,8 +598,8 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d tstart(); /* Call the solver. */ - if (solvers [clmd->sim_parms.solver_type].solver) - solvers [clmd->sim_parms.solver_type].solver (ob, framenr, clmd, effectors); + if (solvers [clmd->sim_parms->solver_type].solver) + solvers [clmd->sim_parms->solver_type].solver (ob, framenr, clmd, effectors); tend(); @@ -614,7 +612,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d cloth_to_object (ob, result, clmd); // bvh_free(clmd->clothObject->tree); - // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); + // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms->epsilon); } } @@ -793,7 +791,7 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v for ( i = 0; i < numverts; i++, verts++ ) { // LATER ON, support also mass painting here - if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) { dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT ); if ( dvert ) @@ -804,7 +802,7 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v { verts->goal = dvert->dw [j].weight; - goalfac= ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal ); + goalfac= ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); verts->goal = ( float ) pow ( verts->goal , 4.0f ); if ( dvert->dw [j].weight >=SOFTGOALSNAP ) @@ -875,9 +873,9 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d VECCOPY (clmd->clothObject->x[i], mvert[i].co); Mat4MulVecfl(ob->obmat, clmd->clothObject->x[i]); - clmd->clothObject->verts [i].mass = clmd->sim_parms.mass; - if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - clmd->clothObject->verts [i].goal= clmd->sim_parms.defgoal; + clmd->clothObject->verts [i].mass = clmd->sim_parms->mass; + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + clmd->clothObject->verts [i].goal= clmd->sim_parms->defgoal; else clmd->clothObject->verts [i].goal= 0.0; clmd->clothObject->verts [i].flags = 0; @@ -891,16 +889,16 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d } /* apply / set vertex groups */ - if (clmd->sim_parms.vgroup_mass > 0) - cloth_apply_vgroup (clmd, olddm, clmd->sim_parms.vgroup_mass); + if (clmd->sim_parms->vgroup_mass > 0) + cloth_apply_vgroup (clmd, olddm, clmd->sim_parms->vgroup_mass); /* init our solver */ - if (solvers [clmd->sim_parms.solver_type].init) - solvers [clmd->sim_parms.solver_type].init (ob, clmd); + if (solvers [clmd->sim_parms->solver_type].init) + solvers [clmd->sim_parms->solver_type].init (ob, clmd); - clmd->clothObject->tree = bvh_build_from_float3(CDDM_get_faces(dm), dm->getNumFaces(dm), clmd->clothObject->x, numverts, clmd->coll_parms.epsilon); + clmd->clothObject->tree = bvh_build_from_float4(CDDM_get_faces(dm), dm->getNumFaces(dm), clmd->clothObject->x, numverts, clmd->coll_parms->epsilon); - clmd->clothObject->selftree = bvh_build_from_float3(NULL, 0, clmd->clothObject->x, numverts, clmd->coll_parms.selfepsilon); + clmd->clothObject->selftree = bvh_build_from_float4(NULL, 0, clmd->clothObject->x, numverts, clmd->coll_parms->selfepsilon); // save initial state cloth_write_cache(ob, clmd, framenr-1); @@ -930,7 +928,7 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - clmd->clothObject->x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_x" ); + clmd->clothObject->x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_x" ); if ( clmd->clothObject->x == NULL ) { cloth_free_modifier ( clmd ); @@ -938,7 +936,7 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - clmd->clothObject->xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_xold" ); + clmd->clothObject->xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_xold" ); if ( clmd->clothObject->xold == NULL ) { cloth_free_modifier ( clmd ); @@ -946,7 +944,7 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - clmd->clothObject->v = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_v" ); + clmd->clothObject->v = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_v" ); if ( clmd->clothObject->v == NULL ) { cloth_free_modifier ( clmd ); @@ -954,7 +952,7 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - clmd->clothObject->current_x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_current_x" ); + clmd->clothObject->current_x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_current_x" ); if ( clmd->clothObject->current_x == NULL ) { cloth_free_modifier ( clmd ); @@ -962,7 +960,7 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - clmd->clothObject->current_xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_current_xold" ); + clmd->clothObject->current_xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_current_xold" ); if ( clmd->clothObject->current_xold == NULL ) { cloth_free_modifier ( clmd ); @@ -970,7 +968,7 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - clmd->clothObject->current_v = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_current_v" ); + clmd->clothObject->current_v = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_current_v" ); if ( clmd->clothObject->current_v == NULL ) { cloth_free_modifier ( clmd ); @@ -978,7 +976,7 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d return; } - clmd->clothObject->xconst = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 3, "Cloth MVert_xconst" ); + clmd->clothObject->xconst = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_xconst" ); if ( clmd->clothObject->xconst == NULL ) { cloth_free_modifier ( clmd ); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index ee8a440735a..c457064065c 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -63,6 +63,12 @@ #include "BKE_global.h" #include "BIF_editdeform.h" +#include "Bullet-C-Api.h" + +#include +#include +#include + #ifdef _WIN32 #include static LARGE_INTEGER _itstart, _itend; @@ -114,20 +120,39 @@ struct Cloth; ///////////////////////////////////////// /* DEFINITIONS */ -typedef float lfVector[3]; +#ifdef __GNUC__ +typedef float lfVector[4] __attribute__ ((aligned (16))); +#else +typedef __declspec(align(16)) lfVector[4]; +#endif + +#ifdef __GNUC__ typedef struct fmatrix3x3 { - float m[3][3]; /* 4x4 matrix */ + float m[3][4] __attribute__ ((aligned (16))); /* 3x3 matrix */ unsigned int c,r; /* column and row number */ int pinned; /* is this vertex allowed to move? */ float n1,n2,n3; /* three normal vectors for collision constrains */ unsigned int vcount; /* vertex count */ unsigned int scount; /* spring count */ } fmatrix3x3; +#else +typedef struct fmatrix3x3 { + __declspec(align(16)) + float m[3][4]; /* 3x3 matrix */ + unsigned int c,r; /* column and row number */ + int pinned; /* is this vertex allowed to move? */ + float n1,n2,n3; /* three normal vectors for collision constrains */ + unsigned int vcount; /* vertex count */ + unsigned int scount; /* spring count */ +} fmatrix3x3; +#endif + /////////////////////////// // float[3] vector /////////////////////////// /* simple vector code */ + /* STATUS: verified */ DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar) { @@ -139,13 +164,18 @@ DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar) /* STATUS: verified */ DO_INLINE void cross_fvector(float to[3], float vectorA[3], float vectorB[3]) { - to[0] = vectorA[1] * vectorB[2] - vectorA[2] * vectorB[1]; - to[1] = vectorA[2] * vectorB[0] - vectorA[0] * vectorB[2]; - to[2] = vectorA[0] * vectorB[1] - vectorA[1] * vectorB[0]; + float temp[3]; + + temp[0] = vectorA[1] * vectorB[2] - vectorA[2] * vectorB[1]; + temp[1] = vectorA[2] * vectorB[0] - vectorA[0] * vectorB[2]; + temp[2] = vectorA[0] * vectorB[1] - vectorA[1] * vectorB[0]; + + VECCOPY(to, temp); } + /* simple v^T * v product ("outer product") */ /* STATUS: HAS TO BE verified (*should* work) */ -DO_INLINE void mul_fvectorT_fvector(float to[3][3], float vectorA[3], float vectorB[3]) +DO_INLINE void mul_fvectorT_fvector(float to[3][4], float vectorA[3], float vectorB[3]) { mul_fvector_S(to[0], vectorB, vectorA[0]); mul_fvector_S(to[1], vectorB, vectorA[1]); @@ -153,7 +183,7 @@ DO_INLINE void mul_fvectorT_fvector(float to[3][3], float vectorA[3], float vect } /* simple v^T * v product with scalar ("outer product") */ /* STATUS: HAS TO BE verified (*should* work) */ -DO_INLINE void mul_fvectorT_fvectorS(float to[3][3], float vectorA[3], float vectorB[3], float aS) +DO_INLINE void mul_fvectorT_fvectorS(float to[3][4], float vectorA[3], float vectorB[3], float aS) { mul_fvector_S(to[0], vectorB, vectorA[0]* aS); mul_fvector_S(to[1], vectorB, vectorA[1]* aS); @@ -170,7 +200,7 @@ void print_fvector(float m3[3]) // long float vector float (*)[3] /////////////////////////// /* print long vector on console: for debug output */ -DO_INLINE void print_lfvector(float (*fLongVector)[3], unsigned int verts) +DO_INLINE void print_lfvector(lfVector *fLongVector, unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -186,7 +216,7 @@ DO_INLINE lfVector *create_lfvector(unsigned int verts) // return (lfVector *)cloth_aligned_malloc(&MEMORY_BASE, verts * sizeof(lfVector)); } /* delete long vector */ -DO_INLINE void del_lfvector(float (*fLongVector)[3]) +DO_INLINE void del_lfvector(lfVector *fLongVector) { if (fLongVector != NULL) { @@ -195,12 +225,12 @@ DO_INLINE void del_lfvector(float (*fLongVector)[3]) } } /* copy long vector */ -DO_INLINE void cp_lfvector(float (*to)[3], float (*from)[3], unsigned int verts) +DO_INLINE void cp_lfvector(lfVector *to, lfVector *from, unsigned int verts) { memcpy(to, from, verts * sizeof(lfVector)); } /* init long vector with float[3] */ -DO_INLINE void init_lfvector(float (*fLongVector)[3], float vector[3], unsigned int verts) +DO_INLINE void init_lfvector(lfVector *fLongVector, float vector[3], unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -209,12 +239,12 @@ DO_INLINE void init_lfvector(float (*fLongVector)[3], float vector[3], unsigned } } /* zero long vector with float[3] */ -DO_INLINE void zero_lfvector(float (*to)[3], unsigned int verts) +DO_INLINE void zero_lfvector(lfVector *to, unsigned int verts) { memset(to, 0.0f, verts * sizeof(lfVector)); } /* multiply long vector with scalar*/ -DO_INLINE void mul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts) +DO_INLINE void mul_lfvectorS(lfVector *to, lfVector *fLongVector, float scalar, unsigned int verts) { unsigned int i = 0; @@ -225,7 +255,7 @@ DO_INLINE void mul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scal } /* multiply long vector with scalar*/ /* A -= B * float */ -DO_INLINE void submul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts) +DO_INLINE void submul_lfvectorS(lfVector *to, lfVector *fLongVector, float scalar, unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -234,12 +264,12 @@ DO_INLINE void submul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float s } } /* dot product for big vector */ -DO_INLINE float dot_lfvector(float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) +DO_INLINE float dot_lfvector(lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) { unsigned int i = 0; float temp = 0.0; // schedule(guided, 2) -#pragma omp parallel for reduction(+: temp) +#pragma omp parallel for reduction(+: temp) schedule(static) for(i = 0; i < verts; i++) { temp += INPR(fLongVectorA[i], fLongVectorB[i]); @@ -247,7 +277,7 @@ DO_INLINE float dot_lfvector(float (*fLongVectorA)[3], float (*fLongVectorB)[3], return temp; } /* A = B + C --> for big vector */ -DO_INLINE void add_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) +DO_INLINE void add_lfvector_lfvector(lfVector *to, lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) { unsigned int i = 0; @@ -258,7 +288,7 @@ DO_INLINE void add_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], f } /* A = B + C * float --> for big vector */ -DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts) +DO_INLINE void add_lfvector_lfvectorS(lfVector *to, lfVector *fLongVectorA, lfVector *fLongVectorB, float bS, unsigned int verts) { unsigned int i = 0; @@ -269,7 +299,7 @@ DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], } } /* A = B * float + C * float --> for big vector */ -DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float aS, float (*fLongVectorB)[3], float bS, unsigned int verts) +DO_INLINE void add_lfvectorS_lfvectorS(lfVector *to, lfVector *fLongVectorA, float aS, lfVector *fLongVectorB, float bS, unsigned int verts) { unsigned int i = 0; @@ -279,7 +309,7 @@ DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], } } /* A = B - C * float --> for big vector */ -DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts) +DO_INLINE void sub_lfvector_lfvectorS(lfVector *to, lfVector *fLongVectorA, lfVector *fLongVectorB, float bS, unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -289,7 +319,7 @@ DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], } /* A = B - C --> for big vector */ -DO_INLINE void sub_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) +DO_INLINE void sub_lfvector_lfvector(lfVector *to, lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) { unsigned int i = 0; @@ -300,30 +330,32 @@ DO_INLINE void sub_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], f } /////////////////////////// -// 4x4 matrix +// 3x3 matrix /////////////////////////// -/* printf 4x4 matrix on console: for debug output */ -void print_fmatrix(float m3[3][3]) +/* printf 3x3 matrix on console: for debug output */ +void print_fmatrix(float m3[3][4]) { printf("%f\t%f\t%f\n",m3[0][0],m3[0][1],m3[0][2]); printf("%f\t%f\t%f\n",m3[1][0],m3[1][1],m3[1][2]); printf("%f\t%f\t%f\n\n",m3[2][0],m3[2][1],m3[2][2]); } -/* copy 4x4 matrix */ -DO_INLINE void cp_fmatrix(float to[3][3], float from[3][3]) +/* copy 3x3 matrix */ +DO_INLINE void cp_fmatrix(float to[3][4], float from[3][4]) { - // memcpy(to, from, sizeof (float) * 9); + memcpy(to, from, sizeof (float) * 12); + /* VECCOPY(to[0], from[0]); VECCOPY(to[1], from[1]); VECCOPY(to[2], from[2]); + */ } -/* calculate determinant of 4x4 matrix */ -DO_INLINE float det_fmatrix(float m[3][3]) +/* calculate determinant of 3x3 matrix */ +DO_INLINE float det_fmatrix(float m[3][4]) { return m[0][0]*m[1][1]*m[2][2] + m[1][0]*m[2][1]*m[0][2] + m[0][1]*m[1][2]*m[2][0] -m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2]; } -DO_INLINE void inverse_fmatrix(float to[3][3], float from[3][3]) +DO_INLINE void inverse_fmatrix(float to[3][4], float from[3][4]) { unsigned int i, j; float d; @@ -354,84 +386,110 @@ DO_INLINE void inverse_fmatrix(float to[3][3], float from[3][3]) } -/* 4x4 matrix multiplied by a scalar */ +/* 3x3 matrix multiplied by a scalar */ /* STATUS: verified */ -DO_INLINE void mul_fmatrix_S(float matrix[3][3], float scalar) +DO_INLINE void mul_fmatrix_S(float matrix[3][4], float scalar) { mul_fvector_S(matrix[0], matrix[0],scalar); mul_fvector_S(matrix[1], matrix[1],scalar); mul_fvector_S(matrix[2], matrix[2],scalar); } -/* a vector multiplied by a 4x4 matrix */ +/* a vector multiplied by a 3x3 matrix */ /* STATUS: verified */ -DO_INLINE void mul_fvector_fmatrix(float *to, float *from, float matrix[3][3]) +DO_INLINE void mul_fvector_fmatrix(float *to, float *from, float matrix[3][4]) { - to[0] = matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2]; - to[1] = matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2]; - to[2] = matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2]; + float temp[3]; + + VECCOPY(temp, from); + + to[0] = matrix[0][0]*temp[0] + matrix[1][0]*temp[1] + matrix[2][0]*temp[2]; + to[1] = matrix[0][1]*temp[0] + matrix[1][1]*temp[1] + matrix[2][1]*temp[2]; + to[2] = matrix[0][2]*temp[0] + matrix[1][2]*temp[1] + matrix[2][2]*temp[2]; } -/* 4x4 matrix multiplied by a vector */ +/* 3x3 matrix multiplied by a vector */ /* STATUS: verified */ -DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][3], float *from) +#ifdef SSE3 +DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][4], float *from) { + __m128 v1, v2, v3, v4; + + v1 = _mm_load_ps(&matrix[0]); + v2 = _mm_load_ps(&matrix[1]); + v3 = _mm_load_ps(&matrix[2]); + v4 = _mm_load_ps(from); + + // stuff + v1 = _mm_mul_ps(v1, v4); + v2 = _mm_mul_ps(v2, v4); + v3 = _mm_mul_ps(v3, v4); + v1 = _mm_hadd_ps(v1, v2); + v3 = _mm_hadd_ps(v3, _mm_setzero_ps()); + v1 = _mm_hadd_ps(v1, v3); + + _mm_store_ps(to, v4); +} +#else +DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][4], float *from) { to[0] = INPR(matrix[0],from); to[1] = INPR(matrix[1],from); to[2] = INPR(matrix[2],from); } -/* 4x4 matrix multiplied by a 4x4 matrix */ +#endif + +/* 3x3 matrix multiplied by a 3x3 matrix */ /* STATUS: verified */ -DO_INLINE void mul_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +DO_INLINE void mul_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) { mul_fvector_fmatrix(to[0], matrixA[0],matrixB); mul_fvector_fmatrix(to[1], matrixA[1],matrixB); mul_fvector_fmatrix(to[2], matrixA[2],matrixB); } -/* 4x4 matrix addition with 4x4 matrix */ -DO_INLINE void add_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +/* 3x3 matrix addition with 3x3 matrix */ +DO_INLINE void add_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) { VECADD(to[0], matrixA[0], matrixB[0]); VECADD(to[1], matrixA[1], matrixB[1]); VECADD(to[2], matrixA[2], matrixB[2]); } -/* 4x4 matrix add-addition with 4x4 matrix */ -DO_INLINE void addadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +/* 3x3 matrix add-addition with 3x3 matrix */ +DO_INLINE void addadd_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) { VECADDADD(to[0], matrixA[0], matrixB[0]); VECADDADD(to[1], matrixA[1], matrixB[1]); VECADDADD(to[2], matrixA[2], matrixB[2]); } -/* 4x4 matrix sub-addition with 4x4 matrix */ -DO_INLINE void addsub_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS) +/* 3x3 matrix sub-addition with 3x3 matrix */ +DO_INLINE void addsub_fmatrixS_fmatrixS(float to[3][4], float matrixA[3][4], float aS, float matrixB[3][4], float bS) { VECADDSUBSS(to[0], matrixA[0], aS, matrixB[0], bS); VECADDSUBSS(to[1], matrixA[1], aS, matrixB[1], bS); VECADDSUBSS(to[2], matrixA[2], aS, matrixB[2], bS); } -/* A -= B + C (4x4 matrix sub-addition with 4x4 matrix) */ -DO_INLINE void subadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +/* A -= B + C (3x3 matrix sub-addition with 3x3 matrix) */ +DO_INLINE void subadd_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) { VECSUBADD(to[0], matrixA[0], matrixB[0]); VECSUBADD(to[1], matrixA[1], matrixB[1]); VECSUBADD(to[2], matrixA[2], matrixB[2]); } -/* A -= B*x + C*y (4x4 matrix sub-addition with 4x4 matrix) */ -DO_INLINE void subadd_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS) +/* A -= B*x + C*y (3x3 matrix sub-addition with 3x3 matrix) */ +DO_INLINE void subadd_fmatrixS_fmatrixS(float to[3][4], float matrixA[3][4], float aS, float matrixB[3][4], float bS) { VECSUBADDSS(to[0], matrixA[0], aS, matrixB[0], bS); VECSUBADDSS(to[1], matrixA[1], aS, matrixB[1], bS); VECSUBADDSS(to[2], matrixA[2], aS, matrixB[2], bS); } -/* A = B - C (4x4 matrix subtraction with 4x4 matrix) */ -DO_INLINE void sub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +/* A = B - C (3x3 matrix subtraction with 3x3 matrix) */ +DO_INLINE void sub_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) { VECSUB(to[0], matrixA[0], matrixB[0]); VECSUB(to[1], matrixA[1], matrixB[1]); VECSUB(to[2], matrixA[2], matrixB[2]); } -/* A += B - C (4x4 matrix add-subtraction with 4x4 matrix) */ -DO_INLINE void addsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) +/* A += B - C (3x3 matrix add-subtraction with 3x3 matrix) */ +DO_INLINE void addsub_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) { VECADDSUB(to[0], matrixA[0], matrixB[0]); VECADDSUB(to[1], matrixA[1], matrixB[1]); @@ -440,53 +498,93 @@ DO_INLINE void addsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float ///////////////////////////////////////////////////////////////// // special functions ///////////////////////////////////////////////////////////////// -/* a vector multiplied and added to/by a 4x4 matrix */ +/* a vector multiplied and added to/by a 3x3 matrix */ +/* DO_INLINE void muladd_fvector_fmatrix(float to[3], float from[3], float matrix[3][3]) { to[0] += matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2]; to[1] += matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2]; to[2] += matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2]; } -/* 4x4 matrix multiplied and added to/by a 4x4 matrix and added to another 4x4 matrix */ +*/ +/* 3x3 matrix multiplied and added to/by a 3x3 matrix and added to another 3x3 matrix */ +/* DO_INLINE void muladd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) { muladd_fvector_fmatrix(to[0], matrixA[0],matrixB); muladd_fvector_fmatrix(to[1], matrixA[1],matrixB); muladd_fvector_fmatrix(to[2], matrixA[2],matrixB); } -/* a vector multiplied and sub'd to/by a 4x4 matrix */ +*/ +/* a vector multiplied and sub'd to/by a 3x3 matrix */ +/* DO_INLINE void mulsub_fvector_fmatrix(float to[3], float from[3], float matrix[3][3]) { to[0] -= matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2]; to[1] -= matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2]; to[2] -= matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2]; } -/* 4x4 matrix multiplied and sub'd to/by a 4x4 matrix and added to another 4x4 matrix */ +*/ +/* 3x3 matrix multiplied and sub'd to/by a 3x3 matrix and added to another 3x3 matrix */ +/* DO_INLINE void mulsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) { mulsub_fvector_fmatrix(to[0], matrixA[0],matrixB); mulsub_fvector_fmatrix(to[1], matrixA[1],matrixB); mulsub_fvector_fmatrix(to[2], matrixA[2],matrixB); } -/* 4x4 matrix multiplied+added by a vector */ +*/ +/* 3x3 matrix multiplied+added by a vector */ /* STATUS: verified */ -DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][3], float from[3]) -{ - to[0] += INPR(matrix[0],from); - to[1] += INPR(matrix[1],from); - to[2] += INPR(matrix[2],from); + +#ifdef SSE3 +DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][4], float from[3]) { + __m128 v1, v2, v3, v4; + + v1 = _mm_load_ps(&matrix[0]); + v2 = _mm_load_ps(&matrix[1]); + v3 = _mm_load_ps(&matrix[2]); + v4 = _mm_load_ps(from); + + // stuff + v1 = _mm_mul_ps(v1, v4); + v2 = _mm_mul_ps(v2, v4); + v3 = _mm_mul_ps(v3, v4); + v1 = _mm_hadd_ps(v1, v2); + v3 = _mm_hadd_ps(v3, _mm_setzero_ps()); + v1 = _mm_hadd_ps(v1, v3); + + v4 = _mm_load_ps(to); + v4 = _mm_add_ps(v4,v1); + + _mm_store_ps(to, v4); } -/* 4x4 matrix multiplied+sub'ed by a vector */ +#else +DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][4], float from[3]) +{ + float temp[3] = { 0,0,0 }; + + temp[0] = INPR(matrix[0],from); + temp[1] = INPR(matrix[1],from); + temp[2] = INPR(matrix[2],from); + + VECADD(to, to, temp); +} +#endif + +/* 3x3 matrix multiplied+sub'ed by a vector */ +/* DO_INLINE void mulsub_fmatrix_fvector(float to[3], float matrix[3][3], float from[3]) { to[0] -= INPR(matrix[0],from); to[1] -= INPR(matrix[1],from); to[2] -= INPR(matrix[2],from); } +*/ ///////////////////////////////////////////////////////////////// /////////////////////////// -// SPARSE SYMMETRIC big matrix with 4x4 matrix entries +// SPARSE SYMMETRIC big matrix with 3x3 matrix entries /////////////////////////// /* printf a big matrix on console: for debug output */ void print_bfmatrix(fmatrix3x3 *m3) @@ -523,10 +621,10 @@ DO_INLINE void cp_bfmatrix(fmatrix3x3 *to, fmatrix3x3 *from) } /* init the diagonal of big matrix */ // slow in parallel -DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][3]) +DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][4]) { unsigned int i,j; - float tmatrix[3][3] = {{0,0,0},{0,0,0},{0,0,0}}; + float tmatrix[3][4] = {{0,0,0,0},{0,0,0,0},{0,0,0,0}}; for(i = 0; i < matrix[0].vcount; i++) { @@ -538,7 +636,7 @@ DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][3]) } } /* init big matrix */ -DO_INLINE void init_bfmatrix(fmatrix3x3 *matrix, float m3[3][3]) +DO_INLINE void init_bfmatrix(fmatrix3x3 *matrix, float m3[3][4]) { unsigned int i; @@ -558,45 +656,31 @@ DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) } /* SPARSE SYMMETRIC multiply big matrix with long vector*/ /* STATUS: verified */ -DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (*fLongVector)[3]) +void mul_bfmatrix_lfvector( lfVector *to, fmatrix3x3 *from, lfVector *fLongVector) { unsigned int i = 0; + float *tflongvector; + float temp[4]={0,0,0,0}; + zero_lfvector(to, from[0].vcount); + /* process diagonal elements */ for(i = 0; i < from[0].vcount; i++) { - muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); + mul_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); } /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */ // TODO: pragma below is wrong, correct it! // #pragma omp parallel for shared(to,from, fLongVector) private(i) + for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) { - unsigned int row = from[i].r; - unsigned int column = from[i].c; - - // muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); - - to[column][0] += INPR(from[i].m[0],fLongVector[row]); - to[column][1] += INPR(from[i].m[1],fLongVector[row]); - to[column][2] += INPR(from[i].m[2],fLongVector[row]); + muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); + muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); } -// #pragma omp parallel for shared(to,from, fLongVector) private(i) - for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) - { - unsigned int row = from[i].r; - unsigned int column = from[i].c; - - // muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); - - to[row][0] += INPR(from[i].m[0],fLongVector[column]); - to[row][1] += INPR(from[i].m[1],fLongVector[column]); - to[row][2] += INPR(from[i].m[2],fLongVector[column]); - } - - } + /* SPARSE SYMMETRIC add big matrix with big matrix: A = B + C*/ DO_INLINE void add_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) { @@ -687,8 +771,8 @@ DO_INLINE void subadd_bfmatrixS_bfmatrixS( fmatrix3x3 *to, fmatrix3x3 *from, flo /////////////////////////////////////////////////////////////////// // simulator start /////////////////////////////////////////////////////////////////// -static float I[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; -static float ZERO[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}; +static float I[3][4] = {{1,0,0,0},{0,1,0,0},{0,0,1,0}}; +static float ZERO[3][4] = {{0,0,0,0},{0,0,0,0},{0,0,0,0}}; typedef struct Implicit_Data { lfVector *X, *V, *Xnew, *Vnew, *F, *B, *dV, *z; @@ -885,31 +969,6 @@ DO_INLINE void filter(lfVector *V, fmatrix3x3 *S) } } -// block diagonalizer -void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *S, fmatrix3x3 *bigI) -{ - unsigned int i=0; - - // Take only the diagonal blocks of A - for(i=0;istarget && conjgrad_loopcount < conjgrad_looplimit)) { // Mul(q,A,d); // q = A*d; @@ -963,172 +1022,242 @@ int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatr conjgrad_loopcount++; } + // itend(); + // printf("cg_filtered time: %f\n", (float)itval()); + conjgrad_lasterror = s; del_lfvector(q); del_lfvector(d); del_lfvector(tmp); del_lfvector(r); + // printf("W/O conjgrad_loopcount: %d\n", conjgrad_loopcount); return conjgrad_loopcount(epsilon_sqr*delta0))&& (conjgrad_loopcount++ < conjgrad_looplimit)) -{ -////////////////////////// -// (s) = q = S*A*c -////////////////////////// -// q = A*c; -mul_bfmatrix_lfvector(q, lA, c); -filter(q,S); -////////////////////////// - -////////////////////////// -// alpha = deltanew / (c^T * q) -////////////////////////// -alpha = deltanew/dot_lfvector(c, q, numverts); -////////////////////////// - -//X = X + c*alpha; -add_lfvector_lfvectorS(ldV, ldV, c, alpha, numverts); -//r = r - q*alpha; -sub_lfvector_lfvectorS(r, r, q, alpha, numverts); - -////////////////////////// -// (h) = s = P^-1 * r -////////////////////////// -// s = Pinv * r; -mul_bfmatrix_lfvector(s, Pinv, r); -filter(s,S); -////////////////////////// - -deltaold = deltanew; - -// deltanew = dot(r,s); -deltanew = dot_lfvector(r, s, numverts); - -////////////////////////// -// c = S * (s + (deltanew/deltaold)*c) -////////////////////////// -// c = s + c * (deltanew/deltaold); -add_lfvector_lfvectorS(c, s, c, (deltanew/deltaold), numverts); -filter(c,S); -////////////////////////// - + unsigned int i = 0; + + // Take only the diagonal blocks of A +// #pragma omp parallel for private(i) + for(i = 0; i (conjgrad_epsilon*conjgrad_epsilon*delta0)) && (iterations < conjgrad_looplimit)); + + del_lfvector(s); + del_lfvector(q); + del_lfvector(c); + del_lfvector(r); + del_lfvector(p_fb); + del_lfvector(filterb); + + printf("iterations: %d\n", iterations); + + return iterations (conjgrad_epsilon*conjgrad_epsilon*delta0)) && (iterations < conjgrad_looplimit)) + { + iterations++; + + mul_bfmatrix_lfvector(s, lA, p); + filter(s, S); + + alpha = deltaNew / dot_lfvector(p, s, numverts); + + add_lfvector_lfvectorS(dv, dv, p, alpha, numverts); + + add_lfvector_lfvectorS(r, r, s, -alpha, numverts); + + mul_bfmatrix_lfvector(h, Pinv, r); + + + deltaOld = deltaNew; + + deltaNew = dot_lfvector(r, h, numverts); + + add_lfvector_lfvectorS(p, h, p, deltaNew / deltaOld, numverts); + filter(p, S); + + } + + del_lfvector(h); + del_lfvector(s); + del_lfvector(p); + del_lfvector(r); + + printf("iterations: %d\n", iterations); + + return iterations (conjgrad_epsilon*delta0)) && (iterations < conjgrad_looplimit)) + { + iterations++; + + mul_bfmatrix_lfvector(s, lA, p); + filter(s, S); + + alpha = deltaNew / dot_lfvector(p, s, numverts); + + add_lfvector_lfvectorS(dv, dv, p, alpha, numverts); + + sub_lfvector_lfvectorS(r, r, s, alpha, numverts); + + mul_bfmatrix_lfvector(h, Pinv, r); + filter(h, S); + + deltaOld = deltaNew; + + deltaNew = dot_lfvector(r, h, numverts); + + add_lfvector_lfvectorS(p, h, p, deltaNew / deltaOld, numverts); + filter(p, S); + + } + + // itend(); + // printf("cg_filtered_pre time: %f\n", (float)itval()); + + del_lfvector(h); + del_lfvector(s); + del_lfvector(p); + del_lfvector(r); + + // printf("iterations: %d\n", iterations); + + return iterationsrestlen; - float cb = clmd->sim_parms.structural; + float cb = clmd->sim_parms->structural; float nullf[3] = {0,0,0}; float stretch_force[3] = {0,0,0}; float bending_force[3] = {0,0,0}; float damping_force[3] = {0,0,0}; - float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; + float nulldfdx[3][4]={ {0,0,0,0}, {0,0,0,0}, {0,0,0,0}}; VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); @@ -1202,8 +1331,8 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, /* if(length>L) { - if((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) - && ((((length-L)*100.0f/L) > clmd->sim_parms.maxspringlen))) // cut spring! + if((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) + && ((((length-L)*100.0f/L) > clmd->sim_parms->maxspringlen))) // cut spring! { s->flags |= CSPRING_FLAG_DEACTIVATE; return; @@ -1225,44 +1354,44 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, { s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = (clmd->sim_parms.structural*(length-L)); + k = (clmd->sim_parms->structural*(length-L)); mul_fvector_S(stretch_force, dir, k); VECADD(s->f, s->f, stretch_force); // Ascher & Boxman, p.21: Damping only during elonglation - mul_fvector_S(damping_force, extent, clmd->sim_parms.Cdis * 0.01 * ((INPR(vel,extent)/length))); + mul_fvector_S(damping_force, extent, clmd->sim_parms->Cdis * 0.01 * ((INPR(vel,extent)/length))); VECADD(s->f, s->f, damping_force); // Formula from Ascher / Boxman, Speeding up cloth simulation - if((dt * (k*dt + 2 * clmd->sim_parms.Cdis * 0.01)) > 0.01 ) + // if((dt * (k*dt + 2 * clmd->sim_parms->Cdis * 0.01)) > 0.01 ) { - dfdx_spring_type1(s->dfdx, dir,length,L,clmd->sim_parms.structural); - dfdv_damp(s->dfdv, dir,clmd->sim_parms.Cdis * 0.01); + dfdx_spring_type1(s->dfdx, dir,length,L,clmd->sim_parms->structural); + dfdv_damp(s->dfdv, dir,clmd->sim_parms->Cdis * 0.01); } - // printf("(dt*k*dt) ): %f, k: %f\n", (dt * (k*dt + 2 * clmd->sim_parms.Cdis * 0.01) ), k); + // printf("(dt*k*dt) ): %f, k: %f\n", (dt * (k*dt + 2 * clmd->sim_parms->Cdis * 0.01) ), k); } } else // calculate force of bending springs { if(length < L) { - // clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; + // clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = fbstar(length, L, clmd->sim_parms.bending, cb); + k = fbstar(length, L, clmd->sim_parms->bending, cb); mul_fvector_S(bending_force, dir, k); VECADD(s->f, s->f, bending_force); // DG: My formula to handle bending for the AIMEX scheme // multiply with 1000 because of numerical problems - if( ((k*1000)*dt*dt) < -0.18 ) + // if( ((k*1000)*dt*dt) < -0.18 ) { - dfdx_spring_type2(s->dfdx, dir,length,L,clmd->sim_parms.bending, cb); - clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; + dfdx_spring_type2(s->dfdx, dir,length,L,clmd->sim_parms->bending, cb); + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; } // printf("(dt*k*dt) ): %f, k: %f\n", (dt*dt*k*-1.0), k); } @@ -1282,7 +1411,7 @@ DO_INLINE int cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv); add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); } - else if(!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE)) + else if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE)) return 0; sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx); @@ -1340,9 +1469,9 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec /* Collect forces and derivatives: F,dFdX,dFdV */ Cloth *cloth = clmd->clothObject; unsigned int i = 0; - float spring_air = clmd->sim_parms.Cvi * 0.01f; /* viscosity of air scaled in percent */ + float spring_air = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */ float gravity[3]; - float tm2[3][3] = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}}; + float tm2[3][4] = {{-spring_air,0,0,0}, {0,-spring_air,0,0},{0,0,-spring_air,0}}; ClothVertex *verts = cloth->verts; MFace *mfaces = cloth->mfaces; float wind_normalized[3]; @@ -1351,7 +1480,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec float kd, ks; LinkNode *search = cloth->springs; - VECCOPY(gravity, clmd->sim_parms.gravity); + VECCOPY(gravity, clmd->sim_parms->gravity); mul_fvector_S(gravity, gravity, 0.001f); /* scale gravity force */ /* set dFdX jacobi matrix to zero */ @@ -1364,7 +1493,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec submul_lfvectorS(lF, lV, spring_air, numverts); /* do goal stuff */ - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { for(i = 0; i < numverts; i++) { @@ -1376,12 +1505,12 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec VECADD(tvect, tvect, cloth->xold[i]); VECSUB(auxvect, tvect, lX[i]); - ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms.goalspring)-1.0f ; + ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms->goalspring)-1.0f ; VECADDS(lF[i], lF[i], auxvect, -ks); // calulate damping forces generated by goals VECSUB(velgoal, cloth->xold[i], cloth->xconst[i]); - kd = clmd->sim_parms.goalfrict * 0.01f; // friction force scale taken from SB + kd = clmd->sim_parms->goalfrict * 0.01f; // friction force scale taken from SB VECSUBADDSS(lF[i], velgoal, kd, lV[i], kd); } @@ -1418,13 +1547,13 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec while(search) { // only handle active springs - // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)){} + // if(((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)){} cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX, dt); search = search->next; } - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE) + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE) { if(cloth->numspringssave != cloth->numsprings) { @@ -1444,46 +1573,62 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec while(search) { // only handle active springs - // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) + // if(((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)) if(!cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX)) break; search = search->next; } - clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; + clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; } + void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, fmatrix3x3 *P, fmatrix3x3 *Pinv) { unsigned int numverts = dFdV[0].vcount; lfVector *dFdXmV = create_lfvector(numverts); + initdiag_bfmatrix(A, I); - // zero_lfvector(dV, numverts); - + subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); mul_bfmatrix_lfvector(dFdXmV, dFdX, lV); add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts); - itstart(); + cg_filtered(dV, A, B, z, S); // conjugate gradient algorithm to solve Ax=b + // cg_filtered_pre(dV, A, B, z, S, P, Pinv); - cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */ - // cg_filtered_pre(dV, A, B, z, dV, P, Pinv, dt); - - itend(); - // printf("cg_filtered calc time: %f\n", (float)itval()); - - - // advance velocities add_lfvector_lfvector(Vnew, lV, dV, numverts); del_lfvector(dFdXmV); } +/* +// this version solves for the new velocity +void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, fmatrix3x3 *P, fmatrix3x3 *Pinv) +{ + unsigned int numverts = dFdV[0].vcount; + + lfVector *dFdXmV = create_lfvector(numverts); + + initdiag_bfmatrix(A, I); + + subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); + + mul_bfmatrix_lfvector(dFdXmV, dFdV, lV); + + add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, -dt, numverts); + add_lfvector_lfvector(B, B, lV, numverts); + + cg_filtered_pre(Vnew, A, B, z, S, P, Pinv); + + del_lfvector(dFdXmV); +} +*/ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) { unsigned int i=0; @@ -1491,13 +1636,13 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase Cloth *cloth = clmd->clothObject; ClothVertex *verts = cloth->verts; unsigned int numverts = cloth->numverts; - float dt = 1.0f / clmd->sim_parms.stepsPerFrame; + float dt = 1.0f / clmd->sim_parms->stepsPerFrame; Implicit_Data *id = cloth->implicit; int result = 0; float force = 0, lastforce = 0; lfVector *dx; - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { for(i = 0; i < numverts; i++) { @@ -1518,7 +1663,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, dt ); // check for sleeping - if(!(clmd->coll_parms.flags & CLOTH_SIMSETTINGS_FLAG_SLEEP)) + // if(!(clmd->coll_parms->flags & CLOTH_SIMSETTINGS_FLAG_SLEEP)) { simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->P, id->Pinv); @@ -1530,14 +1675,16 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase force = dot_lfvector(dx, dx, numverts); del_lfvector(dx); + /* if((force < 0.00001) && (lastforce >= force)) - clmd->coll_parms.flags |= CLOTH_SIMSETTINGS_FLAG_SLEEP; + clmd->coll_parms->flags |= CLOTH_SIMSETTINGS_FLAG_SLEEP; else if((lastforce*2 < force)) - clmd->coll_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_SLEEP; + */ + clmd->coll_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_SLEEP; lastforce = force; - if(clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + if(clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) { // collisions // itstart(); @@ -1545,7 +1692,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // update verts to current positions for(i = 0; i < numverts; i++) { - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { if(verts [i].goal >= SOFTGOALSNAP) { @@ -1615,7 +1762,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase if(effectors) pdEndEffectors(effectors); } - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { for(i = 0; i < numverts; i++) { @@ -1633,11 +1780,19 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase } else { - memcpy(cloth->current_xold, id->X, sizeof(lfVector) * numverts); - memcpy(cloth->x, id->X, sizeof(lfVector) * numverts); + for(i = 0; i < numverts; i++) + { + VECCOPY(cloth->current_xold[i], id->X[i]); + VECCOPY(cloth->x[i], id->X[i]); + } + // memcpy(cloth->current_xold, id->X, sizeof(lfVector) * numverts); + // memcpy(cloth->x, id->X, sizeof(lfVector) * numverts); } - memcpy(cloth->v, id->V, sizeof(lfVector) * numverts); + for(i = 0; i < numverts; i++) + VECCOPY(cloth->v[i], id->V[i]); + + // memcpy(cloth->v, id->V, sizeof(lfVector) * numverts); return 1; } @@ -1645,11 +1800,18 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase void implicit_set_positions (ClothModifierData *clmd) { Cloth *cloth = clmd->clothObject; - unsigned int numverts = cloth->numverts; + unsigned int numverts = cloth->numverts, i = 0; Implicit_Data *id = cloth->implicit; - memcpy(id->X, cloth->x, sizeof(lfVector) * numverts); - memcpy(id->V, cloth->v, sizeof(lfVector) * numverts); + + for(i = 0; i < numverts; i++) + { + VECCOPY(id->X[i], cloth->x[i]); + VECCOPY(id->V[i], cloth->v[i]); + } + + // memcpy(id->X, cloth->x, sizeof(lfVector) * numverts); + // memcpy(id->V, cloth->v, sizeof(lfVector) * numverts); } @@ -1668,7 +1830,7 @@ int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierD cloth1 = clmd->clothObject; cloth2 = coll_clmd->clothObject; - // search = clmd->coll_parms.collision_list; + // search = clmd->coll_parms->collision_list; while(search) { @@ -1711,10 +1873,10 @@ int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierD float vrel_t_pre[3]; float vrel_t[3]; double impulse; - float epsilon = clmd->coll_parms.epsilon; + float epsilon = clmd->coll_parms->epsilon; float overlap = (epsilon + ALMOST_ZERO-collpair->distance); - // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); + // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms->friction*0.01, magrelVel); // magtangent = INPR(tangential, tangential); @@ -1790,7 +1952,7 @@ void cloth_collision_static(ClothModifierData *clmd, LinkNode *collision_list) MFace *face1=NULL, *face2=NULL; ClothVertex *verts1=NULL, *verts2=NULL; double distance = 0; - float epsilon = clmd->coll_parms.epsilon; + float epsilon = clmd->coll_parms->epsilon; unsigned int i = 0; for(i = 0; i < 4; i++) @@ -1940,7 +2102,7 @@ void collisions_collision_moving_edges(ClothModifierData *clmd, ClothModifierDat MFace *face1=NULL, *face2=NULL; ClothVertex *verts1=NULL, *verts2=NULL; double distance = 0; - float epsilon = clmd->coll_parms.epsilon; + float epsilon = clmd->coll_parms->epsilon; unsigned int i = 0, j = 0, k = 0; int numsolutions = 0; float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; @@ -2077,7 +2239,7 @@ void collisions_collision_moving_tris(ClothModifierData *clmd, ClothModifierData MFace *face1=NULL, *face2=NULL; ClothVertex *verts1=NULL, *verts2=NULL; double distance = 0; - float epsilon = clmd->coll_parms.epsilon; + float epsilon = clmd->coll_parms->epsilon; unsigned int i = 0, j = 0, k = 0; int numsolutions = 0; float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; @@ -2184,11 +2346,11 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, CollisionModifierData *collmd = NULL; Cloth *cloth = NULL; Object *ob2 = NULL; - BVH *bvh1 = NULL, *bvh2 = NULL; + BVH *bvh1 = NULL, *bvh2 = NULL, *self_bvh; LinkNode *collision_list = NULL; unsigned int i = 0, j = 0; int collisions = 0, count = 0; - float (*current_x)[3]; + float (*current_x)[4]; if (!(((Cloth *)clmd->clothObject)->tree)) { @@ -2198,14 +2360,15 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, cloth = clmd->clothObject; bvh1 = cloth->tree; + self_bvh = cloth->selftree; //////////////////////////////////////////////////////////// // static collisions //////////////////////////////////////////////////////////// // update cloth bvh - bvh_update_from_float3(bvh1, cloth->current_xold, cloth->numverts, cloth->current_x, 0); // 0 means STATIC, 1 means MOVING (see later in this function) - + bvh_update_from_float4(bvh1, cloth->current_xold, cloth->numverts, cloth->current_x, 0); // 0 means STATIC, 1 means MOVING (see later in this function) +/* // check all collision objects for (base = G.scene->base.first; base; base = base->next) { @@ -2256,12 +2419,84 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, VECADD(cloth->current_x[i], cloth->current_xold[i], cloth->current_v[i]); } ////////////////////////////////////////////// +*/ + /* + // fill collision list + collisions += bvh_traverse(self_bvh->root, self_bvh->root, &collision_list); + // call static collision response + + // free collision list + if(collision_list) + { + LinkNode *search = collision_list; + + while(search) + { + float distance = 0; + float mindistance = cloth->selftree->epsilon; + CollisionPair *collpair = (CollisionPair *)search->link; + + // get distance of faces + distance = plNearestPoints( + cloth->current_x[collpair->point_indexA[0]], cloth->current_x[collpair->point_indexA[1]], cloth->current_x[collpair->point_indexA[2]], cloth->current_x[collpair->point_indexB[0]], cloth->current_x[collpair->point_indexB[1]], cloth->current_x[collpair->point_indexB[2]], collpair->pa,collpair->pb,collpair->vector); + + if(distance < mindistance) + { + /////////////////////////////////////////// + // TODO: take velocity of the collision points into account! + /////////////////////////////////////////// + + float correction = mindistance - distance; + float temp[3]; + + VECCOPY(temp, collpair->vector); + Normalize(temp); + VecMulf(temp, -correction*0.5); + + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[0]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexA[0]], cloth->current_x[collpair->point_indexA[0]], temp); + + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[1]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexA[1]], cloth->current_x[collpair->point_indexA[1]], temp); + + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[2]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexA[2]], cloth->current_x[collpair->point_indexA[2]], temp); + + + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[0]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexB[0]], cloth->current_x[collpair->point_indexB[0]], temp); + + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[1]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexB[1]], cloth->current_x[collpair->point_indexB[1]], temp); + + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[2]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexB[2]], cloth->current_x[collpair->point_indexB[2]], temp); + + collisions = 1; + + } + + } + + search = collision_list; + while(search) + { + CollisionPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(collision_list,NULL); + + collision_list = NULL; + } + */ // Test on *simple* selfcollisions collisions = 1; count = 0; current_x = cloth->current_x; // needed for openMP - +/* #pragma omp parallel for private(i,j, collisions) shared(current_x) for(count = 0; count < 6; count++) { @@ -2275,7 +2510,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, float length = 0; float mindistance = cloth->selftree->epsilon; - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { if((cloth->verts [i].goal >= SOFTGOALSNAP) && (cloth->verts [j].goal >= SOFTGOALSNAP)) @@ -2298,12 +2533,12 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, { float correction = mindistance - length; - if((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [i].goal >= SOFTGOALSNAP)) + if((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [i].goal >= SOFTGOALSNAP)) { VecMulf(temp, -correction); VECADD(current_x[j], current_x[j], temp); } - else if((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [j].goal >= SOFTGOALSNAP)) + else if((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [j].goal >= SOFTGOALSNAP)) { VecMulf(temp, correction); VECADD(current_x[i], current_x[i], temp); @@ -2320,12 +2555,8 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, } } } - /* - // does not compile with OpenMP - if(!collisions) - break; - */ } + ////////////////////////////////////////////// // SELFCOLLISIONS: update velocities @@ -2335,6 +2566,6 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, VECSUB(cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i]); } ////////////////////////////////////////////// - +*/ return 1; } diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index e168d3a9954..234a6b75548 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -751,6 +751,58 @@ BVH *bvh_build_from_float3 (MFace *mfaces, unsigned int numfaces, float (*x)[3], return bvh_build(bvh, mfaces, numfaces); } +BVH *bvh_build_from_float4 (MFace *mfaces, unsigned int numfaces, float (*x)[4], unsigned int numverts, float epsilon) +{ + BVH *bvh=NULL; + CollisionTree *tree=NULL; + unsigned int i = 0; + + bvh = MEM_callocN(sizeof(BVH), "BVH"); + if (bvh == NULL) + { + printf("bvh: Out of memory.\n"); + return NULL; + } + + bvh->flags = 0; + bvh->leaf_tree = NULL; + bvh->leaf_root = NULL; + bvh->tree = NULL; + + bvh->epsilon = epsilon; + bvh->numfaces = numfaces; + bvh->mfaces = mfaces; + + // we have no faces, we save seperate points + if(!mfaces) + { + bvh->numfaces = numverts; + } + + bvh->numverts = numverts; + bvh->xnew = (MVert *)MEM_callocN(sizeof(MVert)*numverts, "BVH MVert"); + + for(i = 0; i < numverts; i++) + { + VECCOPY(bvh->xnew[i].co, x[i]); + } + + bvh->x = MEM_dupallocN(bvh->xnew); + + tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree"); + + if (tree == NULL) + { + printf("bvh_build: Out of memory for nodes.\n"); + bvh_free(bvh); + return NULL; + } + + BLI_linklist_append(&bvh->tree, tree); + + return bvh_build(bvh, mfaces, numfaces); +} + // bvh_overlap - is it possbile for 2 bv's to collide ? int bvh_overlap(float *bv1, float *bv2) { @@ -789,23 +841,80 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio // Check if this node in the second tree a leaf if (tree2->isleaf) { + ////////////////////////////////// + // TODO: check for 3rd point if zero (triangle)!!! + ////////////////////////////////// + CollisionPair *collpair = NULL; if(tree1 != tree2) // do not collide same points { + //////////////////////////////////////// + // FIRST FACE + //////////////////////////////////////// + // save potential colliding triangles collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); VECCOPY(collpair->point_indexA, tree1->point_index); - collpair->point_indexA[3] = tree1->point_index[3]; - VECCOPY(collpair->point_indexB, tree2->point_index); - collpair->point_indexB[3] = tree2->point_index[3]; // we use prepend because lots of insertions at end // of list are horrible slow! BLI_linklist_prepend(&collision_list[0], collpair); + //////////////////////////////////////// + // SECOND FACE + //////////////////////////////////////// + if(tree1->point_index[3]) // check for quad face + { + // save potential colliding triangles + collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); + + VECCOPY(collpair->point_indexA, tree1->point_index); + collpair->point_indexA[2] = tree1->point_index[3]; + + VECCOPY(collpair->point_indexB, tree2->point_index); + + // we use prepend because lots of insertions at end + // of list are horrible slow! + BLI_linklist_prepend(&collision_list[0], collpair); + } + //////////////////////////////////////// + // THIRD FACE + //////////////////////////////////////// + if(tree2->point_index[3]) // check for quad face + { + // save potential colliding triangles + collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); + + VECCOPY(collpair->point_indexA, tree1->point_index); + + VECCOPY(collpair->point_indexB, tree2->point_index); + collpair->point_indexB[2] = tree2->point_index[3]; + + // we use prepend because lots of insertions at end + // of list are horrible slow! + BLI_linklist_prepend(&collision_list[0], collpair); + } + //////////////////////////////////////// + // FOURTH FACE + //////////////////////////////////////// + if(tree1->point_index[3] && tree1->point_index[3]) // check for quad face + { + // save potential colliding triangles + collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); + + VECCOPY(collpair->point_indexA, tree1->point_index); + collpair->point_indexA[2] = tree1->point_index[3]; + + VECCOPY(collpair->point_indexB, tree2->point_index); + collpair->point_indexB[2] = tree2->point_index[3]; + + // we use prepend because lots of insertions at end + // of list are horrible slow! + BLI_linklist_prepend(&collision_list[0], collpair); + } return 1; } else @@ -965,3 +1074,29 @@ void bvh_update_from_float3(BVH * bvh, float (*x)[3], unsigned int numverts, flo bvh_update(bvh, moving); } + +void bvh_update_from_float4(BVH * bvh, float (*x)[4], unsigned int numverts, float (*xnew)[4], int moving) +{ + unsigned int i = 0; + + if(!bvh) + return; + + if(numverts!=bvh->numverts) + return; + + if(x) + { + for(i = 0; i < numverts; i++) + VECCOPY(bvh->x[i].co, x[i]); + } + + if(xnew) + { + for(i = 0; i < numverts; i++) + VECCOPY(bvh->xnew[i].co, xnew[i]); + } + + bvh_update(bvh, moving); +} + diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 531cd78b3b2..f599edf52d9 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4865,6 +4865,12 @@ static void softbodyModifier_deformVerts( static void clothModifier_initData(ModifierData *md) { ClothModifierData *clmd = (ClothModifierData*) md; + + clmd->sim_parms = MEM_callocN(sizeof(SimulationSettings), + "cloth sim parms"); + clmd->coll_parms = MEM_callocN(sizeof(CollisionSettings), + "cloth coll parms"); + cloth_init (clmd); } /* @@ -4942,8 +4948,8 @@ CustomDataMask clothModifier_requiredDataMask(ModifierData *md) CustomDataMask dataMask = 0; /* ask for vertexgroups if we need them */ - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - if (clmd->sim_parms.vgroup_mass > 0) + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + if (clmd->sim_parms->vgroup_mass > 0) dataMask |= (1 << CD_MDEFORMVERT); return dataMask; @@ -4961,8 +4967,12 @@ static void clothModifier_freeData(ModifierData *md) if (clmd) { - clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; + + clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; cloth_free_modifier (clmd); + + MEM_freeN(clmd->sim_parms); + MEM_freeN(clmd->coll_parms); } } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8ee70d4efd2..afe342d8665 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2885,13 +2885,10 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) ClothModifierData *clmd = (ClothModifierData*) md; clmd->clothObject = NULL; - clmd->sim_parms.cache = NULL; - - if (clmd->sim_parms.cache) { - // TODO - // clmd->cache = newdataadr (fd, clmd->cache); - printf ("direct_link_modifiers: read cloth baked_data.\n"); - } + + clmd->sim_parms= newdataadr(fd, clmd->sim_parms); + clmd->coll_parms= newdataadr(fd, clmd->coll_parms); + } else if (md->type==eModifierType_Collision) { CollisionModifierData *collmd = (CollisionModifierData*) md; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 1887f95e1da..64849affdbf 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -771,23 +771,6 @@ static void write_constraint_channels(WriteData *wd, ListBase *chanbase) } -/* -// TODO: finish this -static void write_cloth_cache(WriteData *wd, LinkNode *ln) -{ - - while(ln) { - writestruct(wd, DATA, "cloth_cache", 1, ln); - writestruct(wd, DATA, "cloth_cache_frame", 1, ln->link); - writestruct(wd, DATA, "cloth_cache_frame_verts", 1, ln->link); - writestruct(wd, DATA, "cloth_cache_frame_springs", 1, ln->link); - } - - ln = ln->next; - } -} -*/ - static void write_modifiers(WriteData *wd, ListBase *modbase) { ModifierData *md; @@ -803,28 +786,15 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) HookModifierData *hmd = (HookModifierData*) md; writedata(wd, DATA, sizeof(int)*hmd->totindex, hmd->indexar); - } - else if (md->type==eModifierType_Cloth) { - int n; - ClothModifierData *clmd = (ClothModifierData *) md; - - if (clmd->sim_parms.cache) { - // Compute the number of vertices we're saving. - // TODO - // write_cloth_cache(); - /* - // old code - n = (clmd->sim_parms.bake_end_frame - clmd->sim_parms.bake_start_frame + 1) * - clmd->sim_parms.bake_num_verts; - writedata (wd, DATA, n * sizeof (clmd->baked_data [0]), clmd->baked_data); - printf ("write_modifiers: wrote %d elements of size %d for cloth baked data.\n", - n, sizeof (clmd->baked_data [0])); - */ - } } + else if(md->type==eModifierType_Cloth) { + ClothModifierData *clmd = (ClothModifierData*) md; + writestruct(wd, DATA, "SimulationSettings", 1, clmd->sim_parms); + writestruct(wd, DATA, "CollisionSettings", 1, clmd->coll_parms); + } else if (md->type==eModifierType_MeshDeform) { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; - + writedata(wd, DATA, sizeof(float)*mmd->totvert*mmd->totcagevert, mmd->bindweights); writedata(wd, DATA, sizeof(float)*3*mmd->totcagevert, diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 2441c8b721f..4d8fbf1a6fc 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -32,55 +32,7 @@ #ifndef DNA_CLOTH_TYPES_H #define DNA_CLOTH_TYPES_H -#include "DNA_listBase.h" - - -/** -* Pin and unpin frames are the frames on which the vertices stop moving. -* They will assume the position they had prior to pinFrame until unpinFrame -* is reached. -*/ -typedef struct ClothVertex -{ - int flags; /* General flags per vertex. */ - float mass; /* mass / weight of the vertex */ - float goal; /* goal, from SB */ - float impulse[3]; /* used in collision.c */ - unsigned int impulse_count; /* same as above */ -} ClothVertex; - - -/** -* The definition of a spring. -*/ -typedef struct ClothSpring -{ - int ij; /* Pij from the paper, one end of the spring. */ - int kl; /* Pkl from the paper, one end of the spring. */ - float restlen; /* The original length of the spring. */ - int matrix_index; /* needed for implicit solver (fast lookup) */ - int type; /* types defined in BKE_cloth.h ("springType") */ - int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ - float dfdx[3][3]; - float dfdv[3][3]; - float f[3]; -} ClothSpring; - - - -/** -* This struct contains all the global data required to run a simulation. -* At the time of this writing, this structure contains data appropriate -* to run a simulation as described in Deformation Constraints in a -* Mass-Spring Model to Describe Rigid Cloth Behavior by Xavier Provot. -* -* I've tried to keep similar, if not exact names for the variables as -* are presented in the paper. Where I've changed the concept slightly, -* as in stepsPerFrame comapred to the time step in the paper, I've used -* variables with different names to minimize confusion. -**/ -typedef struct SimulationSettings -{ +typedef struct SimulationSettings { short vgroup_mass; /* optional vertexgroup name for assigning weight. */ short pad; float mingoal; /* see SB */ @@ -103,7 +55,6 @@ typedef struct SimulationSettings float eff_force_scale;/* Scaling of effector forces (see softbody_calc_forces).*/ float eff_wind_scale; /* Scaling of effector wind (see softbody_calc_forces). */ float sim_time_old; - struct LinkNode *cache; float defgoal; float goalfrict; float goalspring; @@ -112,9 +63,7 @@ typedef struct SimulationSettings int firstframe; /* frame on which simulation starts */ } SimulationSettings; - -typedef struct CollisionSettings -{ +typedef struct CollisionSettings { float epsilon; /* The radius of a particle in the cloth. */ float self_friction; /* Fiction/damping with self contact. */ float friction; /* Friction/damping applied on contact with other object.*/ @@ -125,40 +74,4 @@ typedef struct CollisionSettings } CollisionSettings; -/** -* This structure describes a cloth object against which the -* simulation can run. -* -* The m and n members of this structure represent the assumed -* rectangular ordered grid for which the original paper is written. -* At some point they need to disappear and we need to determine out -* own connectivity of the mesh based on the actual edges in the mesh. -* -**/ -typedef struct Cloth -{ - struct ClothVertex *verts; /* The vertices that represent this cloth. */ - struct LinkNode *springs; /* The springs connecting the mesh. */ - unsigned int numverts; /* The number of verts == m * n. */ - unsigned int numsprings; /* The count of springs. */ - unsigned int numfaces; - unsigned char old_solver_type; - unsigned char pad2; - short pad3; - struct BVH *tree; /* collision tree for this cloth object */ - struct BVH *selftree; /* self collision tree for this cloth object */ - struct MFace *mfaces; - struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ - float (*x)[3]; /* The current position of all vertices.*/ - float (*xold)[3]; /* The previous position of all vertices.*/ - float (*current_x)[3]; /* The TEMPORARY current position of all vertices.*/ - float (*current_xold)[3]; /* The TEMPORARY previous position of all vertices.*/ - float (*v)[3]; /* the current velocity of all vertices */ - float (*current_v)[3]; - float (*xconst)[3]; - struct EdgeHash *edgehash; /* used for fast checking adjacent points */ - unsigned int numothersprings; - unsigned int numspringssave; -} Cloth; - #endif diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index ea7e67ddac4..48069f2d7b7 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -9,8 +9,6 @@ /* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE! */ -#include "DNA_cloth_types.h" - typedef enum ModifierType { eModifierType_None = 0, eModifierType_Subsurf, @@ -343,10 +341,10 @@ typedef struct SoftbodyModifierData { typedef struct ClothModifierData { ModifierData modifier; - - struct Cloth *clothObject; /* The internal data structure for cloth. */ - SimulationSettings sim_parms; /* definition is in DNA_cloth_types.h */ - CollisionSettings coll_parms; /* definition is in DNA_cloth_types.h */ + + 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 { diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 2d5b54ac1c2..3adc2862a94 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2208,7 +2208,8 @@ void do_object_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - if(clmd->sim_parms.cache) + /* + if(clmd->sim_parms->cache) { CFRA= 1; update_for_newframe_muted(); @@ -2216,6 +2217,7 @@ void do_object_panels(unsigned short event) allqueue(REDRAWBUTSOBJECT, 0); allqueue(REDRAWVIEW3D, 0); } + */ } } break; @@ -2224,7 +2226,7 @@ void do_object_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - clmd->sim_parms.vgroup_mass = 0; + clmd->sim_parms->vgroup_mass = 0; do_object_panels(B_CLOTH_RENEW); } @@ -3158,9 +3160,9 @@ static void object_panel_cloth(Object *ob) if(clmd) { - // but = uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object", 170,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); + // but = uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object", 170,200,130,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); - if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) + if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { Cloth *cloth = clmd->clothObject; int defCount; @@ -3169,18 +3171,18 @@ static void object_panel_cloth(Object *ob) val2=0; - // uiDefButBitI(block, TOG, CSIMSETT_FLAG_ADVANCED, REDRAWBUTSOBJECT, "Advanced", 180,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Enable advanced mode"); + // uiDefButBitI(block, TOG, CSIMSETT_FLAG_ADVANCED, REDRAWBUTSOBJECT, "Advanced", 180,200,130,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Enable advanced mode"); /* GENERAL STUFF */ uiClearButLock(); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility"); - uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 3.0, 10.0, 5, 0, "Quality of the simulation (higher=>better=>slower)"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms->structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms->bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility"); + uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,150,150,20, &clmd->sim_parms->stepsPerFrame, 3.0, 10.0, 5, 0, "Quality of the simulation (higher=>better=>slower)"); uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Spring damping"); - uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms.Cvi, 0.0, 10.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms->Cdis, 0.0, 10.0, 10, 0, "Spring damping"); + uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms->Cvi, 0.0, 10.0, 10, 0, "Apply gravitation to point movement"); uiBlockEndAlign(block); uiClearButLock(); @@ -3189,15 +3191,15 @@ static void object_panel_cloth(Object *ob) uiDefBut(block, LABEL, 0, "Gravity:", 10,100,60,20, NULL, 0.0, 0, 0, 0, ""); // uiClearButLock(); - uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,100,80,20, &clmd->sim_parms.gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,100,80,20, &clmd->sim_parms.gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:", 230,100,80,20, &clmd->sim_parms.gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,100,80,20, &clmd->sim_parms->gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,100,80,20, &clmd->sim_parms->gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:", 230,100,80,20, &clmd->sim_parms->gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); uiBlockEndAlign(block); /* GOAL STUFF */ uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Use Goal", 10,70,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); - if (clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Use Goal", 10,70,130,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); + if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { if(ob->type==OB_MESH) { @@ -3212,17 +3214,17 @@ static void object_panel_cloth(Object *ob) defCount = BLI_countlist (&ob->defbase); if (defCount == 0) { - clmd->sim_parms.vgroup_mass = 0; + clmd->sim_parms->vgroup_mass = 0; } sprintf (clvg2, "%s%s", clmvg, clvg1); - uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups"); + uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 140,70,20,20, &clmd->sim_parms->vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups"); MEM_freeN (clvg1); MEM_freeN (clvg2); - if(clmd->sim_parms.vgroup_mass) + if(clmd->sim_parms->vgroup_mass) { - bDeformGroup *defGroup = BLI_findlink(&ob->defbase, clmd->sim_parms.vgroup_mass-1); + bDeformGroup *defGroup = BLI_findlink(&ob->defbase, clmd->sim_parms->vgroup_mass-1); if(defGroup) uiDefBut(block, BUT, B_DIFF, defGroup->name, 160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group"); else @@ -3232,30 +3234,30 @@ static void object_panel_cloth(Object *ob) } else - uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); } else { - uiDefButS(block, TOG, B_CLOTH_RENEW, "W", 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + uiDefButS(block, TOG, B_CLOTH_RENEW, "W", 140,70,20,20, &clmd->sim_parms->vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); } - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Damp:", 160,50,150,20, &clmd->sim_parms.goalfrict, 0.0, 50.0, 10, 0, "Goal (vertex target position) friction"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Min:", 10,30,150,20, &clmd->sim_parms.mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Max:", 160,30,150,20, &clmd->sim_parms.maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Stiff:", 10,50,150,20, &clmd->sim_parms->goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Damp:", 160,50,150,20, &clmd->sim_parms->goalfrict, 0.0, 50.0, 10, 0, "Goal (vertex target position) friction"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Min:", 10,30,150,20, &clmd->sim_parms->mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Max:", 160,30,150,20, &clmd->sim_parms->maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); } uiBlockEndAlign(block); /* // no tearing supported anymore since modifier stack restrictions uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CSIMSETT_FLAG_TEARING_ENABLED, B_EFFECT_DEP, "Tearing", 10,0,150,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); + uiDefButBitI(block, TOG, CSIMSETT_FLAG_TEARING_ENABLED, B_EFFECT_DEP, "Tearing", 10,0,150,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); - if (clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) + if (clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) { - uiDefButI(block, NUM, B_DIFF, "Max extent:", 160,0,150,20, &clmd->sim_parms.maxspringlen, 1.0, 1000.0, 10, 0, "Maximum extension before spring gets cut"); + uiDefButI(block, NUM, B_DIFF, "Max extent:", 160,0,150,20, &clmd->sim_parms->maxspringlen, 1.0, 1000.0, 10, 0, "Maximum extension before spring gets cut"); } uiBlockEndAlign(block); @@ -3275,7 +3277,7 @@ static void object_panel_cloth_II(Object *ob) clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) + if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { Cloth *cloth = clmd->clothObject; char str[128]; @@ -3286,18 +3288,18 @@ static void object_panel_cloth_II(Object *ob) uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - uiDefButI(block, NUM, B_DIFF, "First Frame:", 10,160,150,20, &clmd->sim_parms.firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts"); - uiDefButI(block, NUM, B_DIFF, "Last Frame:", 160,160,150,20, &clmd->sim_parms.lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops"); - - if(clmd->sim_parms.cache) + uiDefButI(block, NUM, B_DIFF, "First Frame:", 10,160,150,20, &clmd->sim_parms->firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts"); + uiDefButI(block, NUM, B_DIFF, "Last Frame:", 160,160,150,20, &clmd->sim_parms->lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops"); + /* + if(clmd->sim_parms->cache) { - int length = BLI_linklist_length(clmd->sim_parms.cache); + int length = BLI_linklist_length(clmd->sim_parms->cache); - /* correct spelling if only 1 frame cacheed --> only gimmick */ - if(length-clmd->sim_parms.preroll>1) - sprintf (str, "Frame 1 - %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms.preroll, clmd->sim_parms.preroll, length); + // correct spelling if only 1 frame cacheed --> only gimmick + if(length-clmd->sim_parms->preroll>1) + sprintf (str, "Frame 1 - %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length); else - sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms.preroll, clmd->sim_parms.preroll, length); + sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length); uiDefBut(block, LABEL, 0, str, 10,140,290,20, NULL, 0.0, 0, 0, 0, ""); uiDefBut(block, LABEL, 0, "Clear cache:", 10,120,290,20, NULL, 0.0, 0, 0, 0, ""); @@ -3305,15 +3307,15 @@ static void object_panel_cloth_II(Object *ob) uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 10, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache without preroll"); uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache"); if(length>1) // B_CLOTH_CHANGEPREROLL - uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); + uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms->preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); else uiDefBut(block, LABEL, 0, " ", 10,80,145,20, NULL, 0.0, 0, 0, 0, ""); } - else + else { uiDefBut(block, LABEL, 0, "No frames cached.", 10,120,290,20, NULL, 0.0, 0, 0, 0, ""); - } - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,50,145,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); + }*/ + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,50,145,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); uiBlockEndAlign(block); } } @@ -3335,13 +3337,13 @@ static void object_panel_cloth_III(Object *ob) uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,160,130,20, &clmd->coll_parms.flags, 0, 0, 0, 0, "Enable collisions with this object"); - if (clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,160,130,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable collisions with this object"); + if (clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) { // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ - uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,140,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,140,150,20, &clmd->coll_parms->epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); uiDefBut(block, LABEL, 0, "",160,140,150,20, NULL, 0.0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Selfcoll balls:", 10,120,150,20, &clmd->coll_parms.selfepsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between two selfcollision points"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Selfcoll balls:", 10,120,150,20, &clmd->coll_parms->selfepsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between two selfcollision points"); } else uiDefBut(block, LABEL, 0, "",140,10,170,20, NULL, 0.0, 0, 0, 0, ""); From 14de7f4a2b70c4c1d159542b73dc01fac48261f8 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 19 Nov 2007 00:01:33 +0000 Subject: [PATCH 052/101] fixed sse copy-paste glitch + #define __SSE3__ thanks to Lynx3d --- source/blender/blenkernel/intern/cloth.c | 4 +- source/blender/blenkernel/intern/implicit.c | 157 ++------------------ 2 files changed, 15 insertions(+), 146 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index ea3c8dec0c0..b0a45b6e720 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -567,6 +567,8 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d { if ((clmd->clothObject == NULL) || (numverts != clmd->clothObject->numverts) ) { + cloth_clear_cache(ob, clmd, 0); + if(!cloth_from_object (ob, clmd, result, dm, framenr)) return result; @@ -756,7 +758,7 @@ static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *cl for (i = 0; i < numverts; i++) { VECCOPY (mvert[i].co, cloth->x[i]); - Mat4MulVecfl (ob->imat, mvert[i].co); /* softbody is in global coords */ + Mat4MulVecfl (ob->imat, mvert[i].co); /* cloth is in global coords */ } } } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index c457064065c..eab5e992abe 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -410,14 +410,15 @@ DO_INLINE void mul_fvector_fmatrix(float *to, float *from, float matrix[3][4]) /* 3x3 matrix multiplied by a vector */ /* STATUS: verified */ -#ifdef SSE3 +#ifdef __SSE3__ DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][4], float *from) { + float temp[4]; __m128 v1, v2, v3, v4; - v1 = _mm_load_ps(&matrix[0]); - v2 = _mm_load_ps(&matrix[1]); - v3 = _mm_load_ps(&matrix[2]); - v4 = _mm_load_ps(from); + v1 = _mm_loadu_ps(&matrix[0][0]); + v2 = _mm_loadu_ps(&matrix[1][0]); + v3 = _mm_loadu_ps(&matrix[2][0]); + v4 = _mm_loadu_ps(from); // stuff v1 = _mm_mul_ps(v1, v4); @@ -425,9 +426,9 @@ DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][4], float *from) { v3 = _mm_mul_ps(v3, v4); v1 = _mm_hadd_ps(v1, v2); v3 = _mm_hadd_ps(v3, _mm_setzero_ps()); - v1 = _mm_hadd_ps(v1, v3); + v4 = _mm_hadd_ps(v1, v3); - _mm_store_ps(to, v4); + _mm_storeu_ps(to, v4); } #else DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][4], float *from) @@ -537,7 +538,7 @@ DO_INLINE void mulsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float /* 3x3 matrix multiplied+added by a vector */ /* STATUS: verified */ -#ifdef SSE3 +#ifdef __SSE3__ DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][4], float from[3]) { __m128 v1, v2, v3, v4; @@ -1053,141 +1054,7 @@ DO_INLINE void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv) } } -/* -// 1.0 working PCG, but slow and unstable for bigger epsilon + strong forces -int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv) -{ - unsigned int numverts = lA[0].vcount, iterations = 0, conjgrad_looplimit=100; - float delta0 = 0, deltaNew = 0, deltaOld = 0, alpha = 0; - float conjgrad_epsilon=0.01f, conjgrad_lasterror=0; - lfVector *filterb = create_lfvector(numverts); - lfVector *p_fb = create_lfvector(numverts); - lfVector *r = create_lfvector(numverts); - lfVector *c = create_lfvector(numverts); - lfVector *q = create_lfvector(numverts); - lfVector *s = create_lfvector(numverts); - - BuildPPinv(lA, P, Pinv); - - cp_lfvector(dv, z, numverts); - cp_lfvector(filterb, lB, numverts); - filter(filterb, S); - mul_bfmatrix_lfvector(p_fb, P, filterb); - delta0 = dot_lfvector(filterb, p_fb, numverts); - - mul_bfmatrix_lfvector(r, lA, dv); - mul_lfvectorS(r, r, -1.0, numverts); - add_lfvector_lfvector(r, r, lB, numverts); - filter(r, S); - - mul_bfmatrix_lfvector(c, Pinv, r); - filter(c, S); - - deltaNew = dot_lfvector(r, c, numverts); - - do - { - iterations++; - - mul_bfmatrix_lfvector(q, lA, c); - filter(q, S); - - alpha = deltaNew / dot_lfvector(c, q, numverts); - - add_lfvector_lfvectorS(dv, dv, c, alpha, numverts); - - add_lfvector_lfvectorS(r, r, q, -alpha, numverts); - - mul_bfmatrix_lfvector(s, Pinv, r); - - - deltaOld = deltaNew; - - deltaNew = dot_lfvector(r, s, numverts); - - add_lfvector_lfvectorS(s, s, c, deltaNew / deltaOld, numverts); - filter(s, S); - - cp_lfvector(c, s, numverts); - } while ((deltaNew > (conjgrad_epsilon*conjgrad_epsilon*delta0)) && (iterations < conjgrad_looplimit)); - - del_lfvector(s); - del_lfvector(q); - del_lfvector(c); - del_lfvector(r); - del_lfvector(p_fb); - del_lfvector(filterb); - - printf("iterations: %d\n", iterations); - - return iterations (conjgrad_epsilon*conjgrad_epsilon*delta0)) && (iterations < conjgrad_looplimit)) - { - iterations++; - - mul_bfmatrix_lfvector(s, lA, p); - filter(s, S); - - alpha = deltaNew / dot_lfvector(p, s, numverts); - - add_lfvector_lfvectorS(dv, dv, p, alpha, numverts); - - add_lfvector_lfvectorS(r, r, s, -alpha, numverts); - - mul_bfmatrix_lfvector(h, Pinv, r); - - - deltaOld = deltaNew; - - deltaNew = dot_lfvector(r, h, numverts); - - add_lfvector_lfvectorS(p, h, p, deltaNew / deltaOld, numverts); - filter(p, S); - - } - - del_lfvector(h); - del_lfvector(s); - del_lfvector(p); - del_lfvector(r); - - printf("iterations: %d\n", iterations); - - return iterations Date: Mon, 19 Nov 2007 00:27:25 +0000 Subject: [PATCH 053/101] #ifdef sse headers --- source/blender/blenkernel/intern/implicit.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index eab5e992abe..f562bd49fcc 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -65,9 +65,11 @@ #include "Bullet-C-Api.h" +#ifdef __SSE3__ #include #include #include +#endif #ifdef _WIN32 #include @@ -412,13 +414,12 @@ DO_INLINE void mul_fvector_fmatrix(float *to, float *from, float matrix[3][4]) /* STATUS: verified */ #ifdef __SSE3__ DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][4], float *from) { - float temp[4]; __m128 v1, v2, v3, v4; - v1 = _mm_loadu_ps(&matrix[0][0]); - v2 = _mm_loadu_ps(&matrix[1][0]); - v3 = _mm_loadu_ps(&matrix[2][0]); - v4 = _mm_loadu_ps(from); + v1 = _mm_load_ps(&matrix[0][0]); + v2 = _mm_load_ps(&matrix[1][0]); + v3 = _mm_load_ps(&matrix[2][0]); + v4 = _mm_load_ps(from); // stuff v1 = _mm_mul_ps(v1, v4); @@ -428,7 +429,7 @@ DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][4], float *from) { v3 = _mm_hadd_ps(v3, _mm_setzero_ps()); v4 = _mm_hadd_ps(v1, v3); - _mm_storeu_ps(to, v4); + _mm_store_ps(to, v4); } #else DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][4], float *from) @@ -542,9 +543,9 @@ DO_INLINE void mulsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][4], float from[3]) { __m128 v1, v2, v3, v4; - v1 = _mm_load_ps(&matrix[0]); - v2 = _mm_load_ps(&matrix[1]); - v3 = _mm_load_ps(&matrix[2]); + v1 = _mm_load_ps(&matrix[0][0]); + v2 = _mm_load_ps(&matrix[1][0]); + v3 = _mm_load_ps(&matrix[2][0]); v4 = _mm_load_ps(from); // stuff From f28ab5de21b028a5726dc7e3975fd1a523287e37 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 19 Nov 2007 23:45:26 +0000 Subject: [PATCH 054/101] Bugfix: scaling/rotation/translation works again --- source/blender/blenkernel/intern/cloth.c | 23 ++++++++++----------- source/blender/blenkernel/intern/implicit.c | 13 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index b0a45b6e720..d0ab7ce4ffb 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -862,13 +862,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d /* create springs */ clmd->clothObject->springs = NULL; clmd->clothObject->numsprings = -1; - - if (!cloth_build_springs (clmd->clothObject, dm) ) - { - modifier_setError (&(clmd->modifier), "Can't build springs."); - return 0; - } - + /* set initial values */ for (i = 0; i < numverts; ++i) { @@ -889,6 +883,12 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject->verts [i].impulse_count = 0; VECCOPY ( clmd->clothObject->verts [i].impulse, tnull ); } + + if (!cloth_build_springs (clmd->clothObject, dm) ) + { + modifier_setError (&(clmd->modifier), "Can't build springs."); + return 0; + } /* apply / set vertex groups */ if (clmd->sim_parms->vgroup_mass > 0) @@ -1044,7 +1044,6 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) unsigned int numverts = dm->getNumVerts ( dm ); unsigned int numedges = dm->getNumEdges ( dm ); unsigned int numfaces = dm->getNumFaces ( dm ); - MVert *mvert = CDDM_get_verts ( dm ); MEdge *medge = CDDM_get_edges ( dm ); MFace *mface = CDDM_get_faces ( dm ); unsigned int index2 = 0; // our second vertex index @@ -1081,7 +1080,7 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) { spring->ij = medge[i].v1; spring->kl = medge[i].v2; - VECSUB ( temp, mvert[spring->kl].co, mvert[spring->ij].co ); + VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; spring->flags = 0; @@ -1102,7 +1101,7 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) spring->ij = mface[i].v1; spring->kl = mface[i].v3; - VECSUB ( temp, mvert[spring->kl].co, mvert[spring->ij].co ); + VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_SHEAR; @@ -1119,7 +1118,7 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) spring->ij = mface[i].v2; spring->kl = mface[i].v4; - VECSUB ( temp, mvert[spring->kl].co, mvert[spring->ij].co ); + VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_SHEAR; @@ -1156,7 +1155,7 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) spring->ij = tspring2->ij; spring->kl = index2; - VECSUB ( temp, mvert[index2].co, mvert[tspring2->ij].co ); + VECSUB ( temp, cloth->x[index2], cloth->x[tspring2->ij] ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_BENDING; BLI_edgehash_insert ( edgehash, spring->ij, index2, NULL ); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index f562bd49fcc..21f1d7d0c1c 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1233,6 +1233,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, VECADD(s->f, s->f, damping_force); // Formula from Ascher / Boxman, Speeding up cloth simulation + // couldn't see any speedup // if((dt * (k*dt + 2 * clmd->sim_parms->Cdis * 0.01)) > 0.01 ) { dfdx_spring_type1(s->dfdx, dir,length,L,clmd->sim_parms->structural); @@ -1256,12 +1257,12 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, // DG: My formula to handle bending for the AIMEX scheme // multiply with 1000 because of numerical problems - // if( ((k*1000)*dt*dt) < -0.18 ) + if( ((k*1000.0)*dt*dt) < -0.18 ) { dfdx_spring_type2(s->dfdx, dir,length,L,clmd->sim_parms->bending, cb); clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; } - // printf("(dt*k*dt) ): %f, k: %f\n", (dt*dt*k*-1.0), k); + // printf("(dt*k*dt) ): %f, k: %f\n", (dt*dt*(1000.0*k)), k); } } } @@ -1279,8 +1280,8 @@ DO_INLINE int cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv); add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); } - else if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE)) - return 0; + // else if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE)) + // return 0; sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx); sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, s->dfdx); @@ -1466,8 +1467,8 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts); - // cg_filtered(dV, A, B, z, S); // conjugate gradient algorithm to solve Ax=b - cg_filtered_pre(dV, A, B, z, S, P, Pinv); + cg_filtered(dV, A, B, z, S); // conjugate gradient algorithm to solve Ax=b + // cg_filtered_pre(dV, A, B, z, S, P, Pinv); // advance velocities add_lfvector_lfvector(Vnew, lV, dV, numverts); From 4cb5470f82bf6139418ef0530407ff21aa3f2272 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 21 Nov 2007 08:13:00 +0000 Subject: [PATCH 055/101] WIP commit to be able to revert later (known bug: unstable without sse enabled - weird) --- source/blender/blenkernel/intern/implicit.c | 188 ++++++++++++++++---- 1 file changed, 157 insertions(+), 31 deletions(-) diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 21f1d7d0c1c..3f3b3a66253 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -271,7 +271,7 @@ DO_INLINE float dot_lfvector(lfVector *fLongVectorA, lfVector *fLongVectorB, uns unsigned int i = 0; float temp = 0.0; // schedule(guided, 2) -#pragma omp parallel for reduction(+: temp) schedule(static) +#pragma omp parallel for reduction(+: temp) private(i) schedule(static) for(i = 0; i < verts; i++) { temp += INPR(fLongVectorA[i], fLongVectorB[i]); @@ -287,8 +287,34 @@ DO_INLINE void add_lfvector_lfvector(lfVector *to, lfVector *fLongVectorA, lfVec { VECADD(to[i], fLongVectorA[i], fLongVectorB[i]); } - } +/* +#ifdef __SSE3__ +DO_INLINE void add_lfvector(lfVector *to, lfVector *fLongVectorA, unsigned int verts) { + __m128 v1, v2; + unsigned int i = 0; + + for(i = 0; i < verts; i++) + { + v1 = _mm_load_ps(to[i]); + v2 = _mm_load_ps(fLongVectorA[i]); + + v1 = _mm_add_ps(v1, v2); + + _mm_store_ps(to[i], v1); + } +} +#else */ +DO_INLINE void add_lfvector(lfVector *to, lfVector *fLongVectorA, unsigned int verts) { + unsigned int i = 0; + + for(i = 0; i < verts; i++) + { + VECADD(to[i], to[i], fLongVectorA[i]); + } +} +// #endif + /* A = B + C * float --> for big vector */ DO_INLINE void add_lfvector_lfvectorS(lfVector *to, lfVector *fLongVectorA, lfVector *fLongVectorB, float bS, unsigned int verts) { @@ -300,6 +326,76 @@ DO_INLINE void add_lfvector_lfvectorS(lfVector *to, lfVector *fLongVectorA, lfVe } } + +/* A = A + B * float --> for big vector */ +// tested +/* +#ifdef __SSE3__ +DO_INLINE void add_lfvectorS(lfVector *to, lfVector *fLongVectorA, float bS, unsigned int verts) { + __m128 v1, v2, v3; + unsigned int i = 0; + + for(i = 0; i < verts; i++) + { + v1 = _mm_load_ps(to[i]); + v2 = _mm_load_ps(fLongVectorA[i]); + v3 = _mm_set1_ps(bS); + + v2 = _mm_mul_ps(v2, v3); + v1 = _mm_add_ps(v1, v2); + + _mm_store_ps(to[i], v1); + } +} +#else */ +DO_INLINE void add_lfvectorS(lfVector *to, lfVector *fLongVectorA, float bS, unsigned int verts) { + unsigned int i = 0; + + for(i = 0; i < verts; i++) + { + VECADDS(to[i], to[i], fLongVectorA[i], bS); + } +} +// #endif + + +// tested +/* +#ifdef __SSE3__ +DO_INLINE float add_lfvectorS_dot(lfVector *to, lfVector *fLongVectorA, float bS, unsigned int verts) { + register __m128 v1, v2, v3, v4; + unsigned int i = 0; + float temp; + + v4 = _mm_setzero_ps(); +// #pragma omp parallel for reduction(+: v4) private(i, v1, v2, v3) schedule(static) + for(i = 0; i < verts; i++) + { + v1 = _mm_load_ps(to[i]); + v2 = _mm_load_ps(fLongVectorA[i]); + v3 = _mm_set1_ps(bS); + + v2 = _mm_mul_ps(v2, v3); + v1 = _mm_add_ps(v1, v2); + + _mm_stream_ps(to[i], v1); + + v4 = _mm_add_ps(v4, _mm_mul_ps(v1,v1)); + } + + v4 = _mm_hadd_ps(v4, v4); + v4 = _mm_hadd_ps(v4, v4); + _mm_store_ss(&temp, v4); + + return temp; +} +#else */ +DO_INLINE float add_lfvectorS_dot(lfVector *to, lfVector *fLongVectorA, float bS, unsigned int verts) { + add_lfvectorS(to, fLongVectorA, bS, verts); + return dot_lfvector(to, to, verts); +} +// #endif + /* A = B * float + C * float --> for big vector */ DO_INLINE void add_lfvectorS_lfvectorS(lfVector *to, lfVector *fLongVectorA, float aS, lfVector *fLongVectorB, float bS, unsigned int verts) { @@ -412,8 +508,9 @@ DO_INLINE void mul_fvector_fmatrix(float *to, float *from, float matrix[3][4]) /* 3x3 matrix multiplied by a vector */ /* STATUS: verified */ +/* #ifdef __SSE3__ -DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][4], float *from) { +DO_INLINE void mul_fmatrix_fvector(float to[4], float matrix[3][4], float from[4]) { __m128 v1, v2, v3, v4; v1 = _mm_load_ps(&matrix[0][0]); @@ -431,14 +528,18 @@ DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][4], float *from) { _mm_store_ps(to, v4); } -#else -DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][4], float *from) +#else */ +DO_INLINE void mul_fmatrix_fvector(float to[4], float matrix[3][4], float from[4]) { - to[0] = INPR(matrix[0],from); - to[1] = INPR(matrix[1],from); - to[2] = INPR(matrix[2],from); + float temp[3] = {0,0,0}; + + temp[0] = INPR(matrix[0],from); + temp[1] = INPR(matrix[1],from); + temp[2] = INPR(matrix[2],from); + + VECCOPY(to, temp); } -#endif +// #endif /* 3x3 matrix multiplied by a 3x3 matrix */ /* STATUS: verified */ @@ -538,9 +639,9 @@ DO_INLINE void mulsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float */ /* 3x3 matrix multiplied+added by a vector */ /* STATUS: verified */ - +/* #ifdef __SSE3__ -DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][4], float from[3]) { +DO_INLINE void muladd_fmatrix_fvector(float to[4], float matrix[3][4], float from[4]) { __m128 v1, v2, v3, v4; v1 = _mm_load_ps(&matrix[0][0]); @@ -561,8 +662,8 @@ DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][4], float fro _mm_store_ps(to, v4); } -#else -DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][4], float from[3]) +#else */ +DO_INLINE void muladd_fmatrix_fvector(float to[4], float matrix[3][4], float from[4]) { float temp[3] = { 0,0,0 }; @@ -572,7 +673,7 @@ DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][4], float fro VECADD(to, to, temp); } -#endif +// #endif /* 3x3 matrix multiplied+sub'ed by a vector */ /* @@ -660,27 +761,51 @@ DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) /* STATUS: verified */ void mul_bfmatrix_lfvector( lfVector *to, fmatrix3x3 *from, lfVector *fLongVector) { - unsigned int i = 0; - float *tflongvector; + unsigned int i = 0, numverts = from[0].vcount; + // lfVector *tflongvector = create_lfvector(numverts); float temp[4]={0,0,0,0}; - zero_lfvector(to, from[0].vcount); + zero_lfvector(to, numverts); + /* +#pragma omp parallel sections private(i) +{ +#pragma omp section + { + for(i = numverts; i < numverts+from[0].scount; i++) + { + muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); + + } + } +#pragma omp section + { + for(i = 0; i < numverts+from[0].scount; i++) + { + muladd_fmatrix_fvector(tflongvector[from[i].r], from[i].m, fLongVector[from[i].c]); + } + } +} + add_lfvector(to, tflongvector, numverts); + + del_lfvector(tflongvector); + */ + // alternative NON OpenMP code /* process diagonal elements */ + for(i = 0; i < from[0].vcount; i++) { mul_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); } - + /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */ - // TODO: pragma below is wrong, correct it! -// #pragma omp parallel for shared(to,from, fLongVector) private(i) for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) { muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); } + } /* SPARSE SYMMETRIC add big matrix with big matrix: A = B + C*/ @@ -860,7 +985,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) return 1; } -int implicit_free (ClothModifierData *clmd) +int implicit_free (ClothModifierData *clmd) { Implicit_Data *id; Cloth *cloth; @@ -1010,12 +1135,13 @@ int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatr // X = X + d*a; add_lfvector_lfvectorS(ldV, ldV, d, a, numverts); + + s_prev = s; // r = r - q*a; - sub_lfvector_lfvectorS(r, r, q, a, numverts); - - s_prev = s; + add_lfvector_lfvectorS(r, r, q, -a, numverts); s = dot_lfvector(r, r, numverts); + // s = add_lfvectorS_dot(r, q, -a, numverts); //d = r+d*(s/s_prev); add_lfvector_lfvectorS(d, r, d, (s/s_prev), numverts); @@ -1069,7 +1195,7 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma BuildPPinv(lA, P, Pinv); filter(dv, S); - add_lfvector_lfvector(dv, dv, z, numverts); + add_lfvector(dv, z, numverts); mul_bfmatrix_lfvector(r, lA, dv); sub_lfvector_lfvector(r, lB, r, numverts); @@ -1091,9 +1217,9 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma alpha = deltaNew / dot_lfvector(p, s, numverts); - add_lfvector_lfvectorS(dv, dv, p, alpha, numverts); + add_lfvectorS(dv, p, alpha, numverts); - sub_lfvector_lfvectorS(r, r, s, alpha, numverts); + add_lfvectorS(r, s, -alpha, numverts); mul_bfmatrix_lfvector(h, Pinv, r); filter(h, S); @@ -1257,7 +1383,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, // DG: My formula to handle bending for the AIMEX scheme // multiply with 1000 because of numerical problems - if( ((k*1000.0)*dt*dt) < -0.18 ) + // if( ((k*1000.0)*dt*dt) < -0.18 ) { dfdx_spring_type2(s->dfdx, dir,length,L,clmd->sim_parms->bending, cb); clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; @@ -1392,7 +1518,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec float speed[3] = {0.0f, 0.0f,0.0f}; float force[3]= {0.0f, 0.0f, 0.0f}; - #pragma omp parallel for private (i) shared(lF) + #pragma omp parallel for private (i) shared(lF) schedule(static) for(i = 0; i < cloth->numverts; i++) { float vertexnormal[3]={0,0,0}; @@ -1467,8 +1593,8 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts); - cg_filtered(dV, A, B, z, S); // conjugate gradient algorithm to solve Ax=b - // cg_filtered_pre(dV, A, B, z, S, P, Pinv); + // cg_filtered(dV, A, B, z, S); // conjugate gradient algorithm to solve Ax=b + cg_filtered_pre(dV, A, B, z, S, P, Pinv); // advance velocities add_lfvector_lfvector(Vnew, lV, dV, numverts); From 83c1dd78a630cef4ae6db341440f437f3d04f124 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 22 Nov 2007 17:02:37 +0000 Subject: [PATCH 056/101] Fixed numerical issues, hardened it again. --- source/blender/blenkernel/BKE_cloth.h | 16 +- source/blender/blenkernel/intern/cloth.c | 371 ++++---- source/blender/blenkernel/intern/implicit.c | 884 +++++++------------- 3 files changed, 507 insertions(+), 764 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index f3f566d2832..38cd54085f5 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -72,8 +72,8 @@ typedef struct ClothSpring { 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][4]; - float dfdv[3][4]; + float dfdx[3][3]; + float dfdv[3][3]; float f[3]; } ClothSpring; @@ -91,13 +91,13 @@ typedef struct Cloth { unsigned int numothersprings; unsigned int numspringssave; unsigned int old_solver_type; - float (*x)[4]; /* The current position of all vertices.*/ - float (*xold)[4]; /* The previous position of all vertices.*/ - float (*current_x)[4]; /* The TEMPORARY current position of all vertices.*/ - float (*current_xold)[4]; /* The TEMPORARY previous position of all vertices.*/ + float (*x)[3]; /* The current position of all vertices.*/ + float (*xold)[3]; /* The previous position of all vertices.*/ + float (*current_x)[3]; /* The TEMPORARY current position of all vertices.*/ + float (*current_xold)[3]; /* The TEMPORARY previous position of all vertices.*/ float (*v)[4]; /* the current velocity of all vertices */ - float (*current_v)[4]; - float (*xconst)[4]; + float (*current_v)[3]; + float (*xconst)[3]; } Cloth; /* goal defines */ diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index d0ab7ce4ffb..436a14d1d6c 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -90,9 +90,9 @@ double tval() } #else #include -static struct timeval _tstart, _tend; -static struct timezone tz; -void tstart ( void ) + static struct timeval _tstart, _tend; + static struct timezone tz; + void tstart ( void ) { gettimeofday ( &_tstart, &tz ); } @@ -133,11 +133,11 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v * ******************************************************************************/ /** -* cloth_init - creates a new cloth simulation. -* -* 1. create object -* 2. fill object with standard values or with the GUI settings if given -*/ + * cloth_init - creates a new cloth simulation. + * + * 1. create object + * 2. fill object with standard values or with the GUI settings if given + */ void cloth_init (ClothModifierData *clmd) { /* Initialize our new data structure to reasonable values. */ @@ -202,38 +202,38 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) for(i = 0; i < numfaces; i++) { - if(mface[i].v4) - numquads++; - else - numtris++; - } + if(mface[i].v4) + numquads++; + else + numtris++; +} result = CDDM_from_template(dm, numverts, 0, numtris + 2*numquads); if(!result) - return NULL; + return NULL; // do verts mvert2 = CDDM_get_verts(result); for(a=0; av1 = mface[a].v2; - mf->v2 = mface[a].v3; - mf->v3 = mface[a].v4; - } - else - { - mf->v1 = mface[a].v1; - mf->v2 = mface[a].v2; - mf->v3 = mface[a].v3; - } + if(mface[a].v4 && random==1) + { + mf->v1 = mface[a].v2; + mf->v2 = mface[a].v3; + mf->v3 = mface[a].v4; +} + else + { + mf->v1 = mface[a].v1; + mf->v2 = mface[a].v2; + mf->v3 = mface[a].v3; +} - mf->v4 = 0; - mf->flag |= ME_SMOOTH; + mf->v4 = 0; + mf->flag |= ME_SMOOTH; - test_index_face(mf, NULL, 0, 3); + test_index_face(mf, NULL, 0, 3); - if(mface[a].v4) - { - MFace *mf2; + if(mface[a].v4) + { + MFace *mf2; - i++; + i++; - mf2 = &mface2[i]; + mf2 = &mface2[i]; // DM_copy_face_data(dm, result, a, i, 1); // *mf2 = *inMF; - if(random==1) - { - mf2->v1 = mface[a].v1; - mf2->v2 = mface[a].v2; - mf2->v3 = mface[a].v4; - } - else - { - mf2->v1 = mface[a].v4; - mf2->v2 = mface[a].v1; - mf2->v3 = mface[a].v3; - } - mf2->v4 = 0; - mf2->flag |= ME_SMOOTH; + if(random==1) + { + mf2->v1 = mface[a].v1; + mf2->v2 = mface[a].v2; + mf2->v3 = mface[a].v4; +} + else + { + mf2->v1 = mface[a].v4; + mf2->v2 = mface[a].v1; + mf2->v3 = mface[a].v3; +} + mf2->v4 = 0; + mf2->flag |= ME_SMOOTH; - test_index_face(mf2, NULL, 0, 3); - } + test_index_face(mf2, NULL, 0, 3); +} - i++; - } + i++; +} CDDM_calc_edges(result); CDDM_calc_normals(result); @@ -330,43 +330,43 @@ DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) for(i = 0; i < numsprings; i++) { - if((springs[i].flags & CSPRING_FLAG_DEACTIVATE) - &&(!BLI_edgehash_haskey(edgehash, springs[i].ij, springs[i].kl))) - { - BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL); - BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL); - j++; - } - } + if((springs[i].flags & CSPRING_FLAG_DEACTIVATE) + &&(!BLI_edgehash_haskey(edgehash, springs[i].ij, springs[i].kl))) + { + BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL); + BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL); + j++; +} +} // printf("found %d tears\n", j); result = CDDM_from_template(dm, numverts, 0, numfaces); if(!result) - return NULL; + return NULL; // do verts mvert2 = CDDM_get_verts(result); for(a=0; av1 = mface[a].v1; - mf->v2 = mface[a].v2; - mf->v3 = mface[a].v3; - mf->v4 = mface[a].v4; + if((!BLI_edgehash_haskey(edgehash, mface[a].v1, mface[a].v2)) + &&(!BLI_edgehash_haskey(edgehash, mface[a].v2, mface[a].v3)) + &&(!BLI_edgehash_haskey(edgehash, mface[a].v3, mface[a].v4)) + &&(!BLI_edgehash_haskey(edgehash, mface[a].v4, mface[a].v1))) + { + mf->v1 = mface[a].v1; + mf->v2 = mface[a].v2; + mf->v3 = mface[a].v3; + mf->v4 = mface[a].v4; - test_index_face(mf, NULL, 0, 4); + test_index_face(mf, NULL, 0, 4); - i++; - } - } + i++; +} +} CDDM_lower_num_faces(result, i); CDDM_calc_edges(result); @@ -527,40 +527,40 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d /* if ( clmd->clothObject ) { - if ( clmd->sim_parms->cache ) - { - if ( current_time < clmd->sim_parms->firstframe ) - { - int frametime = cloth_cache_first_frame ( clmd ); - if ( cloth_cache_search_frame ( clmd, frametime ) ) - { - cloth_cache_get_frame ( clmd, frametime ); - cloth_to_object ( ob, result, clmd ); - } - return result; - } - else if ( current_time > clmd->sim_parms->lastframe ) - { - int frametime = cloth_cache_last_frame ( clmd ); - if ( cloth_cache_search_frame ( clmd, frametime ) ) - { - cloth_cache_get_frame ( clmd, frametime ); - cloth_to_object ( ob, result, clmd ); - } - return result; - } - else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed - { - if ( cloth_cache_search_frame ( clmd, framenr ) ) - { - cloth_cache_get_frame ( clmd, framenr ); - cloth_to_object ( ob, result, clmd ); - } - clmd->sim_parms->sim_time = current_time; - return result; - } - } - } + if ( clmd->sim_parms->cache ) + { + if ( current_time < clmd->sim_parms->firstframe ) + { + int frametime = cloth_cache_first_frame ( clmd ); + if ( cloth_cache_search_frame ( clmd, frametime ) ) + { + cloth_cache_get_frame ( clmd, frametime ); + cloth_to_object ( ob, result, clmd ); +} + return result; +} + else if ( current_time > clmd->sim_parms->lastframe ) + { + int frametime = cloth_cache_last_frame ( clmd ); + if ( cloth_cache_search_frame ( clmd, frametime ) ) + { + cloth_cache_get_frame ( clmd, frametime ); + cloth_to_object ( ob, result, clmd ); +} + return result; +} + else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed + { + if ( cloth_cache_search_frame ( clmd, framenr ) ) + { + cloth_cache_get_frame ( clmd, framenr ); + cloth_to_object ( ob, result, clmd ); +} + clmd->sim_parms->sim_time = current_time; + return result; +} +} +} */ if(deltaTime == 1.0f) @@ -737,10 +737,10 @@ void cloth_free_modifier (ClothModifierData *clmd) ******************************************************************************/ /** -* cloth_to_object - copies the deformed vertices to the object. -* -* This function is a modified version of the softbody.c:softbody_to_object() function. -**/ + * cloth_to_object - copies the deformed vertices to the object. + * + * This function is a modified version of the softbody.c:softbody_to_object() function. + **/ static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd) { unsigned int i = 0; @@ -765,9 +765,9 @@ static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *cl /** -* cloth_apply_vgroup - applies a vertex group as specified by type -* -**/ + * cloth_apply_vgroup - applies a vertex group as specified by type + * + **/ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup) { unsigned int i = 0; @@ -862,52 +862,51 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d /* create springs */ clmd->clothObject->springs = NULL; clmd->clothObject->numsprings = -1; + + /* set initial values */ + for (i = 0; i < numverts; ++i) + { + VECCOPY (clmd->clothObject->x[i], mvert[i].co); + Mat4MulVecfl(ob->obmat, clmd->clothObject->x[i]); + + clmd->clothObject->verts [i].mass = clmd->sim_parms->mass; + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + clmd->clothObject->verts [i].goal= clmd->sim_parms->defgoal; + else + clmd->clothObject->verts [i].goal= 0.0; + clmd->clothObject->verts [i].flags = 0; + VECCOPY(clmd->clothObject->xold[i], clmd->clothObject->x[i]); + VECCOPY(clmd->clothObject->xconst[i], clmd->clothObject->x[i]); + VECCOPY(clmd->clothObject->current_xold[i], clmd->clothObject->x[i]); + VecMulf(clmd->clothObject->v[i], 0.0); + + clmd->clothObject->verts [i].impulse_count = 0; + VECCOPY ( clmd->clothObject->verts [i].impulse, tnull ); + } - /* set initial values */ - for (i = 0; i < numverts; ++i) - { - VECCOPY (clmd->clothObject->x[i], mvert[i].co); - Mat4MulVecfl(ob->obmat, clmd->clothObject->x[i]); - - clmd->clothObject->verts [i].mass = clmd->sim_parms->mass; - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - clmd->clothObject->verts [i].goal= clmd->sim_parms->defgoal; - else - clmd->clothObject->verts [i].goal= 0.0; - clmd->clothObject->verts [i].flags = 0; - VECCOPY(clmd->clothObject->xold[i], clmd->clothObject->x[i]); - VECCOPY(clmd->clothObject->xconst[i], clmd->clothObject->x[i]); - VECCOPY(clmd->clothObject->current_xold[i], clmd->clothObject->x[i]); - VecMulf(clmd->clothObject->v[i], 0.0); - - clmd->clothObject->verts [i].impulse_count = 0; - VECCOPY ( clmd->clothObject->verts [i].impulse, tnull ); + if (!cloth_build_springs (clmd->clothObject, dm) ) + { + modifier_setError (&(clmd->modifier), "Can't build springs."); + return 0; + } + + /* apply / set vertex groups */ + if (clmd->sim_parms->vgroup_mass > 0) + cloth_apply_vgroup (clmd, olddm, clmd->sim_parms->vgroup_mass); + + /* init our solver */ + if (solvers [clmd->sim_parms->solver_type].init) + solvers [clmd->sim_parms->solver_type].init (ob, clmd); + + clmd->clothObject->tree = bvh_build_from_float3(CDDM_get_faces(dm), dm->getNumFaces(dm), clmd->clothObject->x, numverts, clmd->coll_parms->epsilon); + + clmd->clothObject->selftree = bvh_build_from_float3(NULL, 0, clmd->clothObject->x, numverts, clmd->coll_parms->selfepsilon); + + // save initial state + cloth_write_cache(ob, clmd, framenr-1); } - - if (!cloth_build_springs (clmd->clothObject, dm) ) - { - modifier_setError (&(clmd->modifier), "Can't build springs."); - return 0; - } - - /* apply / set vertex groups */ - if (clmd->sim_parms->vgroup_mass > 0) - cloth_apply_vgroup (clmd, olddm, clmd->sim_parms->vgroup_mass); - - /* init our solver */ - if (solvers [clmd->sim_parms->solver_type].init) - solvers [clmd->sim_parms->solver_type].init (ob, clmd); - - clmd->clothObject->tree = bvh_build_from_float4(CDDM_get_faces(dm), dm->getNumFaces(dm), clmd->clothObject->x, numverts, clmd->coll_parms->epsilon); - - clmd->clothObject->selftree = bvh_build_from_float4(NULL, 0, clmd->clothObject->x, numverts, clmd->coll_parms->selfepsilon); - - // save initial state - cloth_write_cache(ob, clmd, framenr-1); - } - - return 1; - default: return 0; // TODO - we do not support changing meshes + return 1; + default: return 0; // TODO - we do not support changing meshes } return 0; @@ -1119,15 +1118,15 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) spring->ij = mface[i].v2; spring->kl = mface[i].v4; VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] ); - spring->restlen = sqrt ( INPR ( temp, temp ) ); - spring->type = CLOTH_SPRING_TYPE_SHEAR; + spring->restlen = sqrt ( INPR ( temp, temp ) ); + spring->type = CLOTH_SPRING_TYPE_SHEAR; - BLI_linklist_append ( &edgelist[spring->ij], spring ); - BLI_linklist_append ( &edgelist[spring->kl], spring ); - shear_springs++; + BLI_linklist_append ( &edgelist[spring->ij], spring ); + BLI_linklist_append ( &edgelist[spring->kl], spring ); + shear_springs++; - node2 = BLI_linklist_append_fast ( &node->next, spring ); - node = node2; + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; } } @@ -1148,8 +1147,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) // check for existing spring // check also if startpoint is equal to endpoint if ( !BLI_edgehash_haskey ( edgehash, index2, tspring2->ij ) - && !BLI_edgehash_haskey ( edgehash, tspring2->ij, index2 ) - && ( index2!=tspring2->ij ) ) + && !BLI_edgehash_haskey ( edgehash, tspring2->ij, index2 ) + && ( index2!=tspring2->ij ) ) { spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 3f3b3a66253..6f8f96e58fb 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -63,14 +63,6 @@ #include "BKE_global.h" #include "BIF_editdeform.h" -#include "Bullet-C-Api.h" - -#ifdef __SSE3__ -#include -#include -#include -#endif - #ifdef _WIN32 #include static LARGE_INTEGER _itstart, _itend; @@ -91,14 +83,14 @@ void itend(void) double itval() { return ((double)_itend.QuadPart - - (double)_itstart.QuadPart)/((double)ifreq.QuadPart); + (double)_itstart.QuadPart)/((double)ifreq.QuadPart); } #else #include -static struct timeval _itstart, _itend; -static struct timezone itz; -void itstart(void) + static struct timeval _itstart, _itend; + static struct timezone itz; + void itstart(void) { gettimeofday(&_itstart, &itz); } @@ -122,39 +114,20 @@ struct Cloth; ///////////////////////////////////////// /* DEFINITIONS */ -#ifdef __GNUC__ -typedef float lfVector[4] __attribute__ ((aligned (16))); -#else -typedef __declspec(align(16)) lfVector[4]; -#endif - -#ifdef __GNUC__ +typedef float lfVector[3]; typedef struct fmatrix3x3 { - float m[3][4] __attribute__ ((aligned (16))); /* 3x3 matrix */ + float m[3][3]; /* 4x4 matrix */ unsigned int c,r; /* column and row number */ int pinned; /* is this vertex allowed to move? */ float n1,n2,n3; /* three normal vectors for collision constrains */ unsigned int vcount; /* vertex count */ unsigned int scount; /* spring count */ } fmatrix3x3; -#else -typedef struct fmatrix3x3 { - __declspec(align(16)) - float m[3][4]; /* 3x3 matrix */ - unsigned int c,r; /* column and row number */ - int pinned; /* is this vertex allowed to move? */ - float n1,n2,n3; /* three normal vectors for collision constrains */ - unsigned int vcount; /* vertex count */ - unsigned int scount; /* spring count */ -} fmatrix3x3; -#endif - /////////////////////////// // float[3] vector /////////////////////////// /* simple vector code */ - /* STATUS: verified */ DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar) { @@ -166,18 +139,13 @@ DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar) /* STATUS: verified */ DO_INLINE void cross_fvector(float to[3], float vectorA[3], float vectorB[3]) { - float temp[3]; - - temp[0] = vectorA[1] * vectorB[2] - vectorA[2] * vectorB[1]; - temp[1] = vectorA[2] * vectorB[0] - vectorA[0] * vectorB[2]; - temp[2] = vectorA[0] * vectorB[1] - vectorA[1] * vectorB[0]; - - VECCOPY(to, temp); + to[0] = vectorA[1] * vectorB[2] - vectorA[2] * vectorB[1]; + to[1] = vectorA[2] * vectorB[0] - vectorA[0] * vectorB[2]; + to[2] = vectorA[0] * vectorB[1] - vectorA[1] * vectorB[0]; } - /* simple v^T * v product ("outer product") */ /* STATUS: HAS TO BE verified (*should* work) */ -DO_INLINE void mul_fvectorT_fvector(float to[3][4], float vectorA[3], float vectorB[3]) +DO_INLINE void mul_fvectorT_fvector(float to[3][3], float vectorA[3], float vectorB[3]) { mul_fvector_S(to[0], vectorB, vectorA[0]); mul_fvector_S(to[1], vectorB, vectorA[1]); @@ -185,7 +153,7 @@ DO_INLINE void mul_fvectorT_fvector(float to[3][4], float vectorA[3], float vect } /* simple v^T * v product with scalar ("outer product") */ /* STATUS: HAS TO BE verified (*should* work) */ -DO_INLINE void mul_fvectorT_fvectorS(float to[3][4], float vectorA[3], float vectorB[3], float aS) +DO_INLINE void mul_fvectorT_fvectorS(float to[3][3], float vectorA[3], float vectorB[3], float aS) { mul_fvector_S(to[0], vectorB, vectorA[0]* aS); mul_fvector_S(to[1], vectorB, vectorA[1]* aS); @@ -227,7 +195,7 @@ DO_INLINE void del_lfvector(lfVector *fLongVector) } } /* copy long vector */ -DO_INLINE void cp_lfvector(lfVector *to, lfVector *from, unsigned int verts) +DO_INLINE void cp_lfvector(float (*to)[3], float (*from)[3], unsigned int verts) { memcpy(to, from, verts * sizeof(lfVector)); } @@ -241,12 +209,12 @@ DO_INLINE void init_lfvector(lfVector *fLongVector, float vector[3], unsigned in } } /* zero long vector with float[3] */ -DO_INLINE void zero_lfvector(lfVector *to, unsigned int verts) +DO_INLINE void zero_lfvector(float (*to)[3], unsigned int verts) { memset(to, 0.0f, verts * sizeof(lfVector)); } /* multiply long vector with scalar*/ -DO_INLINE void mul_lfvectorS(lfVector *to, lfVector *fLongVector, float scalar, unsigned int verts) +DO_INLINE void mul_lfvectorS(float (*to)[3], lfVector *fLongVector, float scalar, unsigned int verts) { unsigned int i = 0; @@ -257,7 +225,7 @@ DO_INLINE void mul_lfvectorS(lfVector *to, lfVector *fLongVector, float scalar, } /* multiply long vector with scalar*/ /* A -= B * float */ -DO_INLINE void submul_lfvectorS(lfVector *to, lfVector *fLongVector, float scalar, unsigned int verts) +DO_INLINE void submul_lfvectorS(float (*to)[3], lfVector *fLongVector, float scalar, unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -271,7 +239,7 @@ DO_INLINE float dot_lfvector(lfVector *fLongVectorA, lfVector *fLongVectorB, uns unsigned int i = 0; float temp = 0.0; // schedule(guided, 2) -#pragma omp parallel for reduction(+: temp) private(i) schedule(static) +#pragma omp parallel for reduction(+: temp) for(i = 0; i < verts; i++) { temp += INPR(fLongVectorA[i], fLongVectorB[i]); @@ -279,7 +247,7 @@ DO_INLINE float dot_lfvector(lfVector *fLongVectorA, lfVector *fLongVectorB, uns return temp; } /* A = B + C --> for big vector */ -DO_INLINE void add_lfvector_lfvector(lfVector *to, lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) +DO_INLINE void add_lfvector_lfvector(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) { unsigned int i = 0; @@ -287,36 +255,10 @@ DO_INLINE void add_lfvector_lfvector(lfVector *to, lfVector *fLongVectorA, lfVec { VECADD(to[i], fLongVectorA[i], fLongVectorB[i]); } -} -/* -#ifdef __SSE3__ -DO_INLINE void add_lfvector(lfVector *to, lfVector *fLongVectorA, unsigned int verts) { - __m128 v1, v2; - unsigned int i = 0; - - for(i = 0; i < verts; i++) - { - v1 = _mm_load_ps(to[i]); - v2 = _mm_load_ps(fLongVectorA[i]); - - v1 = _mm_add_ps(v1, v2); - - _mm_store_ps(to[i], v1); - } -} -#else */ -DO_INLINE void add_lfvector(lfVector *to, lfVector *fLongVectorA, unsigned int verts) { - unsigned int i = 0; - for(i = 0; i < verts; i++) - { - VECADD(to[i], to[i], fLongVectorA[i]); - } } -// #endif - /* A = B + C * float --> for big vector */ -DO_INLINE void add_lfvector_lfvectorS(lfVector *to, lfVector *fLongVectorA, lfVector *fLongVectorB, float bS, unsigned int verts) +DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, float bS, unsigned int verts) { unsigned int i = 0; @@ -326,78 +268,8 @@ DO_INLINE void add_lfvector_lfvectorS(lfVector *to, lfVector *fLongVectorA, lfVe } } - -/* A = A + B * float --> for big vector */ -// tested -/* -#ifdef __SSE3__ -DO_INLINE void add_lfvectorS(lfVector *to, lfVector *fLongVectorA, float bS, unsigned int verts) { - __m128 v1, v2, v3; - unsigned int i = 0; - - for(i = 0; i < verts; i++) - { - v1 = _mm_load_ps(to[i]); - v2 = _mm_load_ps(fLongVectorA[i]); - v3 = _mm_set1_ps(bS); - - v2 = _mm_mul_ps(v2, v3); - v1 = _mm_add_ps(v1, v2); - - _mm_store_ps(to[i], v1); - } -} -#else */ -DO_INLINE void add_lfvectorS(lfVector *to, lfVector *fLongVectorA, float bS, unsigned int verts) { - unsigned int i = 0; - - for(i = 0; i < verts; i++) - { - VECADDS(to[i], to[i], fLongVectorA[i], bS); - } -} -// #endif - - -// tested -/* -#ifdef __SSE3__ -DO_INLINE float add_lfvectorS_dot(lfVector *to, lfVector *fLongVectorA, float bS, unsigned int verts) { - register __m128 v1, v2, v3, v4; - unsigned int i = 0; - float temp; - - v4 = _mm_setzero_ps(); -// #pragma omp parallel for reduction(+: v4) private(i, v1, v2, v3) schedule(static) - for(i = 0; i < verts; i++) - { - v1 = _mm_load_ps(to[i]); - v2 = _mm_load_ps(fLongVectorA[i]); - v3 = _mm_set1_ps(bS); - - v2 = _mm_mul_ps(v2, v3); - v1 = _mm_add_ps(v1, v2); - - _mm_stream_ps(to[i], v1); - - v4 = _mm_add_ps(v4, _mm_mul_ps(v1,v1)); - } - - v4 = _mm_hadd_ps(v4, v4); - v4 = _mm_hadd_ps(v4, v4); - _mm_store_ss(&temp, v4); - - return temp; -} -#else */ -DO_INLINE float add_lfvectorS_dot(lfVector *to, lfVector *fLongVectorA, float bS, unsigned int verts) { - add_lfvectorS(to, fLongVectorA, bS, verts); - return dot_lfvector(to, to, verts); -} -// #endif - /* A = B * float + C * float --> for big vector */ -DO_INLINE void add_lfvectorS_lfvectorS(lfVector *to, lfVector *fLongVectorA, float aS, lfVector *fLongVectorB, float bS, unsigned int verts) +DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], lfVector *fLongVectorA, float aS, lfVector *fLongVectorB, float bS, unsigned int verts) { unsigned int i = 0; @@ -407,7 +279,7 @@ DO_INLINE void add_lfvectorS_lfvectorS(lfVector *to, lfVector *fLongVectorA, flo } } /* A = B - C * float --> for big vector */ -DO_INLINE void sub_lfvector_lfvectorS(lfVector *to, lfVector *fLongVectorA, lfVector *fLongVectorB, float bS, unsigned int verts) +DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, float bS, unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -417,7 +289,7 @@ DO_INLINE void sub_lfvector_lfvectorS(lfVector *to, lfVector *fLongVectorA, lfVe } /* A = B - C --> for big vector */ -DO_INLINE void sub_lfvector_lfvector(lfVector *to, lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) +DO_INLINE void sub_lfvector_lfvector(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) { unsigned int i = 0; @@ -428,32 +300,30 @@ DO_INLINE void sub_lfvector_lfvector(lfVector *to, lfVector *fLongVectorA, lfVec } /////////////////////////// -// 3x3 matrix +// 4x4 matrix /////////////////////////// -/* printf 3x3 matrix on console: for debug output */ -void print_fmatrix(float m3[3][4]) +/* printf 4x4 matrix on console: for debug output */ +void print_fmatrix(float m3[3][3]) { printf("%f\t%f\t%f\n",m3[0][0],m3[0][1],m3[0][2]); printf("%f\t%f\t%f\n",m3[1][0],m3[1][1],m3[1][2]); printf("%f\t%f\t%f\n\n",m3[2][0],m3[2][1],m3[2][2]); } -/* copy 3x3 matrix */ -DO_INLINE void cp_fmatrix(float to[3][4], float from[3][4]) +/* copy 4x4 matrix */ +DO_INLINE void cp_fmatrix(float to[3][3], float from[3][3]) { - memcpy(to, from, sizeof (float) * 12); - /* + // memcpy(to, from, sizeof (float) * 9); VECCOPY(to[0], from[0]); VECCOPY(to[1], from[1]); VECCOPY(to[2], from[2]); - */ } -/* calculate determinant of 3x3 matrix */ -DO_INLINE float det_fmatrix(float m[3][4]) +/* calculate determinant of 4x4 matrix */ +DO_INLINE float det_fmatrix(float m[3][3]) { return m[0][0]*m[1][1]*m[2][2] + m[1][0]*m[2][1]*m[0][2] + m[0][1]*m[1][2]*m[2][0] - -m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2]; + -m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2]; } -DO_INLINE void inverse_fmatrix(float to[3][4], float from[3][4]) +DO_INLINE void inverse_fmatrix(float to[3][3], float from[3][3]) { unsigned int i, j; float d; @@ -484,115 +354,84 @@ DO_INLINE void inverse_fmatrix(float to[3][4], float from[3][4]) } -/* 3x3 matrix multiplied by a scalar */ +/* 4x4 matrix multiplied by a scalar */ /* STATUS: verified */ -DO_INLINE void mul_fmatrix_S(float matrix[3][4], float scalar) +DO_INLINE void mul_fmatrix_S(float matrix[3][3], float scalar) { mul_fvector_S(matrix[0], matrix[0],scalar); mul_fvector_S(matrix[1], matrix[1],scalar); mul_fvector_S(matrix[2], matrix[2],scalar); } -/* a vector multiplied by a 3x3 matrix */ +/* a vector multiplied by a 4x4 matrix */ /* STATUS: verified */ -DO_INLINE void mul_fvector_fmatrix(float *to, float *from, float matrix[3][4]) +DO_INLINE void mul_fvector_fmatrix(float *to, float *from, float matrix[3][3]) { - float temp[3]; - - VECCOPY(temp, from); - - to[0] = matrix[0][0]*temp[0] + matrix[1][0]*temp[1] + matrix[2][0]*temp[2]; - to[1] = matrix[0][1]*temp[0] + matrix[1][1]*temp[1] + matrix[2][1]*temp[2]; - to[2] = matrix[0][2]*temp[0] + matrix[1][2]*temp[1] + matrix[2][2]*temp[2]; + to[0] = matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2]; + to[1] = matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2]; + to[2] = matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2]; } -/* 3x3 matrix multiplied by a vector */ +/* 4x4 matrix multiplied by a vector */ /* STATUS: verified */ -/* -#ifdef __SSE3__ -DO_INLINE void mul_fmatrix_fvector(float to[4], float matrix[3][4], float from[4]) { - __m128 v1, v2, v3, v4; - - v1 = _mm_load_ps(&matrix[0][0]); - v2 = _mm_load_ps(&matrix[1][0]); - v3 = _mm_load_ps(&matrix[2][0]); - v4 = _mm_load_ps(from); - - // stuff - v1 = _mm_mul_ps(v1, v4); - v2 = _mm_mul_ps(v2, v4); - v3 = _mm_mul_ps(v3, v4); - v1 = _mm_hadd_ps(v1, v2); - v3 = _mm_hadd_ps(v3, _mm_setzero_ps()); - v4 = _mm_hadd_ps(v1, v3); - - _mm_store_ps(to, v4); -} -#else */ -DO_INLINE void mul_fmatrix_fvector(float to[4], float matrix[3][4], float from[4]) +DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][3], float *from) { - float temp[3] = {0,0,0}; - - temp[0] = INPR(matrix[0],from); - temp[1] = INPR(matrix[1],from); - temp[2] = INPR(matrix[2],from); - - VECCOPY(to, temp); + to[0] = INPR(matrix[0],from); + to[1] = INPR(matrix[1],from); + to[2] = INPR(matrix[2],from); } -// #endif - -/* 3x3 matrix multiplied by a 3x3 matrix */ +/* 4x4 matrix multiplied by a 4x4 matrix */ /* STATUS: verified */ -DO_INLINE void mul_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) +DO_INLINE void mul_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) { mul_fvector_fmatrix(to[0], matrixA[0],matrixB); mul_fvector_fmatrix(to[1], matrixA[1],matrixB); mul_fvector_fmatrix(to[2], matrixA[2],matrixB); } -/* 3x3 matrix addition with 3x3 matrix */ -DO_INLINE void add_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) +/* 4x4 matrix addition with 4x4 matrix */ +DO_INLINE void add_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) { VECADD(to[0], matrixA[0], matrixB[0]); VECADD(to[1], matrixA[1], matrixB[1]); VECADD(to[2], matrixA[2], matrixB[2]); } -/* 3x3 matrix add-addition with 3x3 matrix */ -DO_INLINE void addadd_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) +/* 4x4 matrix add-addition with 4x4 matrix */ +DO_INLINE void addadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) { VECADDADD(to[0], matrixA[0], matrixB[0]); VECADDADD(to[1], matrixA[1], matrixB[1]); VECADDADD(to[2], matrixA[2], matrixB[2]); } -/* 3x3 matrix sub-addition with 3x3 matrix */ -DO_INLINE void addsub_fmatrixS_fmatrixS(float to[3][4], float matrixA[3][4], float aS, float matrixB[3][4], float bS) +/* 4x4 matrix sub-addition with 4x4 matrix */ +DO_INLINE void addsub_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS) { VECADDSUBSS(to[0], matrixA[0], aS, matrixB[0], bS); VECADDSUBSS(to[1], matrixA[1], aS, matrixB[1], bS); VECADDSUBSS(to[2], matrixA[2], aS, matrixB[2], bS); } -/* A -= B + C (3x3 matrix sub-addition with 3x3 matrix) */ -DO_INLINE void subadd_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) +/* A -= B + C (4x4 matrix sub-addition with 4x4 matrix) */ +DO_INLINE void subadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) { VECSUBADD(to[0], matrixA[0], matrixB[0]); VECSUBADD(to[1], matrixA[1], matrixB[1]); VECSUBADD(to[2], matrixA[2], matrixB[2]); } -/* A -= B*x + C*y (3x3 matrix sub-addition with 3x3 matrix) */ -DO_INLINE void subadd_fmatrixS_fmatrixS(float to[3][4], float matrixA[3][4], float aS, float matrixB[3][4], float bS) +/* A -= B*x + C*y (4x4 matrix sub-addition with 4x4 matrix) */ +DO_INLINE void subadd_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS) { VECSUBADDSS(to[0], matrixA[0], aS, matrixB[0], bS); VECSUBADDSS(to[1], matrixA[1], aS, matrixB[1], bS); VECSUBADDSS(to[2], matrixA[2], aS, matrixB[2], bS); } -/* A = B - C (3x3 matrix subtraction with 3x3 matrix) */ -DO_INLINE void sub_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) +/* A = B - C (4x4 matrix subtraction with 4x4 matrix) */ +DO_INLINE void sub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) { VECSUB(to[0], matrixA[0], matrixB[0]); VECSUB(to[1], matrixA[1], matrixB[1]); VECSUB(to[2], matrixA[2], matrixB[2]); } -/* A += B - C (3x3 matrix add-subtraction with 3x3 matrix) */ -DO_INLINE void addsub_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float matrixB[3][4]) +/* A += B - C (4x4 matrix add-subtraction with 4x4 matrix) */ +DO_INLINE void addsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) { VECADDSUB(to[0], matrixA[0], matrixB[0]); VECADDSUB(to[1], matrixA[1], matrixB[1]); @@ -601,93 +440,53 @@ DO_INLINE void addsub_fmatrix_fmatrix(float to[3][4], float matrixA[3][4], float ///////////////////////////////////////////////////////////////// // special functions ///////////////////////////////////////////////////////////////// -/* a vector multiplied and added to/by a 3x3 matrix */ -/* +/* a vector multiplied and added to/by a 4x4 matrix */ DO_INLINE void muladd_fvector_fmatrix(float to[3], float from[3], float matrix[3][3]) { to[0] += matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2]; to[1] += matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2]; to[2] += matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2]; } -*/ -/* 3x3 matrix multiplied and added to/by a 3x3 matrix and added to another 3x3 matrix */ -/* +/* 4x4 matrix multiplied and added to/by a 4x4 matrix and added to another 4x4 matrix */ DO_INLINE void muladd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) { muladd_fvector_fmatrix(to[0], matrixA[0],matrixB); muladd_fvector_fmatrix(to[1], matrixA[1],matrixB); muladd_fvector_fmatrix(to[2], matrixA[2],matrixB); } -*/ -/* a vector multiplied and sub'd to/by a 3x3 matrix */ -/* +/* a vector multiplied and sub'd to/by a 4x4 matrix */ DO_INLINE void mulsub_fvector_fmatrix(float to[3], float from[3], float matrix[3][3]) { to[0] -= matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2]; to[1] -= matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2]; to[2] -= matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2]; } -*/ -/* 3x3 matrix multiplied and sub'd to/by a 3x3 matrix and added to another 3x3 matrix */ -/* +/* 4x4 matrix multiplied and sub'd to/by a 4x4 matrix and added to another 4x4 matrix */ DO_INLINE void mulsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) { mulsub_fvector_fmatrix(to[0], matrixA[0],matrixB); mulsub_fvector_fmatrix(to[1], matrixA[1],matrixB); mulsub_fvector_fmatrix(to[2], matrixA[2],matrixB); } -*/ -/* 3x3 matrix multiplied+added by a vector */ +/* 4x4 matrix multiplied+added by a vector */ /* STATUS: verified */ -/* -#ifdef __SSE3__ -DO_INLINE void muladd_fmatrix_fvector(float to[4], float matrix[3][4], float from[4]) { - __m128 v1, v2, v3, v4; - - v1 = _mm_load_ps(&matrix[0][0]); - v2 = _mm_load_ps(&matrix[1][0]); - v3 = _mm_load_ps(&matrix[2][0]); - v4 = _mm_load_ps(from); - - // stuff - v1 = _mm_mul_ps(v1, v4); - v2 = _mm_mul_ps(v2, v4); - v3 = _mm_mul_ps(v3, v4); - v1 = _mm_hadd_ps(v1, v2); - v3 = _mm_hadd_ps(v3, _mm_setzero_ps()); - v1 = _mm_hadd_ps(v1, v3); - - v4 = _mm_load_ps(to); - v4 = _mm_add_ps(v4,v1); - - _mm_store_ps(to, v4); -} -#else */ -DO_INLINE void muladd_fmatrix_fvector(float to[4], float matrix[3][4], float from[4]) +DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][3], float from[3]) { - float temp[3] = { 0,0,0 }; - - temp[0] = INPR(matrix[0],from); - temp[1] = INPR(matrix[1],from); - temp[2] = INPR(matrix[2],from); - - VECADD(to, to, temp); + to[0] += INPR(matrix[0],from); + to[1] += INPR(matrix[1],from); + to[2] += INPR(matrix[2],from); } -// #endif - -/* 3x3 matrix multiplied+sub'ed by a vector */ -/* +/* 4x4 matrix multiplied+sub'ed by a vector */ DO_INLINE void mulsub_fmatrix_fvector(float to[3], float matrix[3][3], float from[3]) { to[0] -= INPR(matrix[0],from); to[1] -= INPR(matrix[1],from); to[2] -= INPR(matrix[2],from); } -*/ ///////////////////////////////////////////////////////////////// /////////////////////////// -// SPARSE SYMMETRIC big matrix with 3x3 matrix entries +// SPARSE SYMMETRIC big matrix with 4x4 matrix entries /////////////////////////// /* printf a big matrix on console: for debug output */ void print_bfmatrix(fmatrix3x3 *m3) @@ -724,10 +523,10 @@ DO_INLINE void cp_bfmatrix(fmatrix3x3 *to, fmatrix3x3 *from) } /* init the diagonal of big matrix */ // slow in parallel -DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][4]) +DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][3]) { unsigned int i,j; - float tmatrix[3][4] = {{0,0,0,0},{0,0,0,0},{0,0,0,0}}; + float tmatrix[3][3] = {{0,0,0},{0,0,0},{0,0,0}}; for(i = 0; i < matrix[0].vcount; i++) { @@ -739,7 +538,7 @@ DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][4]) } } /* init big matrix */ -DO_INLINE void init_bfmatrix(fmatrix3x3 *matrix, float m3[3][4]) +DO_INLINE void init_bfmatrix(fmatrix3x3 *matrix, float m3[3][3]) { unsigned int i; @@ -759,55 +558,36 @@ DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) } /* SPARSE SYMMETRIC multiply big matrix with long vector*/ /* STATUS: verified */ -void mul_bfmatrix_lfvector( lfVector *to, fmatrix3x3 *from, lfVector *fLongVector) +DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector) { - unsigned int i = 0, numverts = from[0].vcount; - // lfVector *tflongvector = create_lfvector(numverts); - float temp[4]={0,0,0,0}; + unsigned int i = 0; + lfVector *temp = create_lfvector(from[0].vcount); - zero_lfvector(to, numverts); - /* -#pragma omp parallel sections private(i) -{ -#pragma omp section - { - for(i = numverts; i < numverts+from[0].scount; i++) - { - muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); - - } - } -#pragma omp section - { - for(i = 0; i < numverts+from[0].scount; i++) - { - muladd_fmatrix_fvector(tflongvector[from[i].r], from[i].m, fLongVector[from[i].c]); - } - } -} - - add_lfvector(to, tflongvector, numverts); - - del_lfvector(tflongvector); - */ - // alternative NON OpenMP code - /* process diagonal elements */ - - for(i = 0; i < from[0].vcount; i++) - { - mul_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); - } - - /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */ - - for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) - { - muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); - muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); - } - -} + zero_lfvector(to, from[0].vcount); +#pragma omp parallel sections private(i) + { +#pragma omp section + { + for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) + { + muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); + } + } +#pragma omp section + { + for(i = 0; i < from[0].vcount+from[0].scount; i++) + { + muladd_fmatrix_fvector(temp[from[i].r], from[i].m, fLongVector[from[i].c]); + } + } + } + add_lfvector_lfvector(to, to, temp, from[0].vcount); + + del_lfvector(temp); + + +} /* SPARSE SYMMETRIC add big matrix with big matrix: A = B + C*/ DO_INLINE void add_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) { @@ -898,8 +678,8 @@ DO_INLINE void subadd_bfmatrixS_bfmatrixS( fmatrix3x3 *to, fmatrix3x3 *from, flo /////////////////////////////////////////////////////////////////// // simulator start /////////////////////////////////////////////////////////////////// -static float I[3][4] = {{1,0,0,0},{0,1,0,0},{0,0,1,0}}; -static float ZERO[3][4] = {{0,0,0,0},{0,0,0,0},{0,0,0,0}}; +static float I[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; +static float ZERO[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}; typedef struct Implicit_Data { lfVector *X, *V, *Xnew, *Vnew, *F, *B, *dV, *z; @@ -941,7 +721,6 @@ int implicit_init (Object *ob, ClothModifierData *clmd) id->F = create_lfvector(cloth->numverts); id->B = create_lfvector(cloth->numverts); id->dV = create_lfvector(cloth->numverts); - zero_lfvector(id->dV, cloth->numverts); id->z = create_lfvector(cloth->numverts); for(i=0;inumverts;i++) @@ -971,7 +750,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) // dFdV_start[i].c = big_I[i].c = big_zero[i].c = id->A[i+cloth->numverts].c = id->dFdV[i+cloth->numverts].c = id->dFdX[i+cloth->numverts].c = - id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = spring->kl; + id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = spring->kl; spring->matrix_index = i + cloth->numverts; @@ -985,7 +764,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) return 1; } -int implicit_free (ClothModifierData *clmd) +int implicit_free (ClothModifierData *clmd) { Implicit_Data *id; Cloth *cloth; @@ -1096,7 +875,7 @@ DO_INLINE void filter(lfVector *V, fmatrix3x3 *S) } } -int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) +int cg_filtered(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) { // Solves for unknown X in equation AX=B unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100; @@ -1108,22 +887,24 @@ int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatr d = create_lfvector(numverts); tmp = create_lfvector(numverts); r = create_lfvector(numverts); - - // zero_lfvector(ldV, numverts); - filter(ldV, S); - add_lfvector_lfvector(ldV, ldV, z, numverts); + + // zero_lfvector(dv, CLOTHPARTICLES); + filter(dv, S); + + add_lfvector_lfvector(dv, dv, z, numverts); // r = B - Mul(tmp,A,X); // just use B if X known to be zero - mul_bfmatrix_lfvector(r, lA, ldV); - sub_lfvector_lfvector(r, lB, r, numverts); - filter(r, S); + cp_lfvector(r, lB, numverts); + mul_bfmatrix_lfvector(tmp, lA, dv); + sub_lfvector_lfvector(r, r, tmp, numverts); + + filter(r,S); cp_lfvector(d, r, numverts); s = dot_lfvector(r, r, numverts); - starget = s * conjgrad_epsilon; - - // itstart(); + starget = s * sqrt(conjgrad_epsilon); + while((s>starget && conjgrad_loopcount < conjgrad_looplimit)) { // Mul(q,A,d); // q = A*d; @@ -1134,14 +915,13 @@ int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatr a = s/dot_lfvector(d, q, numverts); // X = X + d*a; - add_lfvector_lfvectorS(ldV, ldV, d, a, numverts); - - s_prev = s; + add_lfvector_lfvectorS(dv, dv, d, a, numverts); // r = r - q*a; - add_lfvector_lfvectorS(r, r, q, -a, numverts); + sub_lfvector_lfvectorS(r, r, q, a, numverts); + + s_prev = s; s = dot_lfvector(r, r, numverts); - // s = add_lfvectorS_dot(r, q, -a, numverts); //d = r+d*(s/s_prev); add_lfvector_lfvectorS(d, r, d, (s/s_prev), numverts); @@ -1195,7 +975,7 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma BuildPPinv(lA, P, Pinv); filter(dv, S); - add_lfvector(dv, z, numverts); + add_lfvector_lfvector(dv, dv, z, numverts); mul_bfmatrix_lfvector(r, lA, dv); sub_lfvector_lfvector(r, lB, r, numverts); @@ -1204,11 +984,13 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma mul_bfmatrix_lfvector(p, Pinv, r); filter(p, S); - deltaNew = delta0 = dot_lfvector(r, p, numverts); + deltaNew = dot_lfvector(r, p, numverts); + + delta0 = deltaNew * sqrt(conjgrad_epsilon); // itstart(); - while ((deltaNew > (conjgrad_epsilon*delta0)) && (iterations < conjgrad_looplimit)) + while ((deltaNew > delta0) && (iterations < conjgrad_looplimit)) { iterations++; @@ -1217,9 +999,9 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma alpha = deltaNew / dot_lfvector(p, s, numverts); - add_lfvectorS(dv, p, alpha, numverts); + add_lfvector_lfvectorS(dv, dv, p, alpha, numverts); - add_lfvectorS(r, s, -alpha, numverts); + add_lfvector_lfvectorS(r, r, s, -alpha, numverts); mul_bfmatrix_lfvector(h, Pinv, r); filter(h, S); @@ -1247,11 +1029,11 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma } // outer product is NOT cross product!!! -DO_INLINE void dfdx_spring_type1(float to[3][4], float dir[3],float length,float L,float k) +DO_INLINE void dfdx_spring_type1(float to[3][3], float dir[3],float length,float L,float k) { // dir is unit length direction, rest is spring's restlength, k is spring constant. // return (outerprod(dir,dir)*k + (I - outerprod(dir,dir))*(k - ((k*L)/length))); - float temp[3][4]; + float temp[3][3]; mul_fvectorT_fvector(temp, dir, dir); sub_fmatrix_fmatrix(to, I, temp); mul_fmatrix_S(to, k* (1.0f-(L/length))); @@ -1259,20 +1041,20 @@ DO_INLINE void dfdx_spring_type1(float to[3][4], float dir[3],float length,float add_fmatrix_fmatrix(to, temp, to); } -DO_INLINE void dfdx_spring_type2(float to[3][4], float dir[3],float length,float L,float k, float cb) +DO_INLINE void dfdx_spring_type2(float to[3][3], float dir[3],float length,float L,float k, float cb) { // return outerprod(dir,dir)*fbstar_jacobi(length, L, k, cb); mul_fvectorT_fvectorS(to, dir, dir, fbstar_jacobi(length, L, k, cb)); } -DO_INLINE void dfdv_damp(float to[3][4], float dir[3], float damping) +DO_INLINE void dfdv_damp(float to[3][3], float dir[3], float damping) { // derivative of force wrt velocity. // return outerprod(dir,dir) * damping; mul_fvectorT_fvectorS(to, dir, dir, damping); } -DO_INLINE void dfdx_spring(float to[3][4], float dir[3],float length,float L,float k) +DO_INLINE void dfdx_spring(float to[3][3], float dir[3],float length,float L,float k) { // dir is unit length direction, rest is spring's restlength, k is spring constant. //return ( (I-outerprod(dir,dir))*Min(1.0f,rest/length) - I) * -k; @@ -1283,7 +1065,7 @@ DO_INLINE void dfdx_spring(float to[3][4], float dir[3],float length,float L,fl mul_fmatrix_S(to, -k); } -DO_INLINE void dfdx_damp(float to[3][4], float dir[3],float length,const float vel[3],float rest,float damping) +DO_INLINE void dfdx_damp(float to[3][3], float dir[3],float length,const float vel[3],float rest,float damping) { // inner spring damping vel is the relative velocity of the endpoints. // return (I-outerprod(dir,dir)) * (-damping * -(dot(dir,vel)/Max(length,rest))); @@ -1293,12 +1075,12 @@ DO_INLINE void dfdx_damp(float to[3][4], float dir[3],float length,const float } -DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt) +DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) { float extent[3]; float length = 0; float dir[3] = {0,0,0}; - float vel[3] = {0,0,0}; + float vel[3]; float k = 0.0f; float L = s->restlen; float cb = clmd->sim_parms->structural; @@ -1307,7 +1089,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float stretch_force[3] = {0,0,0}; float bending_force[3] = {0,0,0}; float damping_force[3] = {0,0,0}; - float nulldfdx[3][4]={ {0,0,0,0}, {0,0,0,0}, {0,0,0,0}}; + float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); @@ -1325,13 +1107,13 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, /* if(length>L) { - if((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) - && ((((length-L)*100.0f/L) > clmd->sim_parms->maxspringlen))) // cut spring! - { - s->flags |= CSPRING_FLAG_DEACTIVATE; - return; - } - } + if((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) + && ((((length-L)*100.0f/L) > clmd->sim_parms->maxspringlen))) // cut spring! + { + s->flags |= CSPRING_FLAG_DEACTIVATE; + return; + } + } */ mul_fvector_S(dir, extent, 1.0f/length); } @@ -1348,24 +1130,19 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, { s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = (clmd->sim_parms->structural*(length-L)); + k = clmd->sim_parms->structural; - mul_fvector_S(stretch_force, dir, k); + mul_fvector_S(stretch_force, dir, (k*(length-L))); VECADD(s->f, s->f, stretch_force); // Ascher & Boxman, p.21: Damping only during elonglation - mul_fvector_S(damping_force, extent, clmd->sim_parms->Cdis * 0.01 * ((INPR(vel,extent)/length))); + mul_fvector_S(damping_force, extent, clmd->sim_parms->Cdis * ((INPR(vel,extent)/length))); VECADD(s->f, s->f, damping_force); - - // Formula from Ascher / Boxman, Speeding up cloth simulation - // couldn't see any speedup - // if((dt * (k*dt + 2 * clmd->sim_parms->Cdis * 0.01)) > 0.01 ) - { - dfdx_spring_type1(s->dfdx, dir,length,L,clmd->sim_parms->structural); - dfdv_damp(s->dfdv, dir,clmd->sim_parms->Cdis * 0.01); - } - // printf("(dt*k*dt) ): %f, k: %f\n", (dt * (k*dt + 2 * clmd->sim_parms->Cdis * 0.01) ), k); + + dfdx_spring_type1(s->dfdx, dir,length,L,k); + + dfdv_damp(s->dfdv, dir,clmd->sim_parms->Cdis); } } else // calculate force of bending springs @@ -1376,19 +1153,17 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = fbstar(length, L, clmd->sim_parms->bending, cb); + k = clmd->sim_parms->bending; - mul_fvector_S(bending_force, dir, k); + mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); VECADD(s->f, s->f, bending_force); - // DG: My formula to handle bending for the AIMEX scheme - // multiply with 1000 because of numerical problems - // if( ((k*1000.0)*dt*dt) < -0.18 ) + if(INPR(bending_force,bending_force) > 0.13*0.13) { - dfdx_spring_type2(s->dfdx, dir,length,L,clmd->sim_parms->bending, cb); clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; } - // printf("(dt*k*dt) ): %f, k: %f\n", (dt*dt*(1000.0*k)), k); + + dfdx_spring_type2(s->dfdx, dir,length,L,k, cb); } } } @@ -1406,8 +1181,8 @@ DO_INLINE int cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv); add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); } - // else if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE)) - // return 0; + else if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE)) + return 0; sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx); sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, s->dfdx); @@ -1459,14 +1234,14 @@ DO_INLINE void calc_triangle_force(ClothModifierData *clmd, MFace mface, lfVecto } -void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, float dt) +void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time) { /* Collect forces and derivatives: F,dFdX,dFdV */ Cloth *cloth = clmd->clothObject; unsigned int i = 0; float spring_air = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */ float gravity[3]; - float tm2[3][4] = {{-spring_air,0,0,0}, {0,-spring_air,0,0},{0,0,-spring_air,0}}; + float tm2[3][3] = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}}; ClothVertex *verts = cloth->verts; MFace *mfaces = cloth->mfaces; float wind_normalized[3]; @@ -1518,7 +1293,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec float speed[3] = {0.0f, 0.0f,0.0f}; float force[3]= {0.0f, 0.0f, 0.0f}; - #pragma omp parallel for private (i) shared(lF) schedule(static) +#pragma omp parallel for private (i) shared(lF) for(i = 0; i < cloth->numverts; i++) { float vertexnormal[3]={0,0,0}; @@ -1543,7 +1318,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec { // only handle active springs // if(((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)){} - cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX, dt); + cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); search = search->next; } @@ -1578,52 +1353,38 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec } - void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, fmatrix3x3 *P, fmatrix3x3 *Pinv) { unsigned int numverts = dFdV[0].vcount; lfVector *dFdXmV = create_lfvector(numverts); - initdiag_bfmatrix(A, I); - + zero_lfvector(dV, numverts); + subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); mul_bfmatrix_lfvector(dFdXmV, dFdX, lV); add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts); - // cg_filtered(dV, A, B, z, S); // conjugate gradient algorithm to solve Ax=b - cg_filtered_pre(dV, A, B, z, S, P, Pinv); + // itstart(); + + cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */ + + // TODO: if anyone finds a way to correct this function => + // explodes with stiffness = 3000 and 16k verts + pinned at 2 corners + // cg_filtered_pre(dV, A, B, z, S, P, Pinv); + + // itend(); + // printf("cg_filtered calc time: %f\n", (float)itval()); // advance velocities add_lfvector_lfvector(Vnew, lV, dV, numverts); + del_lfvector(dFdXmV); } -/* -// this version solves for the new velocity -void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, fmatrix3x3 *P, fmatrix3x3 *Pinv) -{ - unsigned int numverts = dFdV[0].vcount; - - lfVector *dFdXmV = create_lfvector(numverts); - - initdiag_bfmatrix(A, I); - - subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); - - mul_bfmatrix_lfvector(dFdXmV, dFdV, lV); - - add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, -dt, numverts); - add_lfvector_lfvector(B, B, lV, numverts); - - cg_filtered_pre(Vnew, A, B, z, S, P, Pinv); - - del_lfvector(dFdXmV); -} -*/ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) { unsigned int i=0; @@ -1635,7 +1396,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase Implicit_Data *id = cloth->implicit; int result = 0; float force = 0, lastforce = 0; - lfVector *dx; + // lfVector *dx; if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { @@ -1655,7 +1416,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase effectors= pdInitEffectors(ob,NULL); // calculate - cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, dt ); + cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); // check for sleeping // if(!(clmd->coll_parms->flags & CLOTH_SIMSETTINGS_FLAG_SLEEP)) @@ -1664,19 +1425,17 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); } - + /* dx = create_lfvector(numverts); sub_lfvector_lfvector(dx, id->Xnew, id->X, numverts); force = dot_lfvector(dx, dx, numverts); del_lfvector(dx); - /* if((force < 0.00001) && (lastforce >= force)) - clmd->coll_parms->flags |= CLOTH_SIMSETTINGS_FLAG_SLEEP; + clmd->coll_parms->flags |= CLOTH_SIMSETTINGS_FLAG_SLEEP; else if((lastforce*2 < force)) + clmd->coll_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_SLEEP; */ - clmd->coll_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_SLEEP; - lastforce = force; if(clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) @@ -1706,7 +1465,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase } // call collision function - result = cloth_bvh_objcollision(clmd, step + dt, step, dt); + result = 0; // cloth_bvh_objcollision(clmd, step + dt, step, dt); // copy corrected positions back to simulation if(result) @@ -1735,7 +1494,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase cp_lfvector(id->V, id->Vnew, numverts); // calculate - cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, dt); + cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->P, id->Pinv); } @@ -1775,19 +1534,11 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase } else { - for(i = 0; i < numverts; i++) - { - VECCOPY(cloth->current_xold[i], id->X[i]); - VECCOPY(cloth->x[i], id->X[i]); - } - // memcpy(cloth->current_xold, id->X, sizeof(lfVector) * numverts); - // memcpy(cloth->x, id->X, sizeof(lfVector) * numverts); + memcpy(cloth->current_xold, id->X, sizeof(lfVector) * numverts); + memcpy(cloth->x, id->X, sizeof(lfVector) * numverts); } - for(i = 0; i < numverts; i++) - VECCOPY(cloth->v[i], id->V[i]); - - // memcpy(cloth->v, id->V, sizeof(lfVector) * numverts); + memcpy(cloth->v, id->V, sizeof(lfVector) * numverts); return 1; } @@ -1795,18 +1546,11 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase void implicit_set_positions (ClothModifierData *clmd) { Cloth *cloth = clmd->clothObject; - unsigned int numverts = cloth->numverts, i = 0; + unsigned int numverts = cloth->numverts; Implicit_Data *id = cloth->implicit; - - for(i = 0; i < numverts; i++) - { - VECCOPY(id->X[i], cloth->x[i]); - VECCOPY(id->V[i], cloth->v[i]); - } - - // memcpy(id->X, cloth->x, sizeof(lfVector) * numverts); - // memcpy(id->V, cloth->v, sizeof(lfVector) * numverts); + memcpy(id->X, cloth->x, sizeof(lfVector) * numverts); + memcpy(id->V, cloth->v, sizeof(lfVector) * numverts); } @@ -1825,7 +1569,7 @@ int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierD cloth1 = clmd->clothObject; cloth2 = coll_clmd->clothObject; - // search = clmd->coll_parms->collision_list; + // search = clmd->coll_parms.collision_list; while(search) { @@ -1868,10 +1612,10 @@ int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierD float vrel_t_pre[3]; float vrel_t[3]; double impulse; - float epsilon = clmd->coll_parms->epsilon; + float epsilon = clmd->coll_parms.epsilon; float overlap = (epsilon + ALMOST_ZERO-collpair->distance); - // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms->friction*0.01, magrelVel); + // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); // magtangent = INPR(tangential, tangential); @@ -2071,20 +1815,20 @@ int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *co VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold); if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; + return 1; VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold); if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; + return 1; VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold); if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; + return 1; VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold); if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - */ + return 1; + */ return 0; } @@ -2345,7 +2089,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, LinkNode *collision_list = NULL; unsigned int i = 0, j = 0; int collisions = 0, count = 0; - float (*current_x)[4]; + float (*current_x)[3]; if (!(((Cloth *)clmd->clothObject)->tree)) { @@ -2362,57 +2106,57 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, //////////////////////////////////////////////////////////// // update cloth bvh - bvh_update_from_float4(bvh1, cloth->current_xold, cloth->numverts, cloth->current_x, 0); // 0 means STATIC, 1 means MOVING (see later in this function) + bvh_update_from_float3(bvh1, cloth->current_xold, cloth->numverts, cloth->current_x, 0); // 0 means STATIC, 1 means MOVING (see later in this function) /* // check all collision objects for (base = G.scene->base.first; base; base = base->next) { - ob2 = base->object; - collmd = (CollisionModifierData *) modifiers_findByType (ob2, eModifierType_Collision); + ob2 = base->object; + collmd = (CollisionModifierData *) modifiers_findByType (ob2, eModifierType_Collision); - if (!collmd) - continue; + if (!collmd) + continue; // check if there is a bounding volume hierarchy - if (collmd->tree) - { - bvh2 = collmd->tree; + if (collmd->tree) + { + bvh2 = collmd->tree; // update position + bvh of collision object - collision_move_object(collmd, step, prevstep); - bvh_update_from_mvert(collmd->tree, collmd->current_x, collmd->numverts, NULL, 0); + collision_move_object(collmd, step, prevstep); + bvh_update_from_mvert(collmd->tree, collmd->current_x, collmd->numverts, NULL, 0); // fill collision list - collisions += bvh_traverse(bvh1->root, bvh2->root, &collision_list); + collisions += bvh_traverse(bvh1->root, bvh2->root, &collision_list); // call static collision response // free collision list - if(collision_list) - { - LinkNode *search = collision_list; + if(collision_list) + { + LinkNode *search = collision_list; - while(search) - { - CollisionPair *coll_pair = search->link; + while(search) + { + CollisionPair *coll_pair = search->link; - MEM_freeN(coll_pair); - search = search->next; - } - BLI_linklist_free(collision_list,NULL); + MEM_freeN(coll_pair); + search = search->next; +} + BLI_linklist_free(collision_list,NULL); - collision_list = NULL; - } - } - } + collision_list = NULL; +} +} +} ////////////////////////////////////////////// // update velocities + positions ////////////////////////////////////////////// for(i = 0; i < cloth->numverts; i++) { - VECADD(cloth->current_x[i], cloth->current_xold[i], cloth->current_v[i]); - } + VECADD(cloth->current_x[i], cloth->current_xold[i], cloth->current_v[i]); +} ////////////////////////////////////////////// */ /* @@ -2424,68 +2168,68 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, // free collision list if(collision_list) { - LinkNode *search = collision_list; + LinkNode *search = collision_list; - while(search) - { - float distance = 0; - float mindistance = cloth->selftree->epsilon; - CollisionPair *collpair = (CollisionPair *)search->link; + while(search) + { + float distance = 0; + float mindistance = cloth->selftree->epsilon; + CollisionPair *collpair = (CollisionPair *)search->link; // get distance of faces - distance = plNearestPoints( - cloth->current_x[collpair->point_indexA[0]], cloth->current_x[collpair->point_indexA[1]], cloth->current_x[collpair->point_indexA[2]], cloth->current_x[collpair->point_indexB[0]], cloth->current_x[collpair->point_indexB[1]], cloth->current_x[collpair->point_indexB[2]], collpair->pa,collpair->pb,collpair->vector); + distance = plNearestPoints( + cloth->current_x[collpair->point_indexA[0]], cloth->current_x[collpair->point_indexA[1]], cloth->current_x[collpair->point_indexA[2]], cloth->current_x[collpair->point_indexB[0]], cloth->current_x[collpair->point_indexB[1]], cloth->current_x[collpair->point_indexB[2]], collpair->pa,collpair->pb,collpair->vector); - if(distance < mindistance) - { - /////////////////////////////////////////// + if(distance < mindistance) + { + /////////////////////////////////////////// // TODO: take velocity of the collision points into account! - /////////////////////////////////////////// + /////////////////////////////////////////// - float correction = mindistance - distance; - float temp[3]; + float correction = mindistance - distance; + float temp[3]; - VECCOPY(temp, collpair->vector); - Normalize(temp); - VecMulf(temp, -correction*0.5); + VECCOPY(temp, collpair->vector); + Normalize(temp); + VecMulf(temp, -correction*0.5); - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[0]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexA[0]], cloth->current_x[collpair->point_indexA[0]], temp); + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[0]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexA[0]], cloth->current_x[collpair->point_indexA[0]], temp); - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[1]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexA[1]], cloth->current_x[collpair->point_indexA[1]], temp); + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[1]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexA[1]], cloth->current_x[collpair->point_indexA[1]], temp); - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[2]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexA[2]], cloth->current_x[collpair->point_indexA[2]], temp); + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[2]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexA[2]], cloth->current_x[collpair->point_indexA[2]], temp); - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[0]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexB[0]], cloth->current_x[collpair->point_indexB[0]], temp); + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[0]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexB[0]], cloth->current_x[collpair->point_indexB[0]], temp); - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[1]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexB[1]], cloth->current_x[collpair->point_indexB[1]], temp); + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[1]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexB[1]], cloth->current_x[collpair->point_indexB[1]], temp); - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[2]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexB[2]], cloth->current_x[collpair->point_indexB[2]], temp); + if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[2]].goal >= SOFTGOALSNAP))) + VECSUB(cloth->current_x[collpair->point_indexB[2]], cloth->current_x[collpair->point_indexB[2]], temp); - collisions = 1; + collisions = 1; - } +} - } +} - search = collision_list; - while(search) - { - CollisionPair *coll_pair = search->link; + search = collision_list; + while(search) + { + CollisionPair *coll_pair = search->link; - MEM_freeN(coll_pair); - search = search->next; - } - BLI_linklist_free(collision_list,NULL); + MEM_freeN(coll_pair); + search = search->next; +} + BLI_linklist_free(collision_list,NULL); - collision_list = NULL; - } + collision_list = NULL; +} */ // Test on *simple* selfcollisions collisions = 1; @@ -2495,62 +2239,62 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, #pragma omp parallel for private(i,j, collisions) shared(current_x) for(count = 0; count < 6; count++) { - collisions = 0; + collisions = 0; - for(i = 0; i < cloth->numverts; i++) - { - for(j = i + 1; j < cloth->numverts; j++) - { - float temp[3]; - float length = 0; - float mindistance = cloth->selftree->epsilon; + for(i = 0; i < cloth->numverts; i++) + { + for(j = i + 1; j < cloth->numverts; j++) + { + float temp[3]; + float length = 0; + float mindistance = cloth->selftree->epsilon; - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - { - if((cloth->verts [i].goal >= SOFTGOALSNAP) - && (cloth->verts [j].goal >= SOFTGOALSNAP)) - { - continue; - } - } + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + { + if((cloth->verts [i].goal >= SOFTGOALSNAP) + && (cloth->verts [j].goal >= SOFTGOALSNAP)) + { + continue; +} +} // check for adjacent points - if(BLI_edgehash_haskey ( cloth->edgehash, i, j )) - { - continue; - } + if(BLI_edgehash_haskey ( cloth->edgehash, i, j )) + { + continue; +} - VECSUB(temp, current_x[i], current_x[j]); + VECSUB(temp, current_x[i], current_x[j]); - length = Normalize(temp); + length = Normalize(temp); - if(length < mindistance) - { - float correction = mindistance - length; + if(length < mindistance) + { + float correction = mindistance - length; - if((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [i].goal >= SOFTGOALSNAP)) - { - VecMulf(temp, -correction); - VECADD(current_x[j], current_x[j], temp); - } - else if((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [j].goal >= SOFTGOALSNAP)) - { - VecMulf(temp, correction); - VECADD(current_x[i], current_x[i], temp); - } - else - { - VecMulf(temp, -correction*0.5); - VECADD(current_x[j], current_x[j], temp); + if((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [i].goal >= SOFTGOALSNAP)) + { + VecMulf(temp, -correction); + VECADD(current_x[j], current_x[j], temp); +} + else if((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [j].goal >= SOFTGOALSNAP)) + { + VecMulf(temp, correction); + VECADD(current_x[i], current_x[i], temp); +} + else + { + VecMulf(temp, -correction*0.5); + VECADD(current_x[j], current_x[j], temp); - VECSUB(current_x[i], current_x[i], temp); - } + VECSUB(current_x[i], current_x[i], temp); +} - collisions = 1; - } - } - } - } + collisions = 1; +} +} +} +} ////////////////////////////////////////////// @@ -2558,8 +2302,8 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, ////////////////////////////////////////////// for(i = 0; i < cloth->numverts; i++) { - VECSUB(cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i]); - } + VECSUB(cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i]); +} ////////////////////////////////////////////// */ return 1; From b5974a058610f9d1f799618724d9fb890fc0be26 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 25 Nov 2007 03:46:41 +0000 Subject: [PATCH 057/101] little debug output for MT fluid --- intern/elbeem/intern/solver_main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp index afc883972e2..8ec667b8cb6 100644 --- a/intern/elbeem/intern/solver_main.cpp +++ b/intern/elbeem/intern/solver_main.cpp @@ -363,7 +363,9 @@ LbmFsgrSolver::mainLoop(int lev) const int cutMin = 1; const int cutConst = mCutoff+2; - +#if PARALLEL==1 + printf("omp_get_num_threads: %d\n", omp_get_num_threads()); +#endif # if LBM_INCLUDE_TESTSOLVERS==1 // 3d region off... quit From c8a412cdcb4059990c2e23f42ee54691daedf13a Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 25 Nov 2007 21:14:52 +0000 Subject: [PATCH 058/101] Commit of fluid fix for 32/64bit and max 2.5gb ram issue --- intern/elbeem/intern/loop_tools.h | 2 +- intern/elbeem/intern/solver_init.cpp | 5 +++-- intern/elbeem/intern/solver_main.cpp | 5 +---- source/blender/blenkernel/BKE_cloth.h | 1 + source/blender/blenkernel/intern/implicit.c | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/intern/elbeem/intern/loop_tools.h b/intern/elbeem/intern/loop_tools.h index 70ecb9ce3e0..8ff51039bf2 100644 --- a/intern/elbeem/intern/loop_tools.h +++ b/intern/elbeem/intern/loop_tools.h @@ -91,7 +91,7 @@ calcListEmpty.reserve(mListEmpty.capacity() / omp_get_num_threads() ); \ calcListFull.reserve( mListFull.capacity() / omp_get_num_threads() ); \ calcListParts.reserve(mSizex); \ - \ + printf("omp_get_num_threads: %d\n", omp_get_num_threads()); \ \ const int id = omp_get_thread_num(); \ const int Nthrds = omp_get_num_threads(); \ diff --git a/intern/elbeem/intern/solver_init.cpp b/intern/elbeem/intern/solver_init.cpp index b0ce130c136..105c8ff3094 100644 --- a/intern/elbeem/intern/solver_init.cpp +++ b/intern/elbeem/intern/solver_init.cpp @@ -703,11 +703,12 @@ bool LbmFsgrSolver::initializeSolverMemory() memBlockAllocProblem = true; } #endif // Mac - if(sizeof(int)==4 && memEstFine>maxDefaultMemChunk) { + if(sizeof(void *)==4 && memEstFine>maxDefaultMemChunk) { // max memory chunk for 32bit systems 2gig memBlockAllocProblem = true; + } - + if(memEstFromFunc>memLimit || memBlockAllocProblem) { sizeReduction *= 0.9; mSizex = (int)(orgSx * sizeReduction); diff --git a/intern/elbeem/intern/solver_main.cpp b/intern/elbeem/intern/solver_main.cpp index 8ec667b8cb6..0f788af7955 100644 --- a/intern/elbeem/intern/solver_main.cpp +++ b/intern/elbeem/intern/solver_main.cpp @@ -363,10 +363,7 @@ LbmFsgrSolver::mainLoop(int lev) const int cutMin = 1; const int cutConst = mCutoff+2; -#if PARALLEL==1 - printf("omp_get_num_threads: %d\n", omp_get_num_threads()); -#endif - + # if LBM_INCLUDE_TESTSOLVERS==1 // 3d region off... quit if((mUseTestdata)&&(mpTest->mFarfMode>0)) { return; } diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 38cd54085f5..f83cf0515df 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -63,6 +63,7 @@ typedef struct ClothVertex { float goal; /* goal, from SB */ float impulse[3]; /* used in collision.c */ unsigned int impulse_count; /* same as above */ + float collball; } ClothVertex; typedef struct ClothSpring { diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 6f8f96e58fb..0f8357cee25 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1465,7 +1465,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase } // call collision function - result = 0; // cloth_bvh_objcollision(clmd, step + dt, step, dt); + result = cloth_bvh_objcollision(clmd, step + dt, step, dt); // copy corrected positions back to simulation if(result) From bc2c9336fdb6baf21bba58e042cbd4b039e25971 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 26 Nov 2007 00:26:29 +0000 Subject: [PATCH 059/101] ccherrett pre-alpha subsurf openmp code --- intern/elbeem/intern/isosurface.cpp | 53 ++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/intern/elbeem/intern/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp index 9925565b85d..5d20e68ef34 100644 --- a/intern/elbeem/intern/isosurface.cpp +++ b/intern/elbeem/intern/isosurface.cpp @@ -156,13 +156,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, @@ -189,7 +182,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 ); @@ -235,6 +233,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); @@ -340,10 +339,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 @@ -404,13 +400,27 @@ void IsoSurface::triangulate( void ) debMsgStd("IsoSurface::triangulate",DM_MSG,"Starting. Parts in use:"< mPoints; + */ +#pragma omp parallel for for(int ok=1;ok<(mSizez-2)*mSubdivs;ok++) { pz += gsz; const int k = ok/mSubdivs; if(k<=0) continue; // skip zero plane 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 @@ -422,6 +432,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 Date: Mon, 26 Nov 2007 00:57:46 +0000 Subject: [PATCH 060/101] Insert revert point (segfault) --- intern/elbeem/intern/isosurface.cpp | 57 ++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/intern/elbeem/intern/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp index 5d20e68ef34..0e3d37ea494 100644 --- a/intern/elbeem/intern/isosurface.cpp +++ b/intern/elbeem/intern/isosurface.cpp @@ -18,6 +18,8 @@ #define round(x) (x) #endif +#include + /****************************************************************************** * Constructor *****************************************************************************/ @@ -400,17 +402,28 @@ void IsoSurface::triangulate( void ) debMsgStd("IsoSurface::triangulate",DM_MSG,"Starting. Parts in use:"< mPoints; - */ -#pragma omp parallel for + vector calcPoints; + vector calcIndices; + const int id = omp_get_thread_num(); + const int Nthrds = omp_get_num_threads(); + + const int Nj = (mSizey-2); + + int jstart = 0+( id * (Nj / Nthrds) ); + int jend = 0+( (id+1) * (Nj / Nthrds) ); + + if(jstart<1) jstart = 1; + if(jend>(mSizey-2)) jend = (mSizey-2); + + for(int ok=1;ok<(mSizez-2)*mSubdivs;ok++) { pz += gsz; const int k = ok/mSubdivs; if(k<=0) continue; // skip zero plane - for(int j=1;j<(mSizey-2);j++) { + for(int j=jstart;j Date: Mon, 26 Nov 2007 01:04:01 +0000 Subject: [PATCH 061/101] Reverted to rev 12673 + test for ccherett --- intern/elbeem/intern/isosurface.cpp | 62 +++++++---------------------- 1 file changed, 15 insertions(+), 47 deletions(-) diff --git a/intern/elbeem/intern/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp index 0e3d37ea494..3be4097a38a 100644 --- a/intern/elbeem/intern/isosurface.cpp +++ b/intern/elbeem/intern/isosurface.cpp @@ -18,8 +18,6 @@ #define round(x) (x) #endif -#include - /****************************************************************************** * Constructor *****************************************************************************/ @@ -134,7 +132,7 @@ void IsoSurface::triangulate( void ) { double gsx,gsy,gsz; // grid spacing in x,y,z direction double px,py,pz; // current position in grid in x,y,z direction - IsoLevelCube cubie; // struct for a small subcube + // IsoLevelCube cubie; // struct for a small subcube myTime_t tritimestart = getTime(); if(!mpData) { @@ -402,28 +400,12 @@ void IsoSurface::triangulate( void ) debMsgStd("IsoSurface::triangulate",DM_MSG,"Starting. Parts in use:"< calcPoints; - vector calcIndices; - const int id = omp_get_thread_num(); - const int Nthrds = omp_get_num_threads(); - - const int Nj = (mSizey-2); - - int jstart = 0+( id * (Nj / Nthrds) ); - int jend = 0+( (id+1) * (Nj / Nthrds) ); - - if(jstart<1) jstart = 1; - if(jend>(mSizey-2)) jend = (mSizey-2); - - for(int ok=1;ok<(mSizez-2)*mSubdivs;ok++) { pz += gsz; const int k = ok/mSubdivs; if(k<=0) continue; // skip zero plane - for(int j=jstart;j Date: Mon, 26 Nov 2007 02:41:06 +0000 Subject: [PATCH 062/101] New feature: Fluids internal subdiv (level >=2) uses OpenMP now --- intern/elbeem/intern/isosurface.cpp | 81 +++++++++++++++++++++++------ intern/elbeem/intern/loop_tools.h | 2 +- 2 files changed, 66 insertions(+), 17 deletions(-) diff --git a/intern/elbeem/intern/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp index 3be4097a38a..6f8c6b11866 100644 --- a/intern/elbeem/intern/isosurface.cpp +++ b/intern/elbeem/intern/isosurface.cpp @@ -18,6 +18,10 @@ #define round(x) (x) #endif +#if PARALLEL==1 +#include +#endif + /****************************************************************************** * Constructor *****************************************************************************/ @@ -132,7 +136,7 @@ void IsoSurface::triangulate( void ) { double gsx,gsy,gsz; // grid spacing in x,y,z direction double px,py,pz; // current position in grid in x,y,z direction - // IsoLevelCube cubie; // struct for a small subcube + IsoLevelCube cubie; // struct for a small subcube myTime_t tritimestart = getTime(); if(!mpData) { @@ -327,6 +331,16 @@ void IsoSurface::triangulate( void ) ( (fi))*(1.-(fj))*( (fk))*orgval[5] + \ ( (fi))*( (fj))*( (fk))*orgval[6] + \ (1.-(fi))*( (fj))*( (fk))*orgval[7] ) + +#if PARALLEL==1 +#define LIST_POINT(x) calcPoints.push_back(x); +#define LIST_POINT_SIZE calcPoints.size() +#define LIST_INDEX(x) calcIndices.push_back(x); +#else +#define LIST_POINT(x) mPoints.push_back(x); +#define LIST_POINT_SIZE mPoints.size() +#define LIST_INDEX(x) mIndices.push_back(x); +#endif // use subdivisions gfxReal subdfac = 1./(gfxReal)(mSubdivs); @@ -400,12 +414,31 @@ void IsoSurface::triangulate( void ) debMsgStd("IsoSurface::triangulate",DM_MSG,"Starting. Parts in use:"< calcPoints; + vector calcIndices; + const int id = omp_get_thread_num(); + const int Nthrds = omp_get_num_threads(); + + const int Nj = (mSizey-2); + + int jstart = 0+( id * (Nj / Nthrds) ); + int jend = 0+( (id+1) * (Nj / Nthrds) ); + + if(jstart<1) jstart = 1; + if(jend>(mSizey-2)) jend = (mSizey-2); +#else + int jstart = 1; + int jend = (mSizey-2); +#endif + for(int ok=1;ok<(mSizez-2)*mSubdivs;ok++) { pz += gsz; const int k = ok/mSubdivs; if(k<=0) continue; // skip zero plane -#pragma omp parallel for - for(int j=1;j<(mSizey-2);j++) { + for(int j=jstart;j Date: Mon, 26 Nov 2007 14:50:27 +0000 Subject: [PATCH 063/101] Segfault revert, MT should work fine again for subdiv fluids --- intern/elbeem/intern/isosurface.cpp | 1125 +++++++++++++-------------- intern/elbeem/intern/loop_tools.h | 20 +- intern/elbeem/intern/paraloopend.h | 6 +- 3 files changed, 551 insertions(+), 600 deletions(-) diff --git a/intern/elbeem/intern/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp index 6f8c6b11866..77530d413c7 100644 --- a/intern/elbeem/intern/isosurface.cpp +++ b/intern/elbeem/intern/isosurface.cpp @@ -18,32 +18,28 @@ #define round(x) (x) #endif -#if PARALLEL==1 -#include -#endif - /****************************************************************************** * Constructor *****************************************************************************/ IsoSurface::IsoSurface(double iso) : - ntlGeometryObject(), - mSizex(-1), mSizey(-1), mSizez(-1), - mpData(NULL), - mIsoValue( iso ), - mPoints(), - mUseFullEdgeArrays(false), - mpEdgeVerticesX(NULL), mpEdgeVerticesY(NULL), mpEdgeVerticesZ(NULL), - mEdgeArSize(-1), - mIndices(), + ntlGeometryObject(), + mSizex(-1), mSizey(-1), mSizez(-1), + mpData(NULL), + mIsoValue( iso ), + mPoints(), + mUseFullEdgeArrays(false), + mpEdgeVerticesX(NULL), mpEdgeVerticesY(NULL), mpEdgeVerticesZ(NULL), + mEdgeArSize(-1), + mIndices(), - mStart(0.0), mEnd(0.0), mDomainExtent(0.0), - mInitDone(false), - mSmoothSurface(0.0), mSmoothNormals(0.0), - mAcrossEdge(), mAdjacentFaces(), - mCutoff(-1), mCutArray(NULL), // off by default - mpIsoParts(NULL), mPartSize(0.), mSubdivs(0), - mFlagCnt(1), - mSCrad1(0.), mSCrad2(0.), mSCcenter(0.) + mStart(0.0), mEnd(0.0), mDomainExtent(0.0), + mInitDone(false), + mSmoothSurface(0.0), mSmoothNormals(0.0), + mAcrossEdge(), mAdjacentFaces(), + mCutoff(-1), mCutArray(NULL), // off by default + mpIsoParts(NULL), mPartSize(0.), mSubdivs(0), + mFlagCnt(1), + mSCrad1(0.), mSCrad2(0.), mSCcenter(0.) { } @@ -75,11 +71,11 @@ void IsoSurface::initializeIsosurface(int setx, int sety, int setz, ntlVec3Gfx e // init mIndices.clear(); - mPoints.clear(); + mPoints.clear(); int nodes = mSizez*mSizey*mSizex; - mpData = new float[nodes]; - for(int i=0;i0) && (kmSizex-2-coAdd-mCutoff) || - (j>mSizey-2-coAdd-mCutoff) ) { - if(mCutArray) { - if(k < mCutArray[j*this->mSizex+i]) continue; - } else { continue; } - } + if( (i0) && (kmSizex-2-coAdd-mCutoff) || + (j>mSizey-2-coAdd-mCutoff) ) { + if(mCutArray) { + if(k < mCutArray[j*this->mSizex+i]) continue; + } else { continue; } + } // Create the triangles... - 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] ] ); - mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+2] ] ); - } + 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] ] ); + mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+2] ] ); + } - }//i - }// j + }//i + }// j // copy edge arrays - if(!mUseFullEdgeArrays) { - for(int j=0;j<(mSizey-0);j++) - for(int i=0;i<(mSizex-0);i++) { + if(!mUseFullEdgeArrays) { + for(int j=0;j<(mSizey-0);j++) + for(int i=0;i<(mSizex-0);i++) { //int edgek = 0; - const int dst = ISOLEVEL_INDEX( i+0, j+0, 0); - const int src = ISOLEVEL_INDEX( i+0, j+0, 1); - mpEdgeVerticesX[ dst ] = mpEdgeVerticesX[ src ]; - mpEdgeVerticesY[ dst ] = mpEdgeVerticesY[ src ]; - mpEdgeVerticesZ[ dst ] = mpEdgeVerticesZ[ src ]; - mpEdgeVerticesX[ src ]=-1; - mpEdgeVerticesY[ src ]=-1; - mpEdgeVerticesZ[ src ]=-1; - } - } // */ + const int dst = ISOLEVEL_INDEX( i+0, j+0, 0); + const int src = ISOLEVEL_INDEX( i+0, j+0, 1); + mpEdgeVerticesX[ dst ] = mpEdgeVerticesX[ src ]; + mpEdgeVerticesY[ dst ] = mpEdgeVerticesY[ src ]; + mpEdgeVerticesZ[ dst ] = mpEdgeVerticesZ[ src ]; + mpEdgeVerticesX[ src ]=-1; + mpEdgeVerticesY[ src ]=-1; + mpEdgeVerticesZ[ src ]=-1; + } + } // */ - } // k + } // k // precalculate normals using an approximation of the scalar field gradient - for(int ni=0;ni<(int)mPoints.size();ni++) { normalize( mPoints[ni].n ); } + for(int ni=0;ni<(int)mPoints.size();ni++) { normalize( mPoints[ni].n ); } - } else { // subdivs + } else { // subdivs #define EDGEAR_INDEX(Ai,Aj,Ak, Bi,Bj) ((mSizex*mSizey*mSubdivs*mSubdivs*(Ak))+\ - (mSizex*mSubdivs*((Aj)*mSubdivs+(Bj)))+((Ai)*mSubdivs)+(Bi)) + (mSizex*mSubdivs*((Aj)*mSubdivs+(Bj)))+((Ai)*mSubdivs)+(Bi)) #define ISOTRILININT(fi,fj,fk) ( \ - (1.-(fi))*(1.-(fj))*(1.-(fk))*orgval[0] + \ - ( (fi))*(1.-(fj))*(1.-(fk))*orgval[1] + \ - ( (fi))*( (fj))*(1.-(fk))*orgval[2] + \ - (1.-(fi))*( (fj))*(1.-(fk))*orgval[3] + \ - (1.-(fi))*(1.-(fj))*( (fk))*orgval[4] + \ - ( (fi))*(1.-(fj))*( (fk))*orgval[5] + \ - ( (fi))*( (fj))*( (fk))*orgval[6] + \ - (1.-(fi))*( (fj))*( (fk))*orgval[7] ) - -#if PARALLEL==1 -#define LIST_POINT(x) calcPoints.push_back(x); -#define LIST_POINT_SIZE calcPoints.size() -#define LIST_INDEX(x) calcIndices.push_back(x); -#else -#define LIST_POINT(x) mPoints.push_back(x); -#define LIST_POINT_SIZE mPoints.size() -#define LIST_INDEX(x) mIndices.push_back(x); -#endif + (1.-(fi))*(1.-(fj))*(1.-(fk))*orgval[0] + \ + ( (fi))*(1.-(fj))*(1.-(fk))*orgval[1] + \ + ( (fi))*( (fj))*(1.-(fk))*orgval[2] + \ + (1.-(fi))*( (fj))*(1.-(fk))*orgval[3] + \ + (1.-(fi))*(1.-(fj))*( (fk))*orgval[4] + \ + ( (fi))*(1.-(fj))*( (fk))*orgval[5] + \ + ( (fi))*( (fj))*( (fk))*orgval[6] + \ + (1.-(fi))*( (fj))*( (fk))*orgval[7] ) // use subdivisions - gfxReal subdfac = 1./(gfxReal)(mSubdivs); - gfxReal orgGsx = gsx; - gfxReal orgGsy = gsy; - gfxReal orgGsz = gsz; - gsx *= subdfac; - gsy *= subdfac; - gsz *= subdfac; - if(mUseFullEdgeArrays) { - errMsg("IsoSurface::triangulate","Disabling mUseFullEdgeArrays!"); - } + gfxReal subdfac = 1./(gfxReal)(mSubdivs); + gfxReal orgGsx = gsx; + gfxReal orgGsy = gsy; + gfxReal orgGsz = gsz; + gsx *= subdfac; + gsy *= subdfac; + gsz *= subdfac; + if(mUseFullEdgeArrays) { + errMsg("IsoSurface::triangulate","Disabling mUseFullEdgeArrays!"); + } - ParticleObject* *arppnt = new ParticleObject*[mSizez*mSizey*mSizex]; + ParticleObject* *arppnt = new ParticleObject*[mSizez*mSizey*mSizex]; // construct pointers // part test - int pInUse = 0; - int pUsedTest = 0; + int pInUse = 0; + int pUsedTest = 0; // reset particles // reset list array - for(int k=0;k<(mSizez);k++) - for(int j=0;j<(mSizey);j++) - for(int i=0;i<(mSizex);i++) { - arppnt[ISOLEVEL_INDEX(i,j,k)] = NULL; - } - if(mpIsoParts) { - for(vector::iterator pit= mpIsoParts->getParticlesBegin(); - pit!= mpIsoParts->getParticlesEnd(); pit++) { - if( (*pit).getActive()==false ) continue; - if( (*pit).getType()!=PART_DROP) continue; - (*pit).setNext(NULL); - } + for(int k=0;k<(mSizez);k++) + for(int j=0;j<(mSizey);j++) + for(int i=0;i<(mSizex);i++) { + arppnt[ISOLEVEL_INDEX(i,j,k)] = NULL; + } + if(mpIsoParts) { + for(vector::iterator pit= mpIsoParts->getParticlesBegin(); + pit!= mpIsoParts->getParticlesEnd(); pit++) { + if( (*pit).getActive()==false ) continue; + if( (*pit).getType()!=PART_DROP) continue; + (*pit).setNext(NULL); + } // build per node lists - for(vector::iterator pit= mpIsoParts->getParticlesBegin(); - pit!= mpIsoParts->getParticlesEnd(); pit++) { - if( (*pit).getActive()==false ) continue; - if( (*pit).getType()!=PART_DROP) continue; + for(vector::iterator pit= mpIsoParts->getParticlesBegin(); + pit!= mpIsoParts->getParticlesEnd(); pit++) { + if( (*pit).getActive()==false ) continue; + if( (*pit).getType()!=PART_DROP) continue; // check lifetime ignored here - ParticleObject *p = &(*pit); - const ntlVec3Gfx ppos = p->getPos(); - const int pi= (int)round(ppos[0])+0; - const int pj= (int)round(ppos[1])+0; - int pk= (int)round(ppos[2])+0;// no offset necessary + ParticleObject *p = &(*pit); + const ntlVec3Gfx ppos = p->getPos(); + const int pi= (int)round(ppos[0])+0; + const int pj= (int)round(ppos[1])+0; + int pk= (int)round(ppos[2])+0;// no offset necessary // 2d should be handled by solver. if(LBMDIM==2) { pk = 0; } - if(pi<0) continue; - if(pj<0) continue; - if(pk<0) continue; - if(pi>mSizex-1) continue; - if(pj>mSizey-1) continue; - if(pk>mSizez-1) continue; - ParticleObject* &pnt = arppnt[ISOLEVEL_INDEX(pi,pj,pk)]; - if(pnt) { + if(pi<0) continue; + if(pj<0) continue; + if(pk<0) continue; + if(pi>mSizex-1) continue; + if(pj>mSizey-1) continue; + if(pk>mSizez-1) continue; + ParticleObject* &pnt = arppnt[ISOLEVEL_INDEX(pi,pj,pk)]; + if(pnt) { // append - ParticleObject* listpnt = pnt; - while(listpnt) { - if(!listpnt->getNext()) { - listpnt->setNext(p); listpnt = NULL; - } else { - listpnt = listpnt->getNext(); - } - } - } else { + ParticleObject* listpnt = pnt; + while(listpnt) { + if(!listpnt->getNext()) { + listpnt->setNext(p); listpnt = NULL; + } else { + listpnt = listpnt->getNext(); + } + } + } else { // start new list - pnt = p; - } - pInUse++; - } - } // mpIsoParts + pnt = p; + } + pInUse++; + } + } // mpIsoParts - debMsgStd("IsoSurface::triangulate",DM_MSG,"Starting. Parts in use:"< calcPoints; - vector calcIndices; - const int id = omp_get_thread_num(); - const int Nthrds = omp_get_num_threads(); - - const int Nj = (mSizey-2); - - int jstart = 0+( id * (Nj / Nthrds) ); - int jend = 0+( (id+1) * (Nj / Nthrds) ); - - if(jstart<1) jstart = 1; - if(jend>(mSizey-2)) jend = (mSizey-2); -#else - int jstart = 1; - int jend = (mSizey-2); -#endif - - for(int ok=1;ok<(mSizez-2)*mSubdivs;ok++) { - pz += gsz; - const int k = ok/mSubdivs; - if(k<=0) continue; // skip zero plane - for(int j=jstart;j=mSizez-1) continue; - for(int poj=-poDistOffset; poj<1+poDistOffset; poj++) { - if(j+poj<0) continue; - if(j+poj>=mSizey-1) continue; - for(int poi=-poDistOffset; poi<1+poDistOffset; poi++) { - if(i+poi<0) continue; - if(i+poi>=mSizex-1) continue; - ParticleObject *p; - p = arppnt[ISOLEVEL_INDEX(i+poi,j+poj,k+pok)]; - while(p) { // */ + const int poDistOffset=2; + for(int pok=-poDistOffset; pok<1+poDistOffset; pok++) { + if(k+pok<0) continue; + if(k+pok>=mSizez-1) continue; + for(int poj=-poDistOffset; poj<1+poDistOffset; poj++) { + if(j+poj<0) continue; + if(j+poj>=mSizey-1) continue; + for(int poi=-poDistOffset; poi<1+poDistOffset; poi++) { + if(i+poi<0) continue; + if(i+poi>=mSizex-1) continue; + ParticleObject *p; + p = arppnt[ISOLEVEL_INDEX(i+poi,j+poj,k+pok)]; + while(p) { // */ /* - for(vector::iterator pit= mpIsoParts->getParticlesBegin(); - pit!= mpIsoParts->getParticlesEnd(); pit++) { { { { + for(vector::iterator pit= mpIsoParts->getParticlesBegin(); + pit!= mpIsoParts->getParticlesEnd(); pit++) { { { { // debug test! , full list slow! - if(( (*pit).getActive()==false ) || ( (*pit).getType()!=PART_DROP)) continue; - ParticleObject *p; - p = &(*pit); // */ + if(( (*pit).getActive()==false ) || ( (*pit).getType()!=PART_DROP)) continue; + ParticleObject *p; + p = &(*pit); // */ - pUsedTest++; - ntlVec3Gfx ppos = p->getPos(); - const int spi= (int)round( (ppos[0]+1.-(gfxReal)i) *(gfxReal)mSubdivs-1.5); - const int spj= (int)round( (ppos[1]+1.-(gfxReal)j) *(gfxReal)mSubdivs-1.5); - const int spk= (int)round( (ppos[2]+1.-(gfxReal)k) *(gfxReal)mSubdivs-1.5)-sdkOffset; // why -2? + pUsedTest++; + ntlVec3Gfx ppos = p->getPos(); + const int spi= (int)round( (ppos[0]+1.-(gfxReal)i) *(gfxReal)mSubdivs-1.5); + const int spj= (int)round( (ppos[1]+1.-(gfxReal)j) *(gfxReal)mSubdivs-1.5); + const int spk= (int)round( (ppos[2]+1.-(gfxReal)k) *(gfxReal)mSubdivs-1.5)-sdkOffset; // why -2? // 2d should be handled by solver. if(LBMDIM==2) { spk = 0; } - gfxReal pfLen = p->getSize()*1.5*mPartSize; // test, was 1.1 - const gfxReal minPfLen = subdfac*0.8; - if(pfLengetSize()*1.5*mPartSize; // test, was 1.1 + const gfxReal minPfLen = subdfac*0.8; + if(pfLengetSize()<<" ps"< 1) { continue; } // */ - for(int swj=-icellpsize; swj<=icellpsize; swj++) { - if(spj+swj< 0) { continue; } - if(spj+swj>mSubdivs+0) { continue; } // */ - for(int swi=-icellpsize; swi<=icellpsize; swi++) { - if(spi+swi< 0) { continue; } - if(spi+swi>mSubdivs+0) { continue; } // */ - ntlVec3Gfx cellp = ntlVec3Gfx( + const int icellpsize = (int)(1.*pfLen*(gfxReal)mSubdivs)+1; + for(int swk=-icellpsize; swk<=icellpsize; swk++) { + if(spk+swk< 0) { continue; } + if(spk+swk> 1) { continue; } // */ + for(int swj=-icellpsize; swj<=icellpsize; swj++) { + if(spj+swj< 0) { continue; } + if(spj+swj>mSubdivs+0) { continue; } // */ + for(int swi=-icellpsize; swi<=icellpsize; swi++) { + if(spi+swi< 0) { continue; } + if(spi+swi>mSubdivs+0) { continue; } // */ + ntlVec3Gfx cellp = ntlVec3Gfx( (1.5+(gfxReal)(spi+swi)) *subdfac + (gfxReal)(i-1), (1.5+(gfxReal)(spj+swj)) *subdfac + (gfxReal)(j-1), (1.5+(gfxReal)(spk+swk)+sdkOffset) *subdfac + (gfxReal)(k-1) ); //if(swi==0 && swj==0 && swk==0) subdAr[spk][spj][spi] = 1.; // DEBUG // clip domain boundaries again - if(cellp[0]<1.) { continue; } - if(cellp[1]<1.) { continue; } - if(cellp[2]<1.) { continue; } - if(cellp[0]>(gfxReal)mSizex-3.) { continue; } - if(cellp[1]>(gfxReal)mSizey-3.) { continue; } - if(cellp[2]>(gfxReal)mSizez-3.) { continue; } - gfxReal len = norm(cellp-ppos); - gfxReal isoadd = 0.; - const gfxReal baseIsoVal = mIsoValue*1.1; - if(len(gfxReal)mSizex-3.) { continue; } + if(cellp[1]>(gfxReal)mSizey-3.) { continue; } + if(cellp[2]>(gfxReal)mSizez-3.) { continue; } + gfxReal len = norm(cellp-ppos); + gfxReal isoadd = 0.; + const gfxReal baseIsoVal = mIsoValue*1.1; + if(len1.) { continue; } - subdAr[spk+swk][spj+swj][spi+swi] = arval + isoadd; - } } } + const gfxReal arval = subdAr[spk+swk][spj+swj][spi+swi]; + if(arval>1.) { continue; } + subdAr[spk+swk][spj+swj][spi+swi] = arval + isoadd; + } } } - p = p->getNext(); - } - } } } // poDist loops */ + p = p->getNext(); + } + } } } // poDist loops */ - py = mStart[1]+(((double)j-0.5)*orgGsy)-gsy; - for(int sj=0;sj 0) { + if (mcEdgeTable[cubeIndex] > 0) { // where to look up if this point already exists - const int edgek = 0; - const int baseIn = EDGEAR_INDEX( i+0, j+0, edgek+0, si,sj); - eVert[ 0] = &mpEdgeVerticesX[ baseIn ]; - eVert[ 1] = &mpEdgeVerticesY[ baseIn + 1 ]; - eVert[ 2] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+0, si+0,sj+1) ]; - eVert[ 3] = &mpEdgeVerticesY[ baseIn ]; + const int edgek = 0; + const int baseIn = EDGEAR_INDEX( i+0, j+0, edgek+0, si,sj); + eVert[ 0] = &mpEdgeVerticesX[ baseIn ]; + eVert[ 1] = &mpEdgeVerticesY[ baseIn + 1 ]; + eVert[ 2] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+0, si+0,sj+1) ]; + eVert[ 3] = &mpEdgeVerticesY[ baseIn ]; - eVert[ 4] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+0) ]; - eVert[ 5] = &mpEdgeVerticesY[ EDGEAR_INDEX( i, j, edgek+1, si+1,sj+0) ]; // with subdivs - eVert[ 6] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+1) ]; - eVert[ 7] = &mpEdgeVerticesY[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+0) ]; + eVert[ 4] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+0) ]; + eVert[ 5] = &mpEdgeVerticesY[ EDGEAR_INDEX( i, j, edgek+1, si+1,sj+0) ]; // with subdivs + eVert[ 6] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+1) ]; + eVert[ 7] = &mpEdgeVerticesY[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+0) ]; - eVert[ 8] = &mpEdgeVerticesZ[ baseIn ]; - eVert[ 9] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+1,sj+0) ]; // with subdivs - eVert[10] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+1,sj+1) ]; - eVert[11] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+0,sj+1) ]; + eVert[ 8] = &mpEdgeVerticesZ[ baseIn ]; + eVert[ 9] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+1,sj+0) ]; // with subdivs + eVert[10] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+1,sj+1) ]; + eVert[11] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+0,sj+1) ]; // grid positions - pos[0] = ntlVec3Gfx(px ,py ,pz); - pos[1] = ntlVec3Gfx(px+gsx,py ,pz); - pos[2] = ntlVec3Gfx(px+gsx,py+gsy,pz); // with subdivs - pos[3] = ntlVec3Gfx(px ,py+gsy,pz); - pos[4] = ntlVec3Gfx(px ,py ,pz+gsz); - pos[5] = ntlVec3Gfx(px+gsx,py ,pz+gsz); - pos[6] = ntlVec3Gfx(px+gsx,py+gsy,pz+gsz); // with subdivs - pos[7] = ntlVec3Gfx(px ,py+gsy,pz+gsz); + pos[0] = ntlVec3Gfx(px ,py ,pz); + pos[1] = ntlVec3Gfx(px+gsx,py ,pz); + pos[2] = ntlVec3Gfx(px+gsx,py+gsy,pz); // with subdivs + pos[3] = ntlVec3Gfx(px ,py+gsy,pz); + pos[4] = ntlVec3Gfx(px ,py ,pz+gsz); + pos[5] = ntlVec3Gfx(px+gsx,py ,pz+gsz); + pos[6] = ntlVec3Gfx(px+gsx,py+gsy,pz+gsz); // with subdivs + pos[7] = ntlVec3Gfx(px ,py+gsy,pz+gsz); // check all edges - for(int e=0;e<12;e++) { - if (mcEdgeTable[cubeIndex] & (1<0) { + float smoSubdfac = 1.; + if(mSubdivs>0) { //smoSubdfac = 1./(float)(mSubdivs); - smoSubdfac = pow(0.55,(double)mSubdivs); // slightly stronger - } - if(mSmoothSurface>0. || mSmoothNormals>0.) debMsgStd("IsoSurface::triangulate",DM_MSG,"Smoothing...",10); - if(mSmoothSurface>0.0) { - smoothSurface(mSmoothSurface*smoSubdfac, (mSmoothNormals<=0.0) ); - } - if(mSmoothNormals>0.0) { - smoothNormals(mSmoothNormals*smoSubdfac); - } + smoSubdfac = pow(0.55,(double)mSubdivs); // slightly stronger + } + if(mSmoothSurface>0. || mSmoothNormals>0.) debMsgStd("IsoSurface::triangulate",DM_MSG,"Smoothing...",10); + if(mSmoothSurface>0.0) { + smoothSurface(mSmoothSurface*smoSubdfac, (mSmoothNormals<=0.0) ); + } + if(mSmoothNormals>0.0) { + smoothNormals(mSmoothNormals*smoSubdfac); + } - myTime_t tritimeend = getTime(); - debMsgStd("IsoSurface::triangulate",DM_MSG,"took "<< getTimeString(tritimeend-tritimestart)<<", S("<getNumParticles(), 10); + myTime_t tritimeend = getTime(); + debMsgStd("IsoSurface::triangulate",DM_MSG,"took "<< getTimeString(tritimeend-tritimestart)<<", S("<getNumParticles(), 10); } @@ -714,8 +665,8 @@ void IsoSurface::triangulate( void ) * Get triangles for rendering *****************************************************************************/ void IsoSurface::getTriangles(double t, vector *triangles, - vector *vertices, - vector *normals, int objectId ) + vector *vertices, + vector *normals, int objectId ) { if(!mInitDone) { debugOut("IsoSurface::getTriangles warning: Not initialized! ", 10); @@ -724,8 +675,8 @@ void IsoSurface::getTriangles(double t, vector *triangles, t = 0.; //return; // DEBUG - /* triangulate field */ - triangulate(); + /* triangulate field */ + triangulate(); //errMsg("TRIS"," "< *triangles, //errMsg("NM"," ivi"<size()<<" ns"<size()<<" ts"<size() ); //errMsg("NM"," ovs"<push_back( mPoints[i].v ); } - for(int i=0;i<(int)mPoints.size();i++) { + for(int i=0;i<(int)mPoints.size();i++) { normals->push_back( mPoints[i].n ); } //errMsg("N2"," ivi"<size()<<" ns"<size()<<" ts"<size() ); //errMsg("N2"," ovs"< *triangles, if(getCastShadows() ) { flag |= TRI_CASTSHADOWS; } - /* init geo init id */ - int geoiId = getGeoInitId(); - if(geoiId > 0) { - flag |= (1<< (geoiId+4)); - flag |= mGeoInitType; - } + /* init geo init id */ + int geoiId = getGeoInitId(); + if(geoiId > 0) { + flag |= (1<< (geoiId+4)); + flag |= mGeoInitType; + } - tri.setFlags( flag ); + tri.setFlags( flag ); - /* triangle normal missing */ - tri.setNormal( ntlVec3Gfx(0.0) ); - tri.setSmoothNormals( smooth ); - tri.setObjectId( objectId ); - triangles->push_back( tri ); + /* triangle normal missing */ + tri.setNormal( ntlVec3Gfx(0.0) ); + tri.setSmoothNormals( smooth ); + tri.setObjectId( objectId ); + triangles->push_back( tri ); } //errMsg("N3"," ivi"<size()<<" ns"<size()<<" ts"<size() ); return; @@ -792,11 +743,11 @@ inline ntlVec3Gfx IsoSurface::getNormal(int i, int j,int k) { // WARNING - this requires a security boundary layer... ntlVec3Gfx ret(0.0); ret[0] = *getData(i-1,j ,k ) - - *getData(i+1,j ,k ); + *getData(i+1,j ,k ); ret[1] = *getData(i ,j-1,k ) - - *getData(i ,j+1,k ); + *getData(i ,j+1,k ); ret[2] = *getData(i ,j ,k-1 ) - - *getData(i ,j ,k+1 ); + *getData(i ,j ,k+1 ); return ret; } @@ -818,13 +769,13 @@ void IsoSurface::setSmoothRad(float radi1, float radi2, ntlVec3Gfx mscc) { // compute normals for all generated triangles void IsoSurface::computeNormals() { - for(int i=0;i<(int)mPoints.size();i++) { + for(int i=0;i<(int)mPoints.size();i++) { mPoints[i].n = ntlVec3Gfx(0.); } - for(int i=0;i<(int)mIndices.size();i+=3) { - const int t1 = mIndices[i]; - const int t2 = mIndices[i+1]; + for(int i=0;i<(int)mIndices.size();i+=3) { + const int t1 = mIndices[i]; + const int t2 = mIndices[i+1]; const int t3 = mIndices[i+2]; const ntlVec3Gfx p1 = mPoints[t1].v; const ntlVec3Gfx p2 = mPoints[t2].v; @@ -841,7 +792,7 @@ void IsoSurface::computeNormals() { mPoints[t3].n += norm * (1./(len2*len3)); } - for(int i=0;i<(int)mPoints.size();i++) { + for(int i=0;i<(int)mPoints.size();i++) { normalize(mPoints[i].n); } } @@ -952,86 +903,86 @@ void IsoSurface::smoothSurface(float sigma, bool normSmooth) // Edges ntlVec3Gfx e[3] = { mPoints[mIndices[i*3+2]].v - mPoints[mIndices[i*3+1]].v, - mPoints[mIndices[i*3+0]].v - mPoints[mIndices[i*3+2]].v, - mPoints[mIndices[i*3+1]].v - mPoints[mIndices[i*3+0]].v }; + mPoints[mIndices[i*3+0]].v - mPoints[mIndices[i*3+2]].v, + mPoints[mIndices[i*3+1]].v - mPoints[mIndices[i*3+0]].v }; // Compute corner weights - float area = 0.5f * norm( cross(e[0], e[1])); - float l2[3] = { normNoSqrt(e[0]), normNoSqrt(e[1]), normNoSqrt(e[2]) }; - float ew[3] = { l2[0] * (l2[1] + l2[2] - l2[0]), - l2[1] * (l2[2] + l2[0] - l2[1]), - l2[2] * (l2[0] + l2[1] - l2[2]) }; - if (ew[0] <= 0.0f) { - cornerareas[i][1] = -0.25f * l2[2] * area / - dot(e[0] , e[2]); - cornerareas[i][2] = -0.25f * l2[1] * area / - dot(e[0] , e[1]); - cornerareas[i][0] = area - cornerareas[i][1] - - cornerareas[i][2]; - } else if (ew[1] <= 0.0f) { - cornerareas[i][2] = -0.25f * l2[0] * area / - dot(e[1] , e[0]); - cornerareas[i][0] = -0.25f * l2[2] * area / - dot(e[1] , e[2]); - cornerareas[i][1] = area - cornerareas[i][2] - - cornerareas[i][0]; - } else if (ew[2] <= 0.0f) { - cornerareas[i][0] = -0.25f * l2[1] * area / - dot(e[2] , e[1]); - cornerareas[i][1] = -0.25f * l2[0] * area / - dot(e[2] , e[0]); - cornerareas[i][2] = area - cornerareas[i][0] - - cornerareas[i][1]; - } else { - float ewscale = 0.5f * area / (ew[0] + ew[1] + ew[2]); - for (int j = 0; j < 3; j++) - cornerareas[i][j] = ewscale * (ew[(j+1)%3] + - ew[(j+2)%3]); - } + float area = 0.5f * norm( cross(e[0], e[1])); + float l2[3] = { normNoSqrt(e[0]), normNoSqrt(e[1]), normNoSqrt(e[2]) }; + float ew[3] = { l2[0] * (l2[1] + l2[2] - l2[0]), + l2[1] * (l2[2] + l2[0] - l2[1]), + l2[2] * (l2[0] + l2[1] - l2[2]) }; + if (ew[0] <= 0.0f) { + cornerareas[i][1] = -0.25f * l2[2] * area / + dot(e[0] , e[2]); + cornerareas[i][2] = -0.25f * l2[1] * area / + dot(e[0] , e[1]); + cornerareas[i][0] = area - cornerareas[i][1] - + cornerareas[i][2]; + } else if (ew[1] <= 0.0f) { + cornerareas[i][2] = -0.25f * l2[0] * area / + dot(e[1] , e[0]); + cornerareas[i][0] = -0.25f * l2[2] * area / + dot(e[1] , e[2]); + cornerareas[i][1] = area - cornerareas[i][2] - + cornerareas[i][0]; + } else if (ew[2] <= 0.0f) { + cornerareas[i][0] = -0.25f * l2[1] * area / + dot(e[2] , e[1]); + cornerareas[i][1] = -0.25f * l2[0] * area / + dot(e[2] , e[0]); + cornerareas[i][2] = area - cornerareas[i][0] - + cornerareas[i][1]; + } else { + float ewscale = 0.5f * area / (ew[0] + ew[1] + ew[2]); + for (int j = 0; j < 3; j++) + cornerareas[i][j] = ewscale * (ew[(j+1)%3] + + ew[(j+2)%3]); + } // NT important, check this... #ifndef WIN32 - if(! finite(cornerareas[i][0]) ) cornerareas[i][0]=1e-6; - if(! finite(cornerareas[i][1]) ) cornerareas[i][1]=1e-6; - if(! finite(cornerareas[i][2]) ) cornerareas[i][2]=1e-6; + if(! finite(cornerareas[i][0]) ) cornerareas[i][0]=1e-6; + if(! finite(cornerareas[i][1]) ) cornerareas[i][1]=1e-6; + if(! finite(cornerareas[i][2]) ) cornerareas[i][2]=1e-6; #else // WIN32 // FIXME check as well... - if(! (cornerareas[i][0]>=0.0) ) cornerareas[i][0]=1e-6; - if(! (cornerareas[i][1]>=0.0) ) cornerareas[i][1]=1e-6; - if(! (cornerareas[i][2]>=0.0) ) cornerareas[i][2]=1e-6; + if(! (cornerareas[i][0]>=0.0) ) cornerareas[i][0]=1e-6; + if(! (cornerareas[i][1]>=0.0) ) cornerareas[i][1]=1e-6; + if(! (cornerareas[i][2]>=0.0) ) cornerareas[i][2]=1e-6; #endif // WIN32 - pointareas[mIndices[i*3+0]] += cornerareas[i][0]; - pointareas[mIndices[i*3+1]] += cornerareas[i][1]; - pointareas[mIndices[i*3+2]] += cornerareas[i][2]; + pointareas[mIndices[i*3+0]] += cornerareas[i][0]; + pointareas[mIndices[i*3+1]] += cornerareas[i][1]; + pointareas[mIndices[i*3+2]] += cornerareas[i][2]; } } // need pointarea - // */ + // */ float invsigma2 = 1.0f / (sigma*sigma); vector dflt(nv); for (int i = 0; i < nv; i++) { if(diffuseVertexField( &mPoints[0].v, 2, - i, invsigma2, dflt[i])) { + i, invsigma2, dflt[i])) { // Just keep the displacement - dflt[i] -= mPoints[i].v; - } else { dflt[i] = 0.0; } //?mPoints[i].v; } + dflt[i] -= mPoints[i].v; + } else { dflt[i] = 0.0; } //?mPoints[i].v; } } // Slightly better small-neighborhood approximation for (int i = 0; i < nf; i++) { ntlVec3Gfx c = mPoints[mIndices[i*3+0]].v + - mPoints[mIndices[i*3+1]].v + - mPoints[mIndices[i*3+2]].v; + mPoints[mIndices[i*3+1]].v + + mPoints[mIndices[i*3+2]].v; c /= 3.0f; for (int j = 0; j < 3; j++) { int v = mIndices[i*3+j]; ntlVec3Gfx d =(c - mPoints[v].v) * 0.5f; dflt[v] += d * (cornerareas[i][j] / - pointareas[mIndices[i*3+j]] * - exp(-0.5f * invsigma2 * normNoSqrt(d)) ); + pointareas[mIndices[i*3+j]] * + exp(-0.5f * invsigma2 * normNoSqrt(d)) ); } } @@ -1039,7 +990,7 @@ void IsoSurface::smoothSurface(float sigma, bool normSmooth) vector dflt2(nv); for (int i = 0; i < nv; i++) { if(diffuseVertexField( &dflt[0], 1, - i, invsigma2, dflt2[i])) { } + i, invsigma2, dflt2[i])) { } else { /*mPoints[i].v=0.0;*/ dflt2[i] = 0.0; }//dflt2[i]; } } @@ -1111,58 +1062,58 @@ void IsoSurface::smoothNormals(float sigma) { // Edges ntlVec3Gfx e[3] = { mPoints[mIndices[i*3+2]].v - mPoints[mIndices[i*3+1]].v, - mPoints[mIndices[i*3+0]].v - mPoints[mIndices[i*3+2]].v, - mPoints[mIndices[i*3+1]].v - mPoints[mIndices[i*3+0]].v }; + mPoints[mIndices[i*3+0]].v - mPoints[mIndices[i*3+2]].v, + mPoints[mIndices[i*3+1]].v - mPoints[mIndices[i*3+0]].v }; // Compute corner weights - float area = 0.5f * norm( cross(e[0], e[1])); - float l2[3] = { normNoSqrt(e[0]), normNoSqrt(e[1]), normNoSqrt(e[2]) }; - float ew[3] = { l2[0] * (l2[1] + l2[2] - l2[0]), - l2[1] * (l2[2] + l2[0] - l2[1]), - l2[2] * (l2[0] + l2[1] - l2[2]) }; - if (ew[0] <= 0.0f) { - cornerareas[i][1] = -0.25f * l2[2] * area / - dot(e[0] , e[2]); - cornerareas[i][2] = -0.25f * l2[1] * area / - dot(e[0] , e[1]); - cornerareas[i][0] = area - cornerareas[i][1] - - cornerareas[i][2]; - } else if (ew[1] <= 0.0f) { - cornerareas[i][2] = -0.25f * l2[0] * area / - dot(e[1] , e[0]); - cornerareas[i][0] = -0.25f * l2[2] * area / - dot(e[1] , e[2]); - cornerareas[i][1] = area - cornerareas[i][2] - - cornerareas[i][0]; - } else if (ew[2] <= 0.0f) { - cornerareas[i][0] = -0.25f * l2[1] * area / - dot(e[2] , e[1]); - cornerareas[i][1] = -0.25f * l2[0] * area / - dot(e[2] , e[0]); - cornerareas[i][2] = area - cornerareas[i][0] - - cornerareas[i][1]; - } else { - float ewscale = 0.5f * area / (ew[0] + ew[1] + ew[2]); - for (int j = 0; j < 3; j++) - cornerareas[i][j] = ewscale * (ew[(j+1)%3] + - ew[(j+2)%3]); - } + float area = 0.5f * norm( cross(e[0], e[1])); + float l2[3] = { normNoSqrt(e[0]), normNoSqrt(e[1]), normNoSqrt(e[2]) }; + float ew[3] = { l2[0] * (l2[1] + l2[2] - l2[0]), + l2[1] * (l2[2] + l2[0] - l2[1]), + l2[2] * (l2[0] + l2[1] - l2[2]) }; + if (ew[0] <= 0.0f) { + cornerareas[i][1] = -0.25f * l2[2] * area / + dot(e[0] , e[2]); + cornerareas[i][2] = -0.25f * l2[1] * area / + dot(e[0] , e[1]); + cornerareas[i][0] = area - cornerareas[i][1] - + cornerareas[i][2]; + } else if (ew[1] <= 0.0f) { + cornerareas[i][2] = -0.25f * l2[0] * area / + dot(e[1] , e[0]); + cornerareas[i][0] = -0.25f * l2[2] * area / + dot(e[1] , e[2]); + cornerareas[i][1] = area - cornerareas[i][2] - + cornerareas[i][0]; + } else if (ew[2] <= 0.0f) { + cornerareas[i][0] = -0.25f * l2[1] * area / + dot(e[2] , e[1]); + cornerareas[i][1] = -0.25f * l2[0] * area / + dot(e[2] , e[0]); + cornerareas[i][2] = area - cornerareas[i][0] - + cornerareas[i][1]; + } else { + float ewscale = 0.5f * area / (ew[0] + ew[1] + ew[2]); + for (int j = 0; j < 3; j++) + cornerareas[i][j] = ewscale * (ew[(j+1)%3] + + ew[(j+2)%3]); + } // NT important, check this... #ifndef WIN32 - if(! finite(cornerareas[i][0]) ) cornerareas[i][0]=1e-6; - if(! finite(cornerareas[i][1]) ) cornerareas[i][1]=1e-6; - if(! finite(cornerareas[i][2]) ) cornerareas[i][2]=1e-6; + if(! finite(cornerareas[i][0]) ) cornerareas[i][0]=1e-6; + if(! finite(cornerareas[i][1]) ) cornerareas[i][1]=1e-6; + if(! finite(cornerareas[i][2]) ) cornerareas[i][2]=1e-6; #else // WIN32 // FIXME check as well... - if(! (cornerareas[i][0]>=0.0) ) cornerareas[i][0]=1e-6; - if(! (cornerareas[i][1]>=0.0) ) cornerareas[i][1]=1e-6; - if(! (cornerareas[i][2]>=0.0) ) cornerareas[i][2]=1e-6; + if(! (cornerareas[i][0]>=0.0) ) cornerareas[i][0]=1e-6; + if(! (cornerareas[i][1]>=0.0) ) cornerareas[i][1]=1e-6; + if(! (cornerareas[i][2]>=0.0) ) cornerareas[i][2]=1e-6; #endif // WIN32 - pointareas[mIndices[i*3+0]] += cornerareas[i][0]; - pointareas[mIndices[i*3+1]] += cornerareas[i][1]; - pointareas[mIndices[i*3+2]] += cornerareas[i][2]; + pointareas[mIndices[i*3+0]] += cornerareas[i][0]; + pointareas[mIndices[i*3+1]] += cornerareas[i][1]; + pointareas[mIndices[i*3+2]] += cornerareas[i][2]; } } // need pointarea diff --git a/intern/elbeem/intern/loop_tools.h b/intern/elbeem/intern/loop_tools.h index 70ecb9ce3e0..163965901e8 100644 --- a/intern/elbeem/intern/loop_tools.h +++ b/intern/elbeem/intern/loop_tools.h @@ -34,7 +34,7 @@ // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> #define GRID_REGION_START() \ - { /* main_region */ \ +{ /* main_region */ \ int kstart=getForZMinBnd(), kend=getForZMaxBnd(mMaxRefine); \ if(gridLoopBound>0){ kstart=getForZMin1(), kend=getForZMax1(mMaxRefine); } \ int kdir = 1; \ @@ -49,7 +49,7 @@ kend = kstart-1; \ kstart = temp-1; \ temp = id; /* dummy remove warning */ \ - } \ +} \ @@ -74,13 +74,13 @@ // loop start #define GRID_REGION_START() \ - { \ +{ \ \ \ if(mSizez<2) { \ mPanic = 1; \ errFatal("ParaLoop::2D","Not valid...!", SIMWORLD_GENERICERROR); \ - } \ +} \ \ \ vector calcListFull; \ @@ -113,14 +113,14 @@ int temp = kend; \ kend = kstart-1; \ kstart = temp-1; \ - } \ +} \ \ const int Nj = mLevel[mMaxRefine].lSizey; \ int jstart = 0+( id * (Nj / Nthrds) ); \ int jend = 0+( (id+1) * (Nj / Nthrds) ); \ if( ((Nj/Nthrds) *Nthrds) != Nj) { \ errMsg("LbmFsgrSolver","Invalid domain size Nj="<::iterator pit= mpIsoParts->getParticlesBegin(); - pit!= mpIsoParts->getParticlesEnd(); pit++) { - if( (*pit).getActive()==false ) continue; - if( (*pit).getType()!=PART_DROP) continue; - (*pit).setNext(NULL); - } + for(int k=0;k<(mSizez);k++) + for(int j=0;j<(mSizey);j++) + for(int i=0;i<(mSizex);i++) { + arppnt[ISOLEVEL_INDEX(i,j,k)] = NULL; + } + if(mpIsoParts) { + for(vector::iterator pit= mpIsoParts->getParticlesBegin(); + pit!= mpIsoParts->getParticlesEnd(); pit++) { + if( (*pit).getActive()==false ) continue; + if( (*pit).getType()!=PART_DROP) continue; + (*pit).setNext(NULL); + } // build per node lists - for(vector::iterator pit= mpIsoParts->getParticlesBegin(); - pit!= mpIsoParts->getParticlesEnd(); pit++) { - if( (*pit).getActive()==false ) continue; - if( (*pit).getType()!=PART_DROP) continue; + for(vector::iterator pit= mpIsoParts->getParticlesBegin(); + pit!= mpIsoParts->getParticlesEnd(); pit++) { + if( (*pit).getActive()==false ) continue; + if( (*pit).getType()!=PART_DROP) continue; // check lifetime ignored here - ParticleObject *p = &(*pit); - const ntlVec3Gfx ppos = p->getPos(); - const int pi= (int)round(ppos[0])+0; - const int pj= (int)round(ppos[1])+0; - int pk= (int)round(ppos[2])+0;// no offset necessary + ParticleObject *p = &(*pit); + const ntlVec3Gfx ppos = p->getPos(); + const int pi= (int)round(ppos[0])+0; + const int pj= (int)round(ppos[1])+0; + int pk= (int)round(ppos[2])+0;// no offset necessary // 2d should be handled by solver. if(LBMDIM==2) { pk = 0; } - if(pi<0) continue; - if(pj<0) continue; - if(pk<0) continue; - if(pi>mSizex-1) continue; - if(pj>mSizey-1) continue; - if(pk>mSizez-1) continue; - ParticleObject* &pnt = arppnt[ISOLEVEL_INDEX(pi,pj,pk)]; - if(pnt) { + if(pi<0) continue; + if(pj<0) continue; + if(pk<0) continue; + if(pi>mSizex-1) continue; + if(pj>mSizey-1) continue; + if(pk>mSizez-1) continue; + ParticleObject* &pnt = arppnt[ISOLEVEL_INDEX(pi,pj,pk)]; + if(pnt) { // append - ParticleObject* listpnt = pnt; - while(listpnt) { - if(!listpnt->getNext()) { - listpnt->setNext(p); listpnt = NULL; - } else { - listpnt = listpnt->getNext(); - } - } - } else { + ParticleObject* listpnt = pnt; + while(listpnt) { + if(!listpnt->getNext()) { + listpnt->setNext(p); listpnt = NULL; + } else { + listpnt = listpnt->getNext(); + } + } + } else { // start new list - pnt = p; - } - pInUse++; - } - } // mpIsoParts + pnt = p; + } + pInUse++; + } + } // mpIsoParts - debMsgStd("IsoSurface::triangulate",DM_MSG,"Starting. Parts in use:"<=mSizez-1) continue; - for(int poj=-poDistOffset; poj<1+poDistOffset; poj++) { - if(j+poj<0) continue; - if(j+poj>=mSizey-1) continue; - for(int poi=-poDistOffset; poi<1+poDistOffset; poi++) { - if(i+poi<0) continue; - if(i+poi>=mSizex-1) continue; - ParticleObject *p; - p = arppnt[ISOLEVEL_INDEX(i+poi,j+poj,k+pok)]; - while(p) { // */ + const int poDistOffset=2; + for(int pok=-poDistOffset; pok<1+poDistOffset; pok++) { + if(k+pok<0) continue; + if(k+pok>=mSizez-1) continue; + for(int poj=-poDistOffset; poj<1+poDistOffset; poj++) { + if(j+poj<0) continue; + if(j+poj>=mSizey-1) continue; + for(int poi=-poDistOffset; poi<1+poDistOffset; poi++) { + if(i+poi<0) continue; + if(i+poi>=mSizex-1) continue; + ParticleObject *p; + p = arppnt[ISOLEVEL_INDEX(i+poi,j+poj,k+pok)]; + while(p) { // */ /* - for(vector::iterator pit= mpIsoParts->getParticlesBegin(); - pit!= mpIsoParts->getParticlesEnd(); pit++) { { { { + for(vector::iterator pit= mpIsoParts->getParticlesBegin(); + pit!= mpIsoParts->getParticlesEnd(); pit++) { { { { // debug test! , full list slow! - if(( (*pit).getActive()==false ) || ( (*pit).getType()!=PART_DROP)) continue; - ParticleObject *p; - p = &(*pit); // */ + if(( (*pit).getActive()==false ) || ( (*pit).getType()!=PART_DROP)) continue; + ParticleObject *p; + p = &(*pit); // */ - pUsedTest++; - ntlVec3Gfx ppos = p->getPos(); - const int spi= (int)round( (ppos[0]+1.-(gfxReal)i) *(gfxReal)mSubdivs-1.5); - const int spj= (int)round( (ppos[1]+1.-(gfxReal)j) *(gfxReal)mSubdivs-1.5); - const int spk= (int)round( (ppos[2]+1.-(gfxReal)k) *(gfxReal)mSubdivs-1.5)-sdkOffset; // why -2? + pUsedTest++; + ntlVec3Gfx ppos = p->getPos(); + const int spi= (int)round( (ppos[0]+1.-(gfxReal)i) *(gfxReal)mSubdivs-1.5); + const int spj= (int)round( (ppos[1]+1.-(gfxReal)j) *(gfxReal)mSubdivs-1.5); + const int spk= (int)round( (ppos[2]+1.-(gfxReal)k) *(gfxReal)mSubdivs-1.5)-sdkOffset; // why -2? // 2d should be handled by solver. if(LBMDIM==2) { spk = 0; } - gfxReal pfLen = p->getSize()*1.5*mPartSize; // test, was 1.1 - const gfxReal minPfLen = subdfac*0.8; - if(pfLengetSize()*1.5*mPartSize; // test, was 1.1 + const gfxReal minPfLen = subdfac*0.8; + if(pfLengetSize()<<" ps"< 1) { continue; } // */ - for(int swj=-icellpsize; swj<=icellpsize; swj++) { - if(spj+swj< 0) { continue; } - if(spj+swj>mSubdivs+0) { continue; } // */ - for(int swi=-icellpsize; swi<=icellpsize; swi++) { - if(spi+swi< 0) { continue; } - if(spi+swi>mSubdivs+0) { continue; } // */ - ntlVec3Gfx cellp = ntlVec3Gfx( + const int icellpsize = (int)(1.*pfLen*(gfxReal)mSubdivs)+1; + for(int swk=-icellpsize; swk<=icellpsize; swk++) { + if(spk+swk< 0) { continue; } + if(spk+swk> 1) { continue; } // */ + for(int swj=-icellpsize; swj<=icellpsize; swj++) { + if(spj+swj< 0) { continue; } + if(spj+swj>mSubdivs+0) { continue; } // */ + for(int swi=-icellpsize; swi<=icellpsize; swi++) { + if(spi+swi< 0) { continue; } + if(spi+swi>mSubdivs+0) { continue; } // */ + ntlVec3Gfx cellp = ntlVec3Gfx( (1.5+(gfxReal)(spi+swi)) *subdfac + (gfxReal)(i-1), (1.5+(gfxReal)(spj+swj)) *subdfac + (gfxReal)(j-1), (1.5+(gfxReal)(spk+swk)+sdkOffset) *subdfac + (gfxReal)(k-1) ); //if(swi==0 && swj==0 && swk==0) subdAr[spk][spj][spi] = 1.; // DEBUG // clip domain boundaries again - if(cellp[0]<1.) { continue; } - if(cellp[1]<1.) { continue; } - if(cellp[2]<1.) { continue; } - if(cellp[0]>(gfxReal)mSizex-3.) { continue; } - if(cellp[1]>(gfxReal)mSizey-3.) { continue; } - if(cellp[2]>(gfxReal)mSizez-3.) { continue; } - gfxReal len = norm(cellp-ppos); - gfxReal isoadd = 0.; - const gfxReal baseIsoVal = mIsoValue*1.1; - if(len(gfxReal)mSizex-3.) { continue; } + if(cellp[1]>(gfxReal)mSizey-3.) { continue; } + if(cellp[2]>(gfxReal)mSizez-3.) { continue; } + gfxReal len = norm(cellp-ppos); + gfxReal isoadd = 0.; + const gfxReal baseIsoVal = mIsoValue*1.1; + if(len1.) { continue; } - subdAr[spk+swk][spj+swj][spi+swi] = arval + isoadd; - } } } + const gfxReal arval = subdAr[spk+swk][spj+swj][spi+swi]; + if(arval>1.) { continue; } + subdAr[spk+swk][spj+swj][spi+swi] = arval + isoadd; + } } } - p = p->getNext(); - } - } } } // poDist loops */ + p = p->getNext(); + } + } } } // poDist loops */ - py = mStart[1]+(((double)j-0.5)*orgGsy)-gsy; - for(int sj=0;sj 0) { + if (mcEdgeTable[cubeIndex] > 0) { // where to look up if this point already exists - const int edgek = 0; - const int baseIn = EDGEAR_INDEX( i+0, j+0, edgek+0, si,sj); - eVert[ 0] = &mpEdgeVerticesX[ baseIn ]; - eVert[ 1] = &mpEdgeVerticesY[ baseIn + 1 ]; - eVert[ 2] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+0, si+0,sj+1) ]; - eVert[ 3] = &mpEdgeVerticesY[ baseIn ]; + const int edgek = 0; + const int baseIn = EDGEAR_INDEX( i+0, j+0, edgek+0, si,sj); + eVert[ 0] = &mpEdgeVerticesX[ baseIn ]; + eVert[ 1] = &mpEdgeVerticesY[ baseIn + 1 ]; + eVert[ 2] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+0, si+0,sj+1) ]; + eVert[ 3] = &mpEdgeVerticesY[ baseIn ]; - eVert[ 4] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+0) ]; - eVert[ 5] = &mpEdgeVerticesY[ EDGEAR_INDEX( i, j, edgek+1, si+1,sj+0) ]; // with subdivs - eVert[ 6] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+1) ]; - eVert[ 7] = &mpEdgeVerticesY[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+0) ]; + eVert[ 4] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+0) ]; + eVert[ 5] = &mpEdgeVerticesY[ EDGEAR_INDEX( i, j, edgek+1, si+1,sj+0) ]; // with subdivs + eVert[ 6] = &mpEdgeVerticesX[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+1) ]; + eVert[ 7] = &mpEdgeVerticesY[ EDGEAR_INDEX( i, j, edgek+1, si+0,sj+0) ]; - eVert[ 8] = &mpEdgeVerticesZ[ baseIn ]; - eVert[ 9] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+1,sj+0) ]; // with subdivs - eVert[10] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+1,sj+1) ]; - eVert[11] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+0,sj+1) ]; + eVert[ 8] = &mpEdgeVerticesZ[ baseIn ]; + eVert[ 9] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+1,sj+0) ]; // with subdivs + eVert[10] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+1,sj+1) ]; + eVert[11] = &mpEdgeVerticesZ[ EDGEAR_INDEX( i, j, edgek+0, si+0,sj+1) ]; // grid positions - pos[0] = ntlVec3Gfx(px ,py ,pz); - pos[1] = ntlVec3Gfx(px+gsx,py ,pz); - pos[2] = ntlVec3Gfx(px+gsx,py+gsy,pz); // with subdivs - pos[3] = ntlVec3Gfx(px ,py+gsy,pz); - pos[4] = ntlVec3Gfx(px ,py ,pz+gsz); - pos[5] = ntlVec3Gfx(px+gsx,py ,pz+gsz); - pos[6] = ntlVec3Gfx(px+gsx,py+gsy,pz+gsz); // with subdivs - pos[7] = ntlVec3Gfx(px ,py+gsy,pz+gsz); + pos[0] = ntlVec3Gfx(px ,py ,pz); + pos[1] = ntlVec3Gfx(px+gsx,py ,pz); + pos[2] = ntlVec3Gfx(px+gsx,py+gsy,pz); // with subdivs + pos[3] = ntlVec3Gfx(px ,py+gsy,pz); + pos[4] = ntlVec3Gfx(px ,py ,pz+gsz); + pos[5] = ntlVec3Gfx(px+gsx,py ,pz+gsz); + pos[6] = ntlVec3Gfx(px+gsx,py+gsy,pz+gsz); // with subdivs + pos[7] = ntlVec3Gfx(px ,py+gsy,pz+gsz); // check all edges - for(int e=0;e<12;e++) { - if (mcEdgeTable[cubeIndex] & (1<0) { + float smoSubdfac = 1.; + if(mSubdivs>0) { //smoSubdfac = 1./(float)(mSubdivs); - smoSubdfac = pow(0.55,(double)mSubdivs); // slightly stronger - } - if(mSmoothSurface>0. || mSmoothNormals>0.) debMsgStd("IsoSurface::triangulate",DM_MSG,"Smoothing...",10); - if(mSmoothSurface>0.0) { - smoothSurface(mSmoothSurface*smoSubdfac, (mSmoothNormals<=0.0) ); - } - if(mSmoothNormals>0.0) { - smoothNormals(mSmoothNormals*smoSubdfac); - } + smoSubdfac = pow(0.55,(double)mSubdivs); // slightly stronger + } + if(mSmoothSurface>0. || mSmoothNormals>0.) debMsgStd("IsoSurface::triangulate",DM_MSG,"Smoothing...",10); + if(mSmoothSurface>0.0) { + smoothSurface(mSmoothSurface*smoSubdfac, (mSmoothNormals<=0.0) ); + } + if(mSmoothNormals>0.0) { + smoothNormals(mSmoothNormals*smoSubdfac); + } - myTime_t tritimeend = getTime(); - debMsgStd("IsoSurface::triangulate",DM_MSG,"took "<< getTimeString(tritimeend-tritimestart)<<", S("<getNumParticles(), 10); + myTime_t tritimeend = getTime(); + debMsgStd("IsoSurface::triangulate",DM_MSG,"took "<< getTimeString(tritimeend-tritimestart)<<", S("<getNumParticles(), 10); } @@ -665,8 +677,8 @@ void IsoSurface::triangulate( void ) * Get triangles for rendering *****************************************************************************/ void IsoSurface::getTriangles(double t, vector *triangles, - vector *vertices, - vector *normals, int objectId ) + vector *vertices, + vector *normals, int objectId ) { if(!mInitDone) { debugOut("IsoSurface::getTriangles warning: Not initialized! ", 10); @@ -675,8 +687,8 @@ void IsoSurface::getTriangles(double t, vector *triangles, t = 0.; //return; // DEBUG - /* triangulate field */ - triangulate(); + /* triangulate field */ + triangulate(); //errMsg("TRIS"," "< *triangles, //errMsg("NM"," ivi"<size()<<" ns"<size()<<" ts"<size() ); //errMsg("NM"," ovs"<push_back( mPoints[i].v ); } - for(int i=0;i<(int)mPoints.size();i++) { + for(int i=0;i<(int)mPoints.size();i++) { normals->push_back( mPoints[i].n ); } //errMsg("N2"," ivi"<size()<<" ns"<size()<<" ts"<size() ); //errMsg("N2"," ovs"< *triangles, if(getCastShadows() ) { flag |= TRI_CASTSHADOWS; } - /* init geo init id */ - int geoiId = getGeoInitId(); - if(geoiId > 0) { - flag |= (1<< (geoiId+4)); - flag |= mGeoInitType; - } + /* init geo init id */ + int geoiId = getGeoInitId(); + if(geoiId > 0) { + flag |= (1<< (geoiId+4)); + flag |= mGeoInitType; + } - tri.setFlags( flag ); + tri.setFlags( flag ); - /* triangle normal missing */ - tri.setNormal( ntlVec3Gfx(0.0) ); - tri.setSmoothNormals( smooth ); - tri.setObjectId( objectId ); - triangles->push_back( tri ); + /* triangle normal missing */ + tri.setNormal( ntlVec3Gfx(0.0) ); + tri.setSmoothNormals( smooth ); + tri.setObjectId( objectId ); + triangles->push_back( tri ); } //errMsg("N3"," ivi"<size()<<" ns"<size()<<" ts"<size() ); return; @@ -743,11 +755,11 @@ inline ntlVec3Gfx IsoSurface::getNormal(int i, int j,int k) { // WARNING - this requires a security boundary layer... ntlVec3Gfx ret(0.0); ret[0] = *getData(i-1,j ,k ) - - *getData(i+1,j ,k ); + *getData(i+1,j ,k ); ret[1] = *getData(i ,j-1,k ) - - *getData(i ,j+1,k ); + *getData(i ,j+1,k ); ret[2] = *getData(i ,j ,k-1 ) - - *getData(i ,j ,k+1 ); + *getData(i ,j ,k+1 ); return ret; } @@ -769,13 +781,13 @@ void IsoSurface::setSmoothRad(float radi1, float radi2, ntlVec3Gfx mscc) { // compute normals for all generated triangles void IsoSurface::computeNormals() { - for(int i=0;i<(int)mPoints.size();i++) { + for(int i=0;i<(int)mPoints.size();i++) { mPoints[i].n = ntlVec3Gfx(0.); } - for(int i=0;i<(int)mIndices.size();i+=3) { - const int t1 = mIndices[i]; - const int t2 = mIndices[i+1]; + for(int i=0;i<(int)mIndices.size();i+=3) { + const int t1 = mIndices[i]; + const int t2 = mIndices[i+1]; const int t3 = mIndices[i+2]; const ntlVec3Gfx p1 = mPoints[t1].v; const ntlVec3Gfx p2 = mPoints[t2].v; @@ -792,7 +804,7 @@ void IsoSurface::computeNormals() { mPoints[t3].n += norm * (1./(len2*len3)); } - for(int i=0;i<(int)mPoints.size();i++) { + for(int i=0;i<(int)mPoints.size();i++) { normalize(mPoints[i].n); } } @@ -903,86 +915,86 @@ void IsoSurface::smoothSurface(float sigma, bool normSmooth) // Edges ntlVec3Gfx e[3] = { mPoints[mIndices[i*3+2]].v - mPoints[mIndices[i*3+1]].v, - mPoints[mIndices[i*3+0]].v - mPoints[mIndices[i*3+2]].v, - mPoints[mIndices[i*3+1]].v - mPoints[mIndices[i*3+0]].v }; + mPoints[mIndices[i*3+0]].v - mPoints[mIndices[i*3+2]].v, + mPoints[mIndices[i*3+1]].v - mPoints[mIndices[i*3+0]].v }; // Compute corner weights - float area = 0.5f * norm( cross(e[0], e[1])); - float l2[3] = { normNoSqrt(e[0]), normNoSqrt(e[1]), normNoSqrt(e[2]) }; - float ew[3] = { l2[0] * (l2[1] + l2[2] - l2[0]), - l2[1] * (l2[2] + l2[0] - l2[1]), - l2[2] * (l2[0] + l2[1] - l2[2]) }; - if (ew[0] <= 0.0f) { - cornerareas[i][1] = -0.25f * l2[2] * area / - dot(e[0] , e[2]); - cornerareas[i][2] = -0.25f * l2[1] * area / - dot(e[0] , e[1]); - cornerareas[i][0] = area - cornerareas[i][1] - - cornerareas[i][2]; - } else if (ew[1] <= 0.0f) { - cornerareas[i][2] = -0.25f * l2[0] * area / - dot(e[1] , e[0]); - cornerareas[i][0] = -0.25f * l2[2] * area / - dot(e[1] , e[2]); - cornerareas[i][1] = area - cornerareas[i][2] - - cornerareas[i][0]; - } else if (ew[2] <= 0.0f) { - cornerareas[i][0] = -0.25f * l2[1] * area / - dot(e[2] , e[1]); - cornerareas[i][1] = -0.25f * l2[0] * area / - dot(e[2] , e[0]); - cornerareas[i][2] = area - cornerareas[i][0] - - cornerareas[i][1]; - } else { - float ewscale = 0.5f * area / (ew[0] + ew[1] + ew[2]); - for (int j = 0; j < 3; j++) - cornerareas[i][j] = ewscale * (ew[(j+1)%3] + - ew[(j+2)%3]); - } + float area = 0.5f * norm( cross(e[0], e[1])); + float l2[3] = { normNoSqrt(e[0]), normNoSqrt(e[1]), normNoSqrt(e[2]) }; + float ew[3] = { l2[0] * (l2[1] + l2[2] - l2[0]), + l2[1] * (l2[2] + l2[0] - l2[1]), + l2[2] * (l2[0] + l2[1] - l2[2]) }; + if (ew[0] <= 0.0f) { + cornerareas[i][1] = -0.25f * l2[2] * area / + dot(e[0] , e[2]); + cornerareas[i][2] = -0.25f * l2[1] * area / + dot(e[0] , e[1]); + cornerareas[i][0] = area - cornerareas[i][1] - + cornerareas[i][2]; + } else if (ew[1] <= 0.0f) { + cornerareas[i][2] = -0.25f * l2[0] * area / + dot(e[1] , e[0]); + cornerareas[i][0] = -0.25f * l2[2] * area / + dot(e[1] , e[2]); + cornerareas[i][1] = area - cornerareas[i][2] - + cornerareas[i][0]; + } else if (ew[2] <= 0.0f) { + cornerareas[i][0] = -0.25f * l2[1] * area / + dot(e[2] , e[1]); + cornerareas[i][1] = -0.25f * l2[0] * area / + dot(e[2] , e[0]); + cornerareas[i][2] = area - cornerareas[i][0] - + cornerareas[i][1]; + } else { + float ewscale = 0.5f * area / (ew[0] + ew[1] + ew[2]); + for (int j = 0; j < 3; j++) + cornerareas[i][j] = ewscale * (ew[(j+1)%3] + + ew[(j+2)%3]); + } // NT important, check this... #ifndef WIN32 - if(! finite(cornerareas[i][0]) ) cornerareas[i][0]=1e-6; - if(! finite(cornerareas[i][1]) ) cornerareas[i][1]=1e-6; - if(! finite(cornerareas[i][2]) ) cornerareas[i][2]=1e-6; + if(! finite(cornerareas[i][0]) ) cornerareas[i][0]=1e-6; + if(! finite(cornerareas[i][1]) ) cornerareas[i][1]=1e-6; + if(! finite(cornerareas[i][2]) ) cornerareas[i][2]=1e-6; #else // WIN32 // FIXME check as well... - if(! (cornerareas[i][0]>=0.0) ) cornerareas[i][0]=1e-6; - if(! (cornerareas[i][1]>=0.0) ) cornerareas[i][1]=1e-6; - if(! (cornerareas[i][2]>=0.0) ) cornerareas[i][2]=1e-6; + if(! (cornerareas[i][0]>=0.0) ) cornerareas[i][0]=1e-6; + if(! (cornerareas[i][1]>=0.0) ) cornerareas[i][1]=1e-6; + if(! (cornerareas[i][2]>=0.0) ) cornerareas[i][2]=1e-6; #endif // WIN32 - pointareas[mIndices[i*3+0]] += cornerareas[i][0]; - pointareas[mIndices[i*3+1]] += cornerareas[i][1]; - pointareas[mIndices[i*3+2]] += cornerareas[i][2]; + pointareas[mIndices[i*3+0]] += cornerareas[i][0]; + pointareas[mIndices[i*3+1]] += cornerareas[i][1]; + pointareas[mIndices[i*3+2]] += cornerareas[i][2]; } } // need pointarea - // */ + // */ float invsigma2 = 1.0f / (sigma*sigma); vector dflt(nv); for (int i = 0; i < nv; i++) { if(diffuseVertexField( &mPoints[0].v, 2, - i, invsigma2, dflt[i])) { + i, invsigma2, dflt[i])) { // Just keep the displacement - dflt[i] -= mPoints[i].v; - } else { dflt[i] = 0.0; } //?mPoints[i].v; } + dflt[i] -= mPoints[i].v; + } else { dflt[i] = 0.0; } //?mPoints[i].v; } } // Slightly better small-neighborhood approximation for (int i = 0; i < nf; i++) { ntlVec3Gfx c = mPoints[mIndices[i*3+0]].v + - mPoints[mIndices[i*3+1]].v + - mPoints[mIndices[i*3+2]].v; + mPoints[mIndices[i*3+1]].v + + mPoints[mIndices[i*3+2]].v; c /= 3.0f; for (int j = 0; j < 3; j++) { int v = mIndices[i*3+j]; ntlVec3Gfx d =(c - mPoints[v].v) * 0.5f; dflt[v] += d * (cornerareas[i][j] / - pointareas[mIndices[i*3+j]] * - exp(-0.5f * invsigma2 * normNoSqrt(d)) ); + pointareas[mIndices[i*3+j]] * + exp(-0.5f * invsigma2 * normNoSqrt(d)) ); } } @@ -990,7 +1002,7 @@ void IsoSurface::smoothSurface(float sigma, bool normSmooth) vector dflt2(nv); for (int i = 0; i < nv; i++) { if(diffuseVertexField( &dflt[0], 1, - i, invsigma2, dflt2[i])) { } + i, invsigma2, dflt2[i])) { } else { /*mPoints[i].v=0.0;*/ dflt2[i] = 0.0; }//dflt2[i]; } } @@ -1062,58 +1074,58 @@ void IsoSurface::smoothNormals(float sigma) { // Edges ntlVec3Gfx e[3] = { mPoints[mIndices[i*3+2]].v - mPoints[mIndices[i*3+1]].v, - mPoints[mIndices[i*3+0]].v - mPoints[mIndices[i*3+2]].v, - mPoints[mIndices[i*3+1]].v - mPoints[mIndices[i*3+0]].v }; + mPoints[mIndices[i*3+0]].v - mPoints[mIndices[i*3+2]].v, + mPoints[mIndices[i*3+1]].v - mPoints[mIndices[i*3+0]].v }; // Compute corner weights - float area = 0.5f * norm( cross(e[0], e[1])); - float l2[3] = { normNoSqrt(e[0]), normNoSqrt(e[1]), normNoSqrt(e[2]) }; - float ew[3] = { l2[0] * (l2[1] + l2[2] - l2[0]), - l2[1] * (l2[2] + l2[0] - l2[1]), - l2[2] * (l2[0] + l2[1] - l2[2]) }; - if (ew[0] <= 0.0f) { - cornerareas[i][1] = -0.25f * l2[2] * area / - dot(e[0] , e[2]); - cornerareas[i][2] = -0.25f * l2[1] * area / - dot(e[0] , e[1]); - cornerareas[i][0] = area - cornerareas[i][1] - - cornerareas[i][2]; - } else if (ew[1] <= 0.0f) { - cornerareas[i][2] = -0.25f * l2[0] * area / - dot(e[1] , e[0]); - cornerareas[i][0] = -0.25f * l2[2] * area / - dot(e[1] , e[2]); - cornerareas[i][1] = area - cornerareas[i][2] - - cornerareas[i][0]; - } else if (ew[2] <= 0.0f) { - cornerareas[i][0] = -0.25f * l2[1] * area / - dot(e[2] , e[1]); - cornerareas[i][1] = -0.25f * l2[0] * area / - dot(e[2] , e[0]); - cornerareas[i][2] = area - cornerareas[i][0] - - cornerareas[i][1]; - } else { - float ewscale = 0.5f * area / (ew[0] + ew[1] + ew[2]); - for (int j = 0; j < 3; j++) - cornerareas[i][j] = ewscale * (ew[(j+1)%3] + - ew[(j+2)%3]); - } + float area = 0.5f * norm( cross(e[0], e[1])); + float l2[3] = { normNoSqrt(e[0]), normNoSqrt(e[1]), normNoSqrt(e[2]) }; + float ew[3] = { l2[0] * (l2[1] + l2[2] - l2[0]), + l2[1] * (l2[2] + l2[0] - l2[1]), + l2[2] * (l2[0] + l2[1] - l2[2]) }; + if (ew[0] <= 0.0f) { + cornerareas[i][1] = -0.25f * l2[2] * area / + dot(e[0] , e[2]); + cornerareas[i][2] = -0.25f * l2[1] * area / + dot(e[0] , e[1]); + cornerareas[i][0] = area - cornerareas[i][1] - + cornerareas[i][2]; + } else if (ew[1] <= 0.0f) { + cornerareas[i][2] = -0.25f * l2[0] * area / + dot(e[1] , e[0]); + cornerareas[i][0] = -0.25f * l2[2] * area / + dot(e[1] , e[2]); + cornerareas[i][1] = area - cornerareas[i][2] - + cornerareas[i][0]; + } else if (ew[2] <= 0.0f) { + cornerareas[i][0] = -0.25f * l2[1] * area / + dot(e[2] , e[1]); + cornerareas[i][1] = -0.25f * l2[0] * area / + dot(e[2] , e[0]); + cornerareas[i][2] = area - cornerareas[i][0] - + cornerareas[i][1]; + } else { + float ewscale = 0.5f * area / (ew[0] + ew[1] + ew[2]); + for (int j = 0; j < 3; j++) + cornerareas[i][j] = ewscale * (ew[(j+1)%3] + + ew[(j+2)%3]); + } // NT important, check this... #ifndef WIN32 - if(! finite(cornerareas[i][0]) ) cornerareas[i][0]=1e-6; - if(! finite(cornerareas[i][1]) ) cornerareas[i][1]=1e-6; - if(! finite(cornerareas[i][2]) ) cornerareas[i][2]=1e-6; + if(! finite(cornerareas[i][0]) ) cornerareas[i][0]=1e-6; + if(! finite(cornerareas[i][1]) ) cornerareas[i][1]=1e-6; + if(! finite(cornerareas[i][2]) ) cornerareas[i][2]=1e-6; #else // WIN32 // FIXME check as well... - if(! (cornerareas[i][0]>=0.0) ) cornerareas[i][0]=1e-6; - if(! (cornerareas[i][1]>=0.0) ) cornerareas[i][1]=1e-6; - if(! (cornerareas[i][2]>=0.0) ) cornerareas[i][2]=1e-6; + if(! (cornerareas[i][0]>=0.0) ) cornerareas[i][0]=1e-6; + if(! (cornerareas[i][1]>=0.0) ) cornerareas[i][1]=1e-6; + if(! (cornerareas[i][2]>=0.0) ) cornerareas[i][2]=1e-6; #endif // WIN32 - pointareas[mIndices[i*3+0]] += cornerareas[i][0]; - pointareas[mIndices[i*3+1]] += cornerareas[i][1]; - pointareas[mIndices[i*3+2]] += cornerareas[i][2]; + pointareas[mIndices[i*3+0]] += cornerareas[i][0]; + pointareas[mIndices[i*3+1]] += cornerareas[i][1]; + pointareas[mIndices[i*3+2]] += cornerareas[i][2]; } } // need pointarea From 543f38c20a10f08eb11391b99c00ff6bf2add3d9 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 29 Nov 2007 12:29:32 +0000 Subject: [PATCH 065/101] Fix: GUI cache reset should work again, same goes for collision modifier (enabled through 'deflection' panel --- source/blender/blenkernel/BKE_cloth.h | 7 +- source/blender/blenkernel/BKE_collisions.h | 10 +- source/blender/blenkernel/intern/cloth.c | 1 + source/blender/blenkernel/intern/collision.c | 2 +- source/blender/blenkernel/intern/implicit.c | 379 +++++++++++-------- source/blender/blenkernel/intern/modifier.c | 6 + source/blender/makesdna/DNA_modifier_types.h | 1 + source/blender/src/buttons_editing.c | 8 - source/blender/src/buttons_object.c | 50 ++- 9 files changed, 300 insertions(+), 164 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 2bb3e32d6b6..c8ec1698b86 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -72,10 +72,10 @@ typedef struct ClothVertex { } ClothVertex; typedef struct ClothSpring { - int ij; /* Pij from the paper, one end of the spring. */ - int kl; /* Pkl from the paper, one end of the spring. */ + unsigned int ij; /* Pij from the paper, one end of the spring. */ + unsigned int kl; /* Pkl from the paper, one end of the spring. */ float restlen; /* The original length of the spring. */ - int matrix_index; /* needed for implicit solver (fast lookup) */ + unsigned int matrix_index; /* needed for implicit solver (fast lookup) */ int type; /* types defined in BKE_cloth.h ("springType") */ int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ float dfdx[3][3]; @@ -152,6 +152,7 @@ typedef enum CLOTH_SPRING_TYPE_STRUCTURAL = 0, CLOTH_SPRING_TYPE_SHEAR, CLOTH_SPRING_TYPE_BENDING, + CLOTH_SPRING_TYPE_COLLISION, } CLOTH_SPRING_TYPES; /* SPRING FLAGS */ diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h index f358bd629e6..e38662fdf95 100644 --- a/source/blender/blenkernel/BKE_collisions.h +++ b/source/blender/blenkernel/BKE_collisions.h @@ -37,11 +37,13 @@ #include #include #include + /* types */ #include "BLI_linklist.h" #include "BKE_DerivedMesh.h" #include "BKE_object.h" -#include "BKE_DerivedMesh.h" + +#include "DNA_modifier_types.h" // used in kdop.c and collision.c typedef struct CollisionTree @@ -82,6 +84,8 @@ typedef struct CollisionPair { int point_indexA[4], point_indexB[4]; float vector[3]; + float normal[3]; // has to be calculated from vector + float distance; float pa[3], pb[3]; } CollisionPair; @@ -115,6 +119,10 @@ LinkNode *BLI_linklist_append_fast (LinkNode **listp, void *ptr); // 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 diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 6eacb26c315..2dd4f1a0f0f 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -1009,6 +1009,7 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d ***************************************************************************************/ // be carefull: implicit solver has to be resettet when using this one! +// --> only for implicit handling of this spring! int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type) { Cloth *cloth = clmd->clothObject; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 6f0ac5f8c6d..4bc1efc1e70 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -71,7 +71,6 @@ #include "Bullet-C-Api.h" - // step is limited from 0 (frame start position) to 1 (frame end position) void collision_move_object(CollisionModifierData *collmd, float step, float prevstep) { @@ -83,6 +82,7 @@ void collision_move_object(CollisionModifierData *collmd, float step, float prev VECSUB(tv, collmd->xnew[i].co, collmd->x[i].co); VECADDS(collmd->current_x[i].co, collmd->x[i].co, tv, prevstep); VECADDS(collmd->current_xnew[i].co, collmd->x[i].co, tv, step); + VECSUB(collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co); } } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 12c5c190691..3b8f6ddd7d8 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -63,6 +63,8 @@ #include "BKE_global.h" #include "BIF_editdeform.h" +#include "Bullet-C-Api.h" + #ifdef _WIN32 #include static LARGE_INTEGER _itstart, _itend; @@ -1123,6 +1125,17 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, } + if(s->type == CLOTH_SPRING_TYPE_COLLISION) + { + if(length < L) + { + mul_fvector_S(stretch_force, dir, (100.0*(length-L))); + + VECADD(s->f, s->f, stretch_force); + } + return; + } + // calculate force of structural + shear springs if(s->type != CLOTH_SPRING_TYPE_BENDING) { @@ -1415,6 +1428,19 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase { effectors= pdInitEffectors(ob,NULL); + // clear constraint matrix from collisions + if(clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + { + for(i = 0; i < id->S[0].vcount; i++) + { + if(!(verts [id->S[i].r].goal >= SOFTGOALSNAP)) + { + id->S[0].vcount = i-1; + break; + } + } + } + // calculate cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); @@ -1553,122 +1579,148 @@ void implicit_set_positions (ClothModifierData *clmd) memcpy(id->V, cloth->v, sizeof(lfVector) * numverts); } - -int collisions_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) +unsigned int implicit_getcreate_S_index(ClothModifierData *clmd, unsigned int index) { - /* + Cloth *cloth = clmd->clothObject; + Implicit_Data *id = cloth->implicit; + unsigned int i = 0, pinned = 0; + + pinned = id->S[0].vcount; + + for(i = 0; i < pinned; i++) + { + if(id->S[i].r == index) + { + return index; + } + } + + // create new PINNED entry in constraint matrix + id->S[0].vcount++; + id->S[pinned].c = id->S[pinned].r = index; + return pinned; +} + +int collisions_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollisionPair *collpair ) +{ + unsigned int i = 0; int result = 0; LinkNode *search = NULL; - CollPair *collpair = NULL; - Cloth *cloth1, *cloth2; + Cloth *cloth1 = NULL; float w1, w2, w3, u1, u2, u3; float v1[3], v2[3], relativeVelocity[3]; - float magrelVel; - + float magrelVel = 0.0; + float epsilon = clmd->coll_parms->epsilon; + cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; + + if(!collpair) + return 0; + + // TODO: check distance & calc normal + // calc distance + normal + collpair->distance = plNearestPoints( + cloth1->current_xold[collpair->point_indexA[0]], + cloth1->current_xold[collpair->point_indexA[1]], + cloth1->current_xold[collpair->point_indexA[2]], + collmd->current_x[collpair->point_indexB[0]].co, + collmd->current_x[collpair->point_indexB[1]].co, + collmd->current_x[collpair->point_indexB[2]].co, + collpair->pa,collpair->pb,collpair->vector); + + if (collpair->distance > (epsilon + ALMOST_ZERO)) + { + return 0; + } - // search = clmd->coll_parms.collision_list; - - while(search) - { - collpair = search->link; - - // compute barycentric coordinates for both collision points - collisions_compute_barycentric(collpair->pa, - cloth1->verts[collpair->ap1].txold, - cloth1->verts[collpair->ap2].txold, - cloth1->verts[collpair->ap3].txold, - &w1, &w2, &w3); - - collisions_compute_barycentric(collpair->pb, - cloth2->verts[collpair->bp1].txold, - cloth2->verts[collpair->bp2].txold, - cloth2->verts[collpair->bp3].txold, - &u1, &u2, &u3); - - // Calculate relative "velocity". - interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3); - - interpolateOnTriangle(v2, cloth2->verts[collpair->bp1].tv, cloth2->verts[collpair->bp2].tv, cloth2->verts[collpair->bp3].tv, u1, u2, u3); - - VECSUB(relativeVelocity, v1, v2); - - // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). - magrelVel = INPR(relativeVelocity, collpair->normal); - - // printf("magrelVel: %f\n", magrelVel); - - // Calculate masses of points. - - // If v_n_mag < 0 the edges are approaching each other. - if(magrelVel < -ALMOST_ZERO) - { - // Calculate Impulse magnitude to stop all motion in normal direction. - // const double I_mag = v_n_mag / (1/m1 + 1/m2); - float magnitude_i = magrelVel / 2.0f; // TODO implement masses - float tangential[3], magtangent, magnormal, collvel[3]; - float vrel_t_pre[3]; - float vrel_t[3]; - double impulse; - float epsilon = clmd->coll_parms.epsilon; - float overlap = (epsilon + ALMOST_ZERO-collpair->distance); - - // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); - - // magtangent = INPR(tangential, tangential); - - // Apply friction impulse. - if (magtangent < -ALMOST_ZERO) - { - - // printf("friction applied: %f\n", magtangent); - // TODO check original code -} - + // compute barycentric coordinates for both collision points + collisions_compute_barycentric (collpair->pa, + cloth1->current_xold[collpair->point_indexA[0]], + cloth1->current_xold[collpair->point_indexA[1]], + cloth1->current_xold[collpair->point_indexA[2]], + &w1, &w2, &w3 ); - impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); - - // printf("impulse: %f\n", impulse); - - // face A - VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); - cloth1->verts[collpair->ap1].impulse_count++; - - VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); - cloth1->verts[collpair->ap2].impulse_count++; - - VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); - cloth1->verts[collpair->ap3].impulse_count++; - - // face B - VECADDMUL(cloth2->verts[collpair->bp1].impulse, collpair->normal, u1 * impulse); - cloth2->verts[collpair->bp1].impulse_count++; - - VECADDMUL(cloth2->verts[collpair->bp2].impulse, collpair->normal, u2 * impulse); - cloth2->verts[collpair->bp2].impulse_count++; - - VECADDMUL(cloth2->verts[collpair->bp3].impulse, collpair->normal, u3 * impulse); - cloth2->verts[collpair->bp3].impulse_count++; - - - result = 1; + collisions_compute_barycentric (collpair->pb, + collmd->current_x[collpair->point_indexB[0]].co, + collmd->current_x[collpair->point_indexB[1]].co, + collmd->current_x[collpair->point_indexB[2]].co, + &u1, &u2, &u3 ); + + // Calculate relative "velocity". + interpolateOnTriangle ( v1, cloth1->current_v[collpair->point_indexA[0]], cloth1->current_v[collpair->point_indexA[1]], cloth1->current_v[collpair->point_indexA[2]], w1, w2, w3 ); + + interpolateOnTriangle ( v2, collmd->current_v[collpair->point_indexB[0]].co, collmd->current_v[collpair->point_indexB[1]].co, collmd->current_v[collpair->point_indexB[2]].co, u1, u2, u3 ); + + VECSUB ( relativeVelocity, v1, v2 ); + + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). + magrelVel = INPR ( relativeVelocity, collpair->normal ); + + // printf("magrelVel: %f\n", magrelVel); + + // Calculate masses of points. + + // If v_n_mag < 0 the edges are approaching each other. + if ( magrelVel < -ALMOST_ZERO ) + { + // Calculate Impulse magnitude to stop all motion in normal direction. + // const double I_mag = v_n_mag / (1/m1 + 1/m2); + float magnitude_i = magrelVel / 2.0f; // TODO implement masses + float tangential[3], magtangent, magnormal, collvel[3]; + float vrel_t_pre[3]; + float vrel_t[3]; + double impulse; + float overlap = ( epsilon + ALMOST_ZERO-collpair->distance ); + + // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); + + // magtangent = INPR(tangential, tangential); + + // Apply friction impulse. + if ( magtangent < -ALMOST_ZERO ) + { + + // printf("friction applied: %f\n", magtangent); + // TODO check original code + } + + + impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); + + // printf("impulse: %f\n", impulse); + + // face A + VECADDMUL ( cloth1->verts[collpair->point_indexA[0]].impulse, collpair->normal, w1 * impulse ); + cloth1->verts[collpair->point_indexA[0]].impulse_count++; + + VECADDMUL ( cloth1->verts[collpair->point_indexA[1]].impulse, collpair->normal, w2 * impulse ); + cloth1->verts[collpair->point_indexA[1]].impulse_count++; + + VECADDMUL ( cloth1->verts[collpair->point_indexA[2]].impulse, collpair->normal, w3 * impulse ); + cloth1->verts[collpair->point_indexA[2]].impulse_count++; + + // face B + /* + VECADDMUL ( collmd->verts[collpair->point_indexB[0]].impulse, collpair->normal, u1 * impulse ); + collmd->verts[collpair->point_indexB[0]].impulse_count++; + + VECADDMUL ( collmd->verts[collpair->point_indexB[1]].impulse, collpair->normal, u2 * impulse ); + collmd->verts[collpair->point_indexB[1]].impulse_count++; + + VECADDMUL ( collmd->verts[collpair->point_indexB[2]].impulse, collpair->normal, u3 * impulse ); + collmd->verts[collpair->point_indexB[2]].impulse_count++; + */ - // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case - - // Apply the impulse and increase impulse counters. - - -} - - search = search->next; -} - + result = 1; + + // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case + + // Apply the impulse and increase impulse counters. + + } return result; - */ - return 0; } @@ -2087,10 +2139,11 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, Object *ob2 = NULL; BVH *bvh1 = NULL, *bvh2 = NULL, *self_bvh; LinkNode *collision_list = NULL; - unsigned int i = 0, j = 0; + unsigned int i = 0, j = 0, index; int collisions = 0, count = 0; float (*current_x)[3]; - + Implicit_Data *id = NULL; + /* if (!(((Cloth *)clmd->clothObject)->tree)) { printf("No BVH found\n"); @@ -2100,65 +2153,77 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, cloth = clmd->clothObject; bvh1 = cloth->tree; self_bvh = cloth->selftree; + id = cloth->implicit; //////////////////////////////////////////////////////////// // static collisions //////////////////////////////////////////////////////////// // update cloth bvh - bvh_update_from_float3(bvh1, cloth->current_xold, cloth->numverts, cloth->current_x, 0); // 0 means STATIC, 1 means MOVING (see later in this function) -/* + bvh_update_from_float3 ( bvh1, cloth->current_xold, cloth->numverts, cloth->current_x, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) + // check all collision objects - for (base = G.scene->base.first; base; base = base->next) + for ( base = G.scene->base.first; base; base = base->next ) { - ob2 = base->object; - collmd = (CollisionModifierData *) modifiers_findByType (ob2, eModifierType_Collision); - - if (!collmd) - continue; - + ob2 = base->object; + collmd = ( CollisionModifierData * ) modifiers_findByType ( ob2, eModifierType_Collision ); + + if ( !collmd ) + continue; + // check if there is a bounding volume hierarchy - if (collmd->tree) - { - bvh2 = collmd->tree; - + if ( collmd->tree ) + { + bvh2 = collmd->tree; + // update position + bvh of collision object - collision_move_object(collmd, step, prevstep); - bvh_update_from_mvert(collmd->tree, collmd->current_x, collmd->numverts, NULL, 0); - - // fill collision list - collisions += bvh_traverse(bvh1->root, bvh2->root, &collision_list); - + collision_move_object ( collmd, step, prevstep ); + bvh_update_from_mvert ( collmd->tree, collmd->current_x, collmd->numverts, NULL, 0 ); + + // fill collision list + collisions += bvh_traverse ( bvh1->root, bvh2->root, &collision_list ); + // call static collision response + if ( collision_list ) + { + LinkNode *search = collision_list; + + while ( search ) + { + collisions_collision_response_static(clmd, collmd, (CollisionPair *)search->link); + + search = search->next; + } + } // free collision list - if(collision_list) - { - LinkNode *search = collision_list; - - while(search) - { - CollisionPair *coll_pair = search->link; - - MEM_freeN(coll_pair); - search = search->next; -} - BLI_linklist_free(collision_list,NULL); + if ( collision_list ) + { + LinkNode *search = collision_list; - collision_list = NULL; -} -} -} + while ( search ) + { + CollisionPair *coll_pair = search->link; + + MEM_freeN ( coll_pair ); + search = search->next; + } + BLI_linklist_free ( collision_list,NULL ); + + collision_list = NULL; + } + } + } ////////////////////////////////////////////// // update velocities + positions ////////////////////////////////////////////// for(i = 0; i < cloth->numverts; i++) { - VECADD(cloth->current_x[i], cloth->current_xold[i], cloth->current_v[i]); -} + VECADD(cloth->current_x[i], cloth->current_xold[i], cloth->current_v[i]); + } ////////////////////////////////////////////// -*/ + */ /* // fill collision list collisions += bvh_traverse(self_bvh->root, self_bvh->root, &collision_list); @@ -2235,7 +2300,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, collisions = 1; count = 0; current_x = cloth->current_x; // needed for openMP - + /* // #pragma omp parallel for private(i,j, collisions) shared(current_x) // for ( count = 0; count < 6; count++ ) { @@ -2275,8 +2340,6 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, { float correction = ((mindistance1 + mindistance2)) - length; - printf("correction: %f\n", correction); - if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) && ( cloth->verts [i].goal >= SOFTGOALSNAP ) ) { VecMulf ( temp, -correction ); @@ -2289,10 +2352,24 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, } else { + unsigned int pinned = id->S[0].vcount; + + printf("correction: %f\n", correction); + VecMulf ( temp, -correction*0.5 ); VECADD ( current_x[j], current_x[j], temp ); - + VECSUB ( cloth->current_v[j], cloth->current_x[j], cloth->current_xold[j] ); + + index = implicit_getcreate_S_index(clmd, j); + id->S[index].pinned = 1; + VECSUB ( current_x[i], current_x[i], temp ); + VECSUB ( cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i] ); + + index = implicit_getcreate_S_index(clmd, i); + id->S[index].pinned = 1; + + cloth_add_spring (clmd, i, j, mindistance1 + mindistance2, CLOTH_SPRING_TYPE_COLLISION); } collisions = 1; @@ -2300,16 +2377,18 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, } } } - + */ ////////////////////////////////////////////// // SELFCOLLISIONS: update velocities ////////////////////////////////////////////// + /* for ( i = 0; i < cloth->numverts; i++ ) { VECSUB ( cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i] ); } + */ ////////////////////////////////////////////// - return 1; + return 0; } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index af8b4aa8079..e433fb6ed88 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5068,6 +5068,7 @@ static void collisionModifier_initData(ModifierData *md) collmd->xnew = NULL; collmd->current_x = NULL; collmd->current_xnew = NULL; + collmd->current_v = NULL; collmd->time = -1; collmd->numverts = 0; collmd->tree = NULL; @@ -5089,11 +5090,14 @@ static void collisionModifier_freeData(ModifierData *md) MEM_freeN(collmd->current_x); if(collmd->current_xnew) MEM_freeN(collmd->current_xnew); + if(collmd->current_v) + MEM_freeN(collmd->current_v); collmd->x = NULL; collmd->xnew = NULL; collmd->current_x = NULL; collmd->current_xnew = NULL; + collmd->current_v = NULL; collmd->time = -1; collmd->numverts = 0; collmd->tree = NULL; @@ -5155,6 +5159,8 @@ static void collisionModifier_deformVerts( collmd->xnew = MEM_dupallocN(collmd->x); // frame end position collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame + collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame + collmd->numverts = numverts; // TODO: epsilon diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 65eec871404..1bb8ce99c88 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -358,6 +358,7 @@ typedef struct CollisionModifierData { struct MVert *xnew; /* position at the end of the frame */ struct MVert *current_xnew; /* new position at the actual inter-frame step */ struct MVert *current_x; /* position at the actual inter-frame step */ + struct MVert *current_v; /* position at the actual inter-frame step */ unsigned int numverts; float time; diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 959fd770959..83f04110974 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1494,14 +1494,6 @@ static void modifiers_convertToReal(void *ob_v, void *md_v) BIF_undo_push("Modifier convert to real"); } -static void modifiers_pointCacheClearModifier(void *ob_v, void *md_v) -{ - Object *ob = ob_v; - ModifierData *md = md_v; - int stack_index = modifiers_indexInObject(ob_v, md_v); - PTCache_id_clear((ID *)ob, CFRA, stack_index); -} - static void build_uvlayer_menu_vars(CustomData *data, char **menu_string, int *uvlayer_tmp, char *uvlayer_name) { diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 2ce543eec44..1808618d7b7 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -48,6 +48,7 @@ #include "BKE_action.h" #include "BKE_cloth.h" +#include "BKE_collisions.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_library.h" @@ -2966,6 +2967,30 @@ void do_effects_panels(unsigned short event) } allqueue(REDRAWVIEW3D, 0); break; + case B_CLOTH_CLEARCACHEALL: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + CFRA= 1; + update_for_newframe_muted(); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + cloth_clear_cache(ob, clmd, 2); + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); + } + } + break; + case B_CLOTH_RENEW: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + do_object_panels(B_CLOTH_CLEARCACHEALL); + cloth_free_modifier (clmd); + } + } + break; default: if(event>=B_SELEFFECT && eventmodifiers, md ); + } + 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; @@ -3025,7 +3071,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"); From 42637b725267192bfe22731bf975cfb1a50541ee Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 12 Dec 2007 17:33:59 +0000 Subject: [PATCH 066/101] Fixed preconditioned conjugate to some degree but some issues left for stiffness>1000 (disabled therefore). There's also some issue with the springs function (some springs seem to be missing/not created) --- source/blender/blenkernel/BKE_cloth.h | 1 - source/blender/blenkernel/BKE_pointcache.h | 1 + source/blender/blenkernel/SConscript | 2 +- source/blender/blenkernel/intern/cloth.c | 11 +++- source/blender/blenkernel/intern/implicit.c | 65 ++++++++++++------- source/blender/blenkernel/intern/key.c | 10 +-- .../blenkernel/intern/particle_system.c | 2 +- source/blender/blenkernel/intern/pointcache.c | 8 +++ source/blender/makesdna/DNA_key_types.h | 5 +- .../nodes/intern/CMP_nodes/CMP_normalize.c | 5 +- source/blender/src/buttons_editing.c | 13 ++-- source/blender/src/buttons_object.c | 2 + source/blender/src/drawview.c | 52 ++++++++++++++- source/blender/src/editkey.c | 6 +- source/blender/src/editmesh_mods.c | 7 ++ source/blender/src/editparticle.c | 16 ++--- 16 files changed, 152 insertions(+), 54 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index c8ec1698b86..e288e7ee082 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -200,7 +200,6 @@ typedef void ( *CM_COLLISION_SELF ) ( struct ClothModifierData *clmd, int step ) // only one available in the moment typedef enum { CM_IMPLICIT = 0, - CM_VERLET = 1, } CM_SOLVER_ID; diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 020b9d15417..afaf9dbeee2 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -44,5 +44,6 @@ int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext); FILE * BKE_ptcache_id_fopen(struct ID *id, char mode, int cfra, int stack_index); void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index); +int BKE_ptcache_id_exist(struct ID *id, int cfra, int stack_index); #endif diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index c83e9f7fbe1..355cd19da33 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -7,7 +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 += ' #/extern/bullet2/src' incs += ' #/intern/bmfont' incs += ' ' + env['BF_OPENGL_INC'] diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 2dd4f1a0f0f..64166493caa 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -115,7 +115,6 @@ double tval() static CM_SOLVER_DEF solvers [] = { { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free }, - // { "Verlet", CM_VERLET, verlet_init, verlet_solver, verlet_free }, }; /* ********** cloth engine ******* */ @@ -477,8 +476,9 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) fclose(fp); } - implicit_set_positions(clmd); - + if(clmd->sim_parms->solver_type == 0) + implicit_set_positions(clmd); + return ret; } @@ -600,6 +600,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d tstart(); /* Call the solver. */ + if (solvers [clmd->sim_parms->solver_type].solver) solvers [clmd->sim_parms->solver_type].solver (ob, framenr, clmd, effectors); @@ -625,6 +626,10 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d if(cloth_read_cache(ob, clmd, framenr)) cloth_to_object (ob, result, clmd); } + else + { + cloth_clear_cache(ob, clmd, 0); + } } return result; diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 3b8f6ddd7d8..7d7ad480026 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -241,7 +241,7 @@ DO_INLINE float dot_lfvector(lfVector *fLongVectorA, lfVector *fLongVectorB, uns unsigned int i = 0; float temp = 0.0; // schedule(guided, 2) -#pragma omp parallel for reduction(+: temp) +#pragma omp parallel for reduction(+: temp) private(i) for(i = 0; i < verts; i++) { temp += INPR(fLongVectorA[i], fLongVectorB[i]); @@ -558,6 +558,7 @@ DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) mul_fmatrix_S(matrix[i].m, scalar); } } + /* SPARSE SYMMETRIC multiply big matrix with long vector*/ /* STATUS: verified */ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector) @@ -590,6 +591,20 @@ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector } + + +/* SPARSE SYMMETRIC multiply big matrix with long vector (for diagonal preconditioner) */ +/* STATUS: verified */ +DO_INLINE void mul_prevfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector) +{ + unsigned int i = 0; + + for(i = 0; i < from[0].vcount; i++) + { + mul_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); + } +} + /* SPARSE SYMMETRIC add big matrix with big matrix: A = B + C*/ DO_INLINE void add_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) { @@ -983,7 +998,7 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma sub_lfvector_lfvector(r, lB, r, numverts); filter(r, S); - mul_bfmatrix_lfvector(p, Pinv, r); + mul_prevfmatrix_lfvector(p, Pinv, r); filter(p, S); deltaNew = dot_lfvector(r, p, numverts); @@ -1005,7 +1020,7 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma add_lfvector_lfvectorS(r, r, s, -alpha, numverts); - mul_bfmatrix_lfvector(h, Pinv, r); + mul_prevfmatrix_lfvector(h, Pinv, r); filter(h, S); deltaOld = deltaNew; @@ -1013,6 +1028,7 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma deltaNew = dot_lfvector(r, h, numverts); add_lfvector_lfvectorS(p, h, p, deltaNew / deltaOld, numverts); + filter(p, S); } @@ -1125,6 +1141,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, } + /* if(s->type == CLOTH_SPRING_TYPE_COLLISION) { if(length < L) @@ -1135,6 +1152,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, } return; } + */ // calculate force of structural + shear springs if(s->type != CLOTH_SPRING_TYPE_BENDING) @@ -1150,7 +1168,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, VECADD(s->f, s->f, stretch_force); // Ascher & Boxman, p.21: Damping only during elonglation - mul_fvector_S(damping_force, extent, clmd->sim_parms->Cdis * ((INPR(vel,extent)/length))); + mul_fvector_S(damping_force, extent, clmd->sim_parms->Cdis * 0.01 * ((INPR(vel,extent)/length))); VECADD(s->f, s->f, damping_force); dfdx_spring_type1(s->dfdx, dir,length,L,k); @@ -1171,12 +1189,17 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); VECADD(s->f, s->f, bending_force); - if(INPR(bending_force,bending_force) > 0.13*0.13) + // if(INPR(bending_force,bending_force) > 0.13*0.13) { clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; } + dfdx_spring_type2(s->dfdx, dir,length,L,k, cb); + /* + if(s->ij == 300 || s->kl == 300) + printf("id->F[0]: %f, id->F[1]: %f, id->F[2]: %f\n", s->f[0], s->f[1], s->f[2]); + */ } } } @@ -1192,7 +1215,7 @@ DO_INLINE int cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, { sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, s->dfdv); sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv); - add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); + add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); } else if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE)) return 0; @@ -1306,7 +1329,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec float speed[3] = {0.0f, 0.0f,0.0f}; float force[3]= {0.0f, 0.0f, 0.0f}; -#pragma omp parallel for private (i) shared(lF) +// #pragma omp parallel for private (i) shared(lF) for(i = 0; i < cloth->numverts; i++) { float vertexnormal[3]={0,0,0}; @@ -1363,7 +1386,6 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec } clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; - } void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, fmatrix3x3 *P, fmatrix3x3 *Pinv) @@ -1375,31 +1397,23 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto zero_lfvector(dV, numverts); subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); - mul_bfmatrix_lfvector(dFdXmV, dFdX, lV); - add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts); - // itstart(); - + // TODO: unstable with quality=5 + stiffness=7000 + no zero_lfvector() cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */ - // TODO: if anyone finds a way to correct this function => - // explodes with stiffness = 3000 and 16k verts + pinned at 2 corners + // TODO: unstable with quality=5 + stiffness=7000 // cg_filtered_pre(dV, A, B, z, S, P, Pinv); - // itend(); - // printf("cg_filtered calc time: %f\n", (float)itval()); - // advance velocities add_lfvector_lfvector(Vnew, lV, dV, numverts); - del_lfvector(dFdXmV); } int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) -{ +{ unsigned int i=0; float step=0.0f, tf=1.0f; Cloth *cloth = clmd->clothObject; @@ -1418,7 +1432,10 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // update velocities with constrained velocities from pinned verts if(verts [i].goal >= SOFTGOALSNAP) { - VECSUB(id->V[i], cloth->xconst[i], cloth->xold[i]); + float temp[3]; + VECSUB(temp, cloth->xconst[i], cloth->xold[i]); + VECSUB(id->z[i], temp, id->V[i]); + // VecMulf(id->V[i], 1.0 / dt); } } @@ -1612,6 +1629,8 @@ int collisions_collision_response_static ( ClothModifierData *clmd, CollisionMod float v1[3], v2[3], relativeVelocity[3]; float magrelVel = 0.0; float epsilon = clmd->coll_parms->epsilon; + + return 0; cloth1 = clmd->clothObject; @@ -2143,7 +2162,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, int collisions = 0, count = 0; float (*current_x)[3]; Implicit_Data *id = NULL; - /* + if (!(((Cloth *)clmd->clothObject)->tree)) { printf("No BVH found\n"); @@ -2182,7 +2201,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, // fill collision list collisions += bvh_traverse ( bvh1->root, bvh2->root, &collision_list ); - + // call static collision response if ( collision_list ) { @@ -2223,7 +2242,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, VECADD(cloth->current_x[i], cloth->current_xold[i], cloth->current_v[i]); } ////////////////////////////////////////////// - */ + /* // fill collision list collisions += bvh_traverse(self_bvh->root, self_bvh->root, &collision_list); diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 234a096edce..b57b799001a 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -672,14 +672,12 @@ static void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, i /* step 2: do it */ - kb= key->block.first; - while(kb) { - + for(kb=key->block.first; kb; kb=kb->next) { if(kb!=key->refkey) { float icuval= kb->curval; /* only with value, and no difference allowed */ - if(icuval!=0.0f && kb->totelem==tot) { + if(!(kb->flag & KEYBLOCK_MUTE) && icuval!=0.0f && kb->totelem==tot) { KeyBlock *refb; float weight, *weights= kb->weights; @@ -738,7 +736,6 @@ static void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, i } } } - kb= kb->next; } } @@ -1312,6 +1309,9 @@ int do_ob_key(Object *ob) if(ob->shapeflag & (OB_SHAPE_LOCK|OB_SHAPE_TEMPLOCK)) { KeyBlock *kb= BLI_findlink(&key->block, ob->shapenr-1); + if(kb && (kb->flag & KEYBLOCK_MUTE)) + kb= key->refkey; + if(kb==NULL) { kb= key->block.first; ob->shapenr= 1; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 5d3a4332b5d..1c7d235cd90 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -4271,7 +4271,7 @@ void psys_to_softbody(Object *ob, ParticleSystem *psys, int force_recalc) if((psys->softflag&OB_SB_ENABLE)==0) return; - if((ob->recalc&OB_RECALC_TIME)==0) + if(ob->recalc && (ob->recalc&OB_RECALC_TIME)==0) psys->softflag|=OB_SB_REDO; /* let's replace the object's own softbody with the particle softbody */ diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 9492754260c..c4ef437019e 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -183,3 +183,11 @@ void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index) return; } +int BKE_ptcache_id_exist(struct ID *id, int cfra, int stack_index) +{ + char filename[(FILE_MAXDIR+FILE_MAXFILE)*2]; + + BKE_ptcache_id_filename(id, filename, cfra, stack_index, 1, 1); + + return BLI_exists(filename); +} diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h index 785cf515a42..87c09fb0ee4 100644 --- a/source/blender/makesdna/DNA_key_types.h +++ b/source/blender/makesdna/DNA_key_types.h @@ -44,7 +44,7 @@ typedef struct KeyBlock { float pos; float curval; - short type, adrcode, relative, pad1; /* relative == 0 means first key is reference */ + short type, adrcode, relative, flag; /* relative == 0 means first key is reference */ int totelem, pad2; void *data; @@ -87,5 +87,8 @@ typedef struct Key { #define KEY_CARDINAL 1 #define KEY_BSPLINE 2 +/* keyblock->flag */ +#define KEYBLOCK_MUTE 1 + #endif diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c b/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c index a62e4be4015..7f76cb40948 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_normalize.c @@ -85,8 +85,11 @@ static void node_composit_exec_normalize(void *data, bNode *node, bNodeStack **i min = *val; } } + min = MIN2(0.1, min); + max = MAX2(0.9, max); + mult = 1.0f/(max-min); - + printf("min %f max %f\n", min, max); composit3_pixel_processor(node, stackbuf, in[0]->data, in[0]->vec, NULL, &min, NULL, &mult, do_normalize, CB_VAL, CB_VAL, CB_VAL); diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 9ffb7578980..05fed2f8fbc 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -410,7 +410,6 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an return; } } - efa= efa->next; } } else if ELEM(G.obedit->type, OB_CURVE, OB_SURF) { @@ -484,7 +483,7 @@ void do_common_editbuts(unsigned short event) // old name, is a mix of object an if(ma) { ob->actcol= find_material_index(ob, ma); if(ob->actcol==0) { - assign_material(ob, ma, ob->totcol); + assign_material(ob, ma, ob->totcol+1); ob->actcol= ob->totcol; } } @@ -2474,15 +2473,17 @@ static void editing_panel_shapes(Object *ob) uiBlockBeginAlign(block); if(ob->shapeflag & OB_SHAPE_LOCK) icon= ICON_PIN_HLT; else icon= ICON_PIN_DEHLT; uiDefIconButBitS(block, TOG, OB_SHAPE_LOCK, B_LOCKKEY, icon, 10,150,25,20, &ob->shapeflag, 0, 0, 0, 0, "Always show the current Shape for this Object"); + if(kb->flag & KEYBLOCK_MUTE) icon= ICON_MUTE_IPO_ON; else icon = ICON_MUTE_IPO_OFF; + uiDefIconButBitS(block, TOG, KEYBLOCK_MUTE, B_MODIFIER_RECALC, icon, 35,150,20,20, &kb->flag, 0, 0, 0, 0, "Mute the current Shape"); uiSetButLock(G.obedit==ob, "Unable to perform in EditMode"); - uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT, 35,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key"); + uiDefIconBut(block, BUT, B_PREVKEY, ICON_TRIA_LEFT, 55,150,20,20, NULL, 0, 0, 0, 0, "Previous Shape Key"); strp= make_key_menu(key, 1); - uiDefButS(block, MENU, B_SETKEY, strp, 55,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices"); + uiDefButS(block, MENU, B_SETKEY, strp, 75,150,20,20, &ob->shapenr, 0, 0, 0, 0, "Browse existing choices"); MEM_freeN(strp); - uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT, 75,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key"); + uiDefIconBut(block, BUT, B_NEXTKEY, ICON_TRIA_RIGHT, 95,150,20,20, NULL, 0, 0, 0, 0, "Next Shape Key"); uiClearButLock(); - uiDefBut(block, TEX, B_NAMEKEY, "", 95, 150, 190, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name"); + uiDefBut(block, TEX, B_NAMEKEY, "", 115, 150, 170, 20, kb->name, 0.0, 31.0, 0, 0, "Current Shape Key name"); uiDefIconBut(block, BUT, B_DELKEY, ICON_X, 285,150,25,20, 0, 0, 0, 0, 0, "Deletes current Shape Key"); uiBlockEndAlign(block); diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index e7a2a654ba1..3360dab61f8 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3298,6 +3298,7 @@ static void object_softbodies__enable(void *ob_v, void *arg2) if (!ob->soft) { ob->soft= sbNew(); ob->softflag |= OB_SB_GOAL|OB_SB_EDGES; + softbody_clear_cache(ob, CFRA); } } /* needed so that initial state is cached correctly */ @@ -3331,6 +3332,7 @@ static void object_softbodies__enable_psys(void *ob_v, void *psys_v) psys->soft= sbNew(); psys->softflag |= OB_SB_GOAL|OB_SB_EDGES; psys->soft->particles=psys; + clear_particles_from_cache(ob, psys, CFRA); } psys->softflag |= OB_SB_ENABLE; } diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 14690b08d48..93915a0e92e 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -70,6 +70,8 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_meta_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_force.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" #include "DNA_screen_types.h" @@ -101,8 +103,10 @@ #include "BKE_key.h" #include "BKE_main.h" #include "BKE_mesh.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_particle.h" +#include "BKE_pointcache.h" #include "BKE_scene.h" #include "BKE_texture.h" #include "BKE_utildefines.h" @@ -3292,10 +3296,50 @@ static void inner_play_prefetch_shutdown(int mode) seq_stop_threads(); } +static int cached_dynamics(int sfra, int efra) +{ + Base *base = G.scene->base.first; + Object *ob; + ModifierData *md; + ParticleSystem *psys; + int i, stack_index, cached=1; + + while(base && cached) { + ob = base->object; + if(ob->softflag & OB_SB_ENABLE && ob->soft) { + for(i=0, md=ob->modifiers.first; md; i++, md=md->next) { + if(md->type == eModifierType_Softbody) { + stack_index = i; + break; + } + } + for(i=sfra; i<=efra && cached; i++) + cached &= BKE_ptcache_id_exist(&ob->id,i,stack_index); + } + + for(psys=ob->particlesystem.first; psys; psys=psys->next) { + stack_index = modifiers_indexInObject(ob,(ModifierData*)psys_get_modifier(ob,psys)); + if(psys->part->type==PART_HAIR) { + if(psys->softflag & OB_SB_ENABLE && psys->soft); + else + stack_index = -1; + } + + if(stack_index >= 0) + for(i=sfra; i<=efra && cached; i++) + cached &= BKE_ptcache_id_exist(&ob->id,i,stack_index); + } + + base = base->next; + } + + return cached; +} void inner_play_anim_loop(int init, int mode) { ScrArea *sa; static int last_cfra = -1; + static int cached = 0; /* init */ if(init) { @@ -3304,7 +3348,7 @@ void inner_play_anim_loop(int init, int mode) tottime= 0.0; curmode= mode; last_cfra = -1; - + cached = cached_dynamics(PSFRA,PEFRA); return; } @@ -3328,7 +3372,7 @@ void inner_play_anim_loop(int init, int mode) if (sa->spacetype == SPACE_SEQ) { scrarea_do_windraw(sa); } - } + } sa= sa->next; } @@ -3380,8 +3424,10 @@ void inner_play_anim_loop(int init, int mode) CFRA = PSFRA; audiostream_stop(); audiostream_start( CFRA ); + cached = cached_dynamics(PSFRA,PEFRA); } else { - if (U.mixbufsize + if (cached + && U.mixbufsize && (G.scene->audio.flag & AUDIO_SYNC)) { CFRA = audiostream_pos(); } else { diff --git a/source/blender/src/editkey.c b/source/blender/src/editkey.c index 0d861cda5d0..5cc193f8844 100644 --- a/source/blender/src/editkey.c +++ b/source/blender/src/editkey.c @@ -625,7 +625,7 @@ void insert_shapekey(Object *ob) void delete_key(Object *ob) { - KeyBlock *kb; + KeyBlock *kb, *rkb; Key *key; IpoCurve *icu; @@ -635,6 +635,10 @@ void delete_key(Object *ob) kb= BLI_findlink(&key->block, ob->shapenr-1); if(kb) { + for(rkb= key->block.first; rkb; rkb= rkb->next) + if(rkb->relative == ob->shapenr-1) + rkb->relative= 0; + BLI_remlink(&key->block, kb); key->totkey--; if(key->refkey== kb) key->refkey= key->block.first; diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index ae10cef0879..a74bd851aeb 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -82,6 +82,7 @@ editmesh_mods.c, UI level access, no geometry changes #include "BIF_interface.h" #include "BIF_meshtools.h" #include "BIF_mywindow.h" +#include "BIF_previewrender.h" #include "BIF_resources.h" #include "BIF_screen.h" #include "BIF_space.h" @@ -2126,6 +2127,12 @@ void mouse_mesh(void) allqueue(REDRAWIMAGE, 0); allqueue(REDRAWBUTSEDIT, 0); /* for the texture face panel */ } + if (efa && efa->mat_nr != G.obedit->actcol-1) { + G.obedit->actcol= efa->mat_nr+1; + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWBUTSSHADING, 0); + BIF_preview_changed(ID_MA); + } } rightmouse_transform(); diff --git a/source/blender/src/editparticle.c b/source/blender/src/editparticle.c index e08ca3279d6..c9cf745fa44 100644 --- a/source/blender/src/editparticle.c +++ b/source/blender/src/editparticle.c @@ -1703,10 +1703,10 @@ static int remove_tagged_elements(Object *ob, ParticleSystem *psys) } } - MEM_freeN(psys->particles); + if(psys->particles) MEM_freeN(psys->particles); psys->particles = new_pars; - MEM_freeN(edit->keys); + if(edit->keys) MEM_freeN(edit->keys); edit->keys = new_keys; if(edit->mirror_cache) { @@ -2256,10 +2256,10 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe memcpy(new_keys, edit->keys, totpart * sizeof(ParticleEditKey*)); /* change old arrays to new ones */ - MEM_freeN(psys->particles); + if(psys->particles) MEM_freeN(psys->particles); psys->particles = new_pars; - MEM_freeN(edit->keys); + if(edit->keys) MEM_freeN(edit->keys); edit->keys = new_keys; if(edit->mirror_cache) { @@ -2267,8 +2267,6 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe edit->mirror_cache = NULL; } - psys->totpart = newtotpart; - /* create tree for interpolation */ if(pset->flag & PE_INTERPOLATE_ADDED && psys->totpart){ tree=BLI_kdtree_new(psys->totpart); @@ -2281,6 +2279,8 @@ static void brush_add(Object *ob, ParticleSystem *psys, short *mval, short numbe BLI_kdtree_balance(tree); } + psys->totpart = newtotpart; + /* create new elements */ pa = psys->particles + totpart; key = edit->keys + totpart; @@ -2691,10 +2691,10 @@ void PE_mirror_x(int tagged) memcpy(new_pars, psys->particles, totpart*sizeof(ParticleData)); memcpy(new_keys, edit->keys, totpart*sizeof(ParticleEditKey*)); - MEM_freeN(psys->particles); + if(psys->particles) MEM_freeN(psys->particles); psys->particles= new_pars; - MEM_freeN(edit->keys); + if(edit->keys) MEM_freeN(edit->keys); edit->keys= new_keys; if(edit->mirror_cache) { From 3bf1536f5ed210fb8832f782999ca6a072a6a3c6 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 18 Dec 2007 16:54:12 +0000 Subject: [PATCH 067/101] Some User UI changes: a) Don't ask the user anymore if he wants to overwrite the file when he's doing a simple ctrl-s/ctrl-w; b) Ask for saving on exit when a file has changed, ontheless quit.blend is saved anyway. --> All branch changes, not likely to go into trunk --- source/blender/blenkernel/BKE_blender.h | 1 + source/blender/blenkernel/BKE_cloth.h | 14 + source/blender/blenkernel/intern/blender.c | 7 +- source/blender/blenkernel/intern/cloth.c | 698 ++- source/blender/blenkernel/intern/implicit.c | 102 +- source/blender/blenkernel/intern/kdop.c | 1 + source/blender/blenkernel/intern/modifier.c | 2 + source/blender/makesdna/DNA_userdef_types.h | 1 + source/blender/src/blenderbuttons.c | 4737 +++++++++++-------- source/blender/src/header_info.c | 3 +- source/blender/src/toets.c | 4 + source/blender/src/toolbox.c | 22 + source/blender/src/usiblender.c | 52 +- 13 files changed, 3551 insertions(+), 2093 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 243425db139..84ebd3102b3 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -70,6 +70,7 @@ extern void BKE_reset_undo(void); extern char *BKE_undo_menu_string(void); extern void BKE_undo_number(int nr); extern void BKE_undo_save_quit(void); +extern int BKE_undo_there(void); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index e288e7ee082..d888ba28ebe 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -60,6 +60,18 @@ struct ClothModifierData; #define CLOTH_MAX_THREAD 2 +typedef struct fc +{ + float *d, *d0; // density + float *T, *T0; // temperature + float *u, *u0; // velocity in x direction + float *v, *v0; // velocity in y direction + float *w, *w0; // velocity in z direction +} fc; +fc *f_init(void); +void f_free(fc *m_fc); +void step(fc *m_fc, float dt); + typedef struct ClothVertex { int flags; /* General flags per vertex. */ @@ -69,6 +81,7 @@ typedef struct ClothVertex { unsigned int impulse_count; /* same as above */ float collball; char octantflag; + float weight; } ClothVertex; typedef struct ClothSpring { @@ -104,6 +117,7 @@ typedef struct Cloth { float (*v)[4]; /* the current velocity of all vertices */ float (*current_v)[3]; float (*xconst)[3]; + struct fc *m_fc; } Cloth; /* goal defines */ diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 9845f571126..13b48559f75 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -85,6 +85,7 @@ #include "BKE_bad_level_calls.h" // for freeAllRad editNurb free_editMesh free_editText free_editArmature #include "BKE_utildefines.h" // O_BINARY FALSE #include "BIF_mainqueue.h" // mainqenter for onload script +#include "BIF_toolbox.h" #include "mydevice.h" #include "nla.h" #include "blendef.h" @@ -617,6 +618,10 @@ void BKE_write_undo(char *name) success= BLO_write_file_mem(prevfile, &curundo->memfile, G.fileflags, &err); } + + /* signals "file needs save" on exit */ + if(curundo!=NULL && curundo->prev!=NULL) + U.uiflag |= USER_UNDOSAVE; } /* 1= an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */ @@ -694,7 +699,7 @@ char *BKE_undo_menu_string(void) return menu; } - /* saves quit.blend */ +/* saves quit.blend */ void BKE_undo_save_quit(void) { UndoElem *uel; diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 64166493caa..95d487b2ec7 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -78,6 +78,22 @@ #include "BIF_space.h" #include "mydevice.h" +#ifdef WIN32 +#include +#endif // WIN32 +#ifdef __APPLE__ +#define GL_GLEXT_LEGACY 1 +#include +#include +#else +#include +#if defined(__sun__) && !defined(__sparc__) +#include +#else +#include +#endif +#endif + #ifdef _WIN32 void tstart ( void ) {} @@ -482,6 +498,309 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) return ret; } +#define AMBIENT 50 +#define DECAY 0.04f +#define ALMOST_EQUAL(a, b) ((fabs(a-b)<0.00001f)?1:0) + + // cube vertices +GLfloat cv[][3] = { + {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f}, + {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f} +}; + + // edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] +float edges[12][2][3] = { + {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + + {{1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}}, + {{-1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}}, + {{-1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}}, + {{1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}}, + + {{-1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}}, + {{-1.0f, -1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}}, + {{-1.0f, -1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}}, + {{-1.0f, 1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}} +}; + +void light_ray(unsigned char* _texture_data, int _ray_templ[4096][3], int x, int y, int z, int n, float decay) +{ + int xx = x, yy = y, zz = z, i = 0; + int offset; + + int l = 255; + float d; + + do { + offset = ((((zz*n) + yy)*n + xx) << 2); + if (_texture_data[offset + 2] > 0) + _texture_data[offset + 2] = (unsigned char) ((_texture_data[offset + 2] + l)*0.5f); + else + _texture_data[offset + 2] = (unsigned char) l; + d = _texture_data[offset+1]; + if (l > AMBIENT) { + l -= d*decay; + if (l < AMBIENT) + l = AMBIENT; + } + + i++; + xx = x + _ray_templ[i][0]; + yy = y + _ray_templ[i][1]; + zz = z + _ray_templ[i][2]; + + } while ((xx>=0)&&(xx=0)&&(yy=0)&&(zz0) ? 0 : n-1; + int sy = (_light_dir[1]>0) ? 0 : n-1; + int sz = (_light_dir[2]>0) ? 0 : n-1; + + float decay = 1.0f/(n*DECAY); + + for (i=0; i 0) ? 1 : -1; + int yinc = (ly > 0) ? 1 : -1; + int zinc = (lz > 0) ? 1 : -1; + float tx, ty, tz; + int i = 1; + int len = 0; + int maxlen = 3*edgelen*edgelen; + _ray_templ[0][0] = _ray_templ[0][2] = _ray_templ[0][2] = 0; + + while (len <= maxlen) + { + // fx + t*lx = (x+1) -> t = (x+1-fx)/lx + tx = (x+xinc-fx)/lx; + ty = (y+yinc-fy)/ly; + tz = (z+zinc-fz)/lz; + + if ((tx<=ty)&&(tx<=tz)) { + _ray_templ[i][0] = _ray_templ[i-1][0] + xinc; + x =+ xinc; + fx = x; + + if (ALMOST_EQUAL(ty,tx)) { + _ray_templ[i][1] = _ray_templ[i-1][1] + yinc; + y += yinc; + fy = y; + } else { + _ray_templ[i][1] = _ray_templ[i-1][1]; + fy += tx*ly; + } + + if (ALMOST_EQUAL(tz,tx)) { + _ray_templ[i][2] = _ray_templ[i-1][2] + zinc; + z += zinc; + fz = z; + } else { + _ray_templ[i][2] = _ray_templ[i-1][2]; + fz += tx*lz; + } + } else if ((ty0)&&(t<2)) { + ret[num][0] = edges[i][0][0] + edges[i][1][0]*t; + ret[num][1] = edges[i][0][1] + edges[i][1][1]*t; + ret[num][2] = edges[i][0][2] + edges[i][1][2]*t; + num++; + } + } + + return num; +} + +void draw_slices(float m[][4]) +{ + int i; + + Vec3 viewdir(m[0][2], m[1][2], m[2][2]); + viewdir.Normalize(); + // find cube vertex that is closest to the viewer + for (i=0; i<8; i++) { + float x = cv[i][0] + viewdir[0]; + float y = cv[i][1] + viewdir[1]; + float z = cv[i][2] + viewdir[2]; + if ((x>=-1.0f)&&(x<=1.0f) + &&(y>=-1.0f)&&(y<=1.0f) + &&(z>=-1.0f)&&(z<=1.0f)) + { + break; + } + } + if(i != 8) return; + + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glDisable(GL_DEPTH_TEST); + // our slices are defined by the plane equation a*x + b*y +c*z + d = 0 + // (a,b,c), the plane normal, are given by viewdir + // d is the parameter along the view direction. the first d is given by + // inserting previously found vertex into the plane equation + float d0 = -(viewdir[0]*cv[i][0] + viewdir[1]*cv[i][1] + viewdir[2]*cv[i][2]); + float dd = 2*d0/64.0f; + int n = 0; + for (float d = -d0; d < d0; d += dd) { + // intersect_edges returns the intersection points of all cube edges with + // the given plane that lie within the cube + float pt[12][3]; + int num = intersect_edges(pt, viewdir[0], viewdir[1], viewdir[2], d); + + if (num > 2) { + // sort points to get a convex polygon + // std::sort(pt.begin()+1, pt.end(), Convexcomp(pt[0], viewdir)); + int shuffled = 1; + + while(shuffled) + { + int j; + shuffled = 0; + + for(j = 0; j < num-1; j++) + { + // Vec3 va = a-p0, vb = b-p0; + // return dot(up, cross(va, vb)) >= 0; + float va[3], vb[3], vc[3]; + + VECSUB(va, pt[j], pt[0]); + VECSUB(vb, pt[j+1], pt[0]); + Crossf(vc, va, vb); + + if(INPR(viewdir, vc)>= 0) + { + float temp[3]; + + VECCOPY(temp, pt[j]); + VECCOPY(pt[j], pt[j+1]); + VECCOPY(pt[j+1], temp); + + shuffled = 1; + } + } + } + + glEnable(GL_TEXTURE_3D); + glEnable(GL_FRAGMENT_PROGRAM_ARB); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, _prog[0]); + glActiveTextureARB(GL_TEXTURE0_ARB); + glBindTexture(GL_TEXTURE_3D, _txt[0]); + glBegin(GL_POLYGON); + for (i=0; ir.cfra; float current_time = bsystem_time(ob, (float)G.scene->r.cfra, 0.0); ListBase *effectors = NULL; - float deltaTime = current_time - clmd->sim_parms->sim_time; + float deltaTime = current_time - clmd->sim_parms->sim_time; + unsigned char* _texture_data=NULL; + float _light_dir[3]; + int _ray_templ[4096][3]; clmd->sim_parms->dt = 1.0f / (clmd->sim_parms->stepsPerFrame * G.scene->r.frs_sec); @@ -577,7 +899,14 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d cloth = clmd->clothObject; } - + /* + deltaTime = 0; + while( deltaTime < 1.0) + { + step(cloth->m_fc, 0.1); + deltaTime+=0.1; + } + */ clmd->clothObject->old_solver_type = clmd->sim_parms->solver_type; // Insure we have a clmd->clothObject, in case allocation failed. @@ -632,6 +961,34 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d } } + cloth = clmd->clothObject; + /* + if(cloth) + { + if (_texture_data == NULL) + _texture_data = (unsigned char*) malloc((30+2)*(30+2)*(30+2)*4); + + for (i=0; i<(30+2)*(30+2)*(30+2); i++) { + _texture_data[(i<<2)] = (unsigned char) (cloth->m_fc->T[i] * 255.0f); + _texture_data[(i<<2)+1] = (unsigned char) (cloth->m_fc->d[i] * 255.0f); + _texture_data[(i<<2)+2] = 0; + _texture_data[(i<<2)+3] = 255; + } + + // from ligth constructor + _light_dir[0] = -1.0f; + _light_dir[1] = 0.5f; + _light_dir[2] = 0.0f; + + gen_ray_templ(_ray_templ, _light_dir, 30 + 2); + + cast_light(_texture_data, _ray_templ, _light_dir, 30+2); + + glActiveTextureARB(GL_TEXTURE0_ARB); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 30+2, 30+2, 30+2, 0, GL_RGBA, GL_UNSIGNED_BYTE, _texture_data); + free(_texture_data); + } + */ return result; } @@ -653,6 +1010,8 @@ void cloth_free_modifier (ClothModifierData *clmd) if (cloth) { + f_free(cloth->m_fc); + // If our solver provides a free function, call it if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free) { @@ -834,6 +1193,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d unsigned int numverts = dm->getNumVerts(dm); MVert *mvert = CDDM_get_verts(dm); float tnull[3] = {0,0,0}; + Cloth *cloth = NULL; /* If we have a clothObject, free it. */ if (clmd->clothObject != NULL) @@ -851,6 +1211,10 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject."); return 0; } + + cloth = clmd->clothObject; + + cloth->m_fc = f_init(); switch (ob->type) { @@ -1228,3 +1592,333 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) * SPRING NETWORK BUILDING IMPLEMENTATION END ***************************************************************************************/ +#define F_ITER 20 +#define m_diffusion 0.00001f +#define m_viscosity 0.000f +#define m_buoyancy 1.5f +#define m_cooling 1.0f +#define m_vc_eps 4.0f + +#define GRID_SIZE 30 +#define SIZE ((GRID_SIZE+2)*(GRID_SIZE+2)*(GRID_SIZE+2)) +#define _I(x,y,z) (((z)<<10)+((y)<<5)+x) + +#define SWAPFPTR(x,y) {float *t=x;x=y;y=t;} + +float buffers[10][SIZE]; +float sd[SIZE], su[SIZE], sv[SIZE], sw[SIZE], sT[SIZE]; + + +// nothing to do in this mode +// add code for 2nd mode +void set_bnd(int b, float* x, int N) +{ +} + +void lin_solve(int b, float *x, float *x0, float a, float c, int N) +{ + float cRecip = 1.0 / c; + int i, j, k, l; + for (l=0; lN+0.5) xx=N+0.5f; i0=(int)xx; i1=i0+1; + if (yy<0.5) yy=0.5f; if (yy>N+0.5) yy=N+0.5f; j0=(int)yy; j1=j0+1; + if (zz<0.5) zz=0.5f; if (zz>N+0.5) zz=N+0.5f; k0=(int)zz; k1=k0+1; + sx1 = xx-i0; sx0 = 1-sx1; + sy1 = yy-j0; sy0 = 1-sy1; + sz1 = zz-k0; sz0 = 1-sz1; + v0 = sx0*(sy0*x0[_I(i0,j0,k0)]+sy1*x0[_I(i0,j1,k0)])+sx1*(sy0*x0[_I(i1,j0,k0)]+sy1*x0[_I(i1,j1,k0)]); + v1 = sx0*(sy0*x0[_I(i0,j0,k1)]+sy1*x0[_I(i0,j1,k1)])+sx1*(sy0*x0[_I(i1,j0,k1)]+sy1*x0[_I(i1,j1,k1)]); + x[_I(i,j,k)] = sz0*v0 + sz1*v1; + } + } + } + set_bnd(b,x, N); +} + +void advect_cool(int b, float* x0, float* x, float* y0, float* y, float* uu, float* vv, float* ww, float dt, float cooling, int N) +{ + int i, j, k, i0, j0, k0, i1, j1, k1; + float sx0, sx1, sy0, sy1, sz0, sz1, v0, v1; + float xx, yy, zz, dt0, c0; + dt0 = dt*N; + c0 = 1.0f - cooling*dt; + for (k=1; k<=N; k++) + { + for (j=1; j<=N; j++) + { + for (i=1; i<=N; i++) + { + xx = i-dt0*uu[_I(i,j,k)]; + yy = j-dt0*vv[_I(i,j,k)]; + zz = k-dt0*ww[_I(i,j,k)]; + if (xx<0.5) xx=0.5f; if (xx>N+0.5) xx=N+0.5f; i0=(int)xx; i1=i0+1; + if (yy<0.5) yy=0.5f; if (yy>N+0.5) yy=N+0.5f; j0=(int)yy; j1=j0+1; + if (zz<0.5) zz=0.5f; if (zz>N+0.5) zz=N+0.5f; k0=(int)zz; k1=k0+1; + sx1 = xx-i0; sx0 = 1-sx1; + sy1 = yy-j0; sy0 = 1-sy1; + sz1 = zz-k0; sz0 = 1-sz1; + v0 = sx0*(sy0*x0[_I(i0,j0,k0)]+sy1*x0[_I(i0,j1,k0)])+sx1*(sy0*x0[_I(i1,j0,k0)]+sy1*x0[_I(i1,j1,k0)]); + v1 = sx0*(sy0*x0[_I(i0,j0,k1)]+sy1*x0[_I(i0,j1,k1)])+sx1*(sy0*x0[_I(i1,j0,k1)]+sy1*x0[_I(i1,j1,k1)]); + x[_I(i,j,k)] = sz0*v0 + sz1*v1; + v0 = sx0*(sy0*y0[_I(i0,j0,k0)]+sy1*y0[_I(i0,j1,k0)])+sx1*(sy0*y0[_I(i1,j0,k0)]+sy1*y0[_I(i1,j1,k0)]); + v1 = sx0*(sy0*y0[_I(i0,j0,k1)]+sy1*y0[_I(i0,j1,k1)])+sx1*(sy0*y0[_I(i1,j0,k1)]+sy1*y0[_I(i1,j1,k1)]); + y[_I(i,j,k)] = (sz0*v0 + sz1*v1)*c0; + } + } + } + set_bnd(b,x, N); + set_bnd(b,y, N); +} + +void fproject(float* u, float* u0, float* v, float* v0, float* w, float* w0, int N) +{ + float* p = u0; float* div = v0; // temporary buffers, use old velocity buffers + int i, j, k; + float h; + h = 1.0f/N; + for (k=1; k<=N; k++) { + for (j=1; j<=N; j++) { + for (i=1; i<=N; i++) { + div[_I(i,j,k)] = -h*( + u[_I(i+1,j,k)]-u[_I(i-1,j,k)]+ + v[_I(i,j+1,k)]-v[_I(i,j-1,k)]+ + w[_I(i,j,k+1)]-w[_I(i,j,k-1)])*0.5; + p[_I(i,j,k)] = 0; + } + } + } + set_bnd(0, div, N); + set_bnd(0, p, N); + lin_solve(0, p, div, 1, 6, N); + + for (k=1; k<=N; k++) { + for (j=1; j<=N; j++) { + for (i=1; i<=N; i++) { + u[_I(i,j,k)] -= (p[_I(i+1,j,k)]-p[_I(i-1,j,k)])*0.5*N; + v[_I(i,j,k)] -= (p[_I(i,j+1,k)]-p[_I(i,j-1,k)])*0.5*N; + w[_I(i,j,k)] -= (p[_I(i,j,k+1)]-p[_I(i,j,k-1)])*0.5*N; + } + } + } + set_bnd(1, u, N); + set_bnd(2, v, N); + set_bnd(3, w, N); +} + +void vorticity_confinement(float *T0, float* u, float* u0, float* v, float* v0, float* w, float* w0, float dt, float vc_eps, int N) +{ + int i,j,k,ijk; + float *curlx = u0, *curly = v0, *curlz=w0, *curl=T0; // temp buffers + float dt0 = dt * vc_eps; + float x,y,z; + + + for (k=1; ku, m_fc->u0, m_fc->v, m_fc->v0, m_fc->w, m_fc->w0, m_fc->T, m_fc->T0, dt, GRID_SIZE); + dens_temp_step(sd, sT, m_fc->T, m_fc->T0, m_fc->d, m_fc->d0, m_fc->u, m_fc->v, m_fc->w, dt, GRID_SIZE); +} + + + +void clear_buffer(float* x) +{ + int i; + for (i=0; id=buffers[i++]; m_fc->d0=buffers[i++]; + m_fc->T=buffers[i++]; m_fc->T0=buffers[i++]; + m_fc->u=buffers[i++]; m_fc->u0=buffers[i++]; + m_fc->v=buffers[i++]; m_fc->v0=buffers[i++]; + m_fc->w=buffers[i++]; m_fc->w0=buffers[i++]; + + clear_sources(sd, su, sv); + + size=(GRID_SIZE+2)*(GRID_SIZE+2)*(GRID_SIZE+2); + for (i=0; iv[i] = -0.5f; + + return m_fc; +} + +void f_free(fc *m_fc) +{ + if(m_fc) + MEM_freeN(m_fc); +} + diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 7d7ad480026..9e4428c1055 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1630,12 +1630,13 @@ int collisions_collision_response_static ( ClothModifierData *clmd, CollisionMod float magrelVel = 0.0; float epsilon = clmd->coll_parms->epsilon; - return 0; cloth1 = clmd->clothObject; if(!collpair) + { return 0; + } // TODO: check distance & calc normal // calc distance + normal @@ -1650,8 +1651,11 @@ int collisions_collision_response_static ( ClothModifierData *clmd, CollisionMod if (collpair->distance > (epsilon + ALMOST_ZERO)) { + printf("collpair->distance > (epsilon + ALMOST_ZERO)\n"); return 0; } + + printf("IN1\n"); // compute barycentric coordinates for both collision points collisions_compute_barycentric (collpair->pa, @@ -1683,6 +1687,8 @@ int collisions_collision_response_static ( ClothModifierData *clmd, CollisionMod // If v_n_mag < 0 the edges are approaching each other. if ( magrelVel < -ALMOST_ZERO ) { + printf("magrelVel < -ALMOST_ZERO\n"); + // Calculate Impulse magnitude to stop all motion in normal direction. // const double I_mag = v_n_mag / (1/m1 + 1/m2); float magnitude_i = magrelVel / 2.0f; // TODO implement masses @@ -2162,6 +2168,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, int collisions = 0, count = 0; float (*current_x)[3]; Implicit_Data *id = NULL; + int ret = 0; if (!(((Cloth *)clmd->clothObject)->tree)) { @@ -2206,7 +2213,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, if ( collision_list ) { LinkNode *search = collision_list; - + while ( search ) { collisions_collision_response_static(clmd, collmd, (CollisionPair *)search->link); @@ -2234,6 +2241,24 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, } } + // vertex weight = 2 + + for(i = 0; i < cloth->numverts; i++) + if ((cloth->verts[i].impulse_count > 0) && !(cloth->verts[i].flags & CVERT_FLAG_PINNED)) + { + printf("applying impulse\n"); + + VECADDS(cloth->current_v[i], cloth->current_v[i], cloth->verts[i].impulse, 1.0 / (cloth->verts[i].impulse_count * 2.0)); + + // reset + cloth->verts[i].impulse_count = 0; + cloth->verts[i].impulse[0] = 0.0; + cloth->verts[i].impulse[1] = 0.0; + cloth->verts[i].impulse[2] = 0.0; + + ret = 1; + } + ////////////////////////////////////////////// // update velocities + positions ////////////////////////////////////////////// @@ -2243,78 +2268,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, } ////////////////////////////////////////////// - /* - // fill collision list - collisions += bvh_traverse(self_bvh->root, self_bvh->root, &collision_list); - // call static collision response - - // free collision list - if(collision_list) - { - LinkNode *search = collision_list; - - while(search) - { - float distance = 0; - float mindistance = cloth->selftree->epsilon; - CollisionPair *collpair = (CollisionPair *)search->link; - - // get distance of faces - distance = plNearestPoints( - cloth->current_x[collpair->point_indexA[0]], cloth->current_x[collpair->point_indexA[1]], cloth->current_x[collpair->point_indexA[2]], cloth->current_x[collpair->point_indexB[0]], cloth->current_x[collpair->point_indexB[1]], cloth->current_x[collpair->point_indexB[2]], collpair->pa,collpair->pb,collpair->vector); - - if(distance < mindistance) - { - /////////////////////////////////////////// - // TODO: take velocity of the collision points into account! - /////////////////////////////////////////// - - float correction = mindistance - distance; - float temp[3]; - - VECCOPY(temp, collpair->vector); - Normalize(temp); - VecMulf(temp, -correction*0.5); - - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[0]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexA[0]], cloth->current_x[collpair->point_indexA[0]], temp); - - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[1]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexA[1]], cloth->current_x[collpair->point_indexA[1]], temp); - - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexA[2]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexA[2]], cloth->current_x[collpair->point_indexA[2]], temp); - - - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[0]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexB[0]], cloth->current_x[collpair->point_indexB[0]], temp); - - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[1]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexB[1]], cloth->current_x[collpair->point_indexB[1]], temp); - - if(!((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (cloth->verts [collpair->point_indexB[2]].goal >= SOFTGOALSNAP))) - VECSUB(cloth->current_x[collpair->point_indexB[2]], cloth->current_x[collpair->point_indexB[2]], temp); - - collisions = 1; - -} - -} - - search = collision_list; - while(search) - { - CollisionPair *coll_pair = search->link; - - MEM_freeN(coll_pair); - search = search->next; -} - BLI_linklist_free(collision_list,NULL); - - collision_list = NULL; -} - */ // Test on *simple* selfcollisions collisions = 1; count = 0; @@ -2409,5 +2363,5 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, */ ////////////////////////////////////////////// - return 0; + return ret; } diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 234a6b75548..74b5b3d7b7f 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -915,6 +915,7 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio // of list are horrible slow! BLI_linklist_prepend(&collision_list[0], collpair); } + return 1; } else diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 554613b3355..50160771054 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5187,6 +5187,8 @@ static void collisionModifier_deformVerts( // recalc static bounding boxes bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0); + + printf("bvh_update_from_mvert\n"); } collmd->time = current_time; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index c37b332929d..138040b13ca 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -259,6 +259,7 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_KEYINSERTNEED (1 << 19) #define USER_ZOOM_TO_MOUSEPOS (1 << 20) #define USER_SHOW_FPS (1 << 21) +#define USER_UNDOSAVE (1 << 22) // flag to signal a write_undo() call after a save (save on exit needed then) /* transopts */ diff --git a/source/blender/src/blenderbuttons.c b/source/blender/src/blenderbuttons.c index c8fb9ec7a7a..84bb22afeac 100644 --- a/source/blender/src/blenderbuttons.c +++ b/source/blender/src/blenderbuttons.c @@ -1,2020 +1,2731 @@ /* DataToC output of file */ -int datatoc_blenderbuttons_size= 64418; +int datatoc_blenderbuttons_size= 87170; char datatoc_blenderbuttons[]= { 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 2, 0, 0, 0, 1, 0, 8, 6, 0, 0, 0,197,144,206,103, 0, - 0, 0, 1,115, 82, 71, 66, 0,174,206, 28,233, 0, 0, 0, 6, 98, 75, 71, 68, 0,255, 0,255, 0,255,160,189,167,147, 0, 0, - 0, 9,112, 72, 89,115, 0, 0, 11, 19, 0, 0, 11, 19, 1, 0,154,156, 24, 0, 0, 0, 7,116, 73, 77, 69, 7,215, 11, 26, 20, - 59, 43, 0,186, 29, 9, 0, 0, 32, 0, 73, 68, 65, 84,120,218,236,125,121, 92, 84, 85,255,255,251,220,217,217, 23, 1, 21,151, -193,125, 95,201, 37, 55, 40, 53,243,155,153, 6,148,154,100,101, 98,137,218,147,166, 61,101,143,250,211, 71,197,164, 50, 53,161, -167,210,172, 52, 5,115,201, 45, 81, 7,245, 81, 82,113, 47, 23, 20, 69, 4, 69,150, 97, 22,102,187,115,151,223, 31, 51, 67, 3, - 2,179,128, 91,207,188, 95,220,215,229,222,123,238,103,206, 61,219,103, 61,231,144, 30, 61,122,240,240,192, 3, 15, 60,240,192, - 3, 15,254,167, 64,121,138,192, 3, 15, 60,240,192, 3, 15,254,119,112,230,236, 1, 0, 0,241, 88, 0, 60,240,192, 3, 15, 60, -240,192, 99, 1,240,192, 3, 15, 60,240,192, 3, 15, 60, 2,128, 7, 30,120,224,129, 7, 30,120,224, 17, 0, 60,240,192, 3, 15, - 60,240,192,131,191, 5,132,246, 23,231,206,157, 35,238, 18,170, 41,150,192, 67,207, 67,175, 54,164,166,166,242,107,215,174,125, -100,249, 27, 55,110, 28,191,105,211, 38,226,169,143, 39,154, 30,234, 65, 15,158,242,243,208,251, 59,211,115, 89, 0,248, 31, 71, -245, 2, 36,143,115, 62, 83, 82, 82, 48,117,234, 84,226,169, 54,247,235,120,216,176, 97,149,215, 25, 25, 25,127,139,178, 28,253, - 82, 66,157, 3,193,142,237,169,127,235, 54, 35, 11,220, 6,169,177, 13, 34, 64,163, 2,123,145, 99,152,247, 56,183, 69, 79,255, -245,224,241,177, 0, 60,140,198, 58,122,244,232,168, 29, 59,118, 40,236,174,163,119,236,216,145,249, 88,244, 72,222, 50,118, 18, -242,216,246, 75, 62, 47, 47, 15, 0, 32,151,203,159,164, 65,196,105,233,116,220,184,113, 78,167,221,180,105,147, 43,130, 26,191, -101,203,150,202,139,109,219,182, 97,216,176, 97, 85,158, 63, 42, 33, 32, 59, 59,155, 7,128,200,200, 72,210, 16,233,118,108, 79, -125,160,245, 23, 30,209, 28, 0,112,207,104, 4, 99, 48, 89,110,170, 52, 0,128,216,216, 88,164,165,165,213,154,191,222,185,189, -249,182,119,219,186,244,227, 63, 15,252,217,137,122,145, 33,240,221,139, 48,238,216,134,242,242, 49, 40, 7,208, 75,246, 41,230, -201, 78,163,185, 20, 40, 49,230, 98,158, 33,206,165,223,141,141,141,141, 74, 75, 75, 83, 84,187, 23,157,150,150,150,249,152,245, -173, 6,105,183, 79,200,247, 54, 56,154, 4, 75,136,143,200,159,152,164, 98,222,164, 50, 80, 21, 6, 13,167, 51,153,255, 39,102, -199, 57, 20, 0,172, 12,219,118,174,111, 67,224,119,236,216,129,133, 91, 22,195,167,185, 63, 42,110,171, 49, 63,110,158,226, 49, -215,184, 31, 39, 16,185, 92,206,231,229,229, 33, 47, 47, 15,251,246,237,195,212,169, 83, 31, 87, 33,192,214,129, 72,106,106,170, - 40, 33, 33,193,188,124,249,242, 83, 0, 48,103,206,156,167,234,122,113,204,152, 49,149,255, 51, 12, 11,218,108, 2,109,162, 65, -211,150,131, 97, 24,204,153, 51,199,165,188,216, 51,255,154, 96, 21, 6,248, 71,105, 9,112, 69,248,121,100, 26,126,128, 31, 46, -220,248, 25, 50, 52, 3,139, 99, 40,254,230, 12,206,231,150, 97,236,178,117, 78,189,222,246,110, 91, 39, 25,186, 5,175,254,247, - 85,135,101, 34, 27, 57, 15, 65,163,223, 66,225,123,189, 0, 67,121,229,253, 51,134, 15,112, 6, 0, 12,192, 96, 89, 44, 14, 6, -158, 70, 0,128,222,229,189,157,106, 51,105,105,105,247,221,180, 99,144,228, 49,234, 99, 13, 49, 6, 60, 9,223,219,160, 24,208, -173, 7,121, 45, 60, 66,168,106,209, 72, 16,218, 49,156, 18,146, 80,162, 87,171, 57, 41,194, 88,170,103, 51,246,245, 81,195, 89, - 39, 73,221,113,225,103,155, 58,145,102,150, 11,244,146, 31,168, 0,176, 99,199, 14,197,150, 79, 62, 66,220,162, 37,138,122, 54, - 2,222,198,248, 1,160, 84, 95, 6, 4, 3,255, 60,184, 0,154, 27,229, 88,243,246,202,199,141,145,213, 54,240, 60,234, 60, 86, - 10, 1, 35, 70,140, 64, 94, 94, 30,228,114,249, 99, 87,118, 10,133,101,220,136,142,142,230, 1, 80,169,169,169,225, 9, 9, 9, -133,203,151, 47, 63,237, 44, 17,134, 97, 64,211,230, 74,198,111,207,252,179,179,179, 17, 25, 25,233, 82,166,226,226,226,236,153, - 45, 50, 50, 50,170, 11, 0, 13,209, 86, 92,174,135,200,200, 72, 50,110,220, 56,126,248,240,225,247, 61,219,191,127,191,205,210, - 97,179,122, 56, 77,191, 33,221, 1,225, 17,205, 81, 88,174,198, 47, 83, 95, 70, 48, 25,128,220,255,204, 70,171, 49,173,144,225, - 2,243,175, 44, 44,171,169,141, 52,128,169, 45,124,203, 49,232,111, 85,160, 48, 33,162,206,116, 23,165, 7,176,176,235, 61, 44, -189,248,113,125,235,179, 33,152,110, 67,210, 64, 3,211,122, 16,223,219, 32,136,143,143,247, 2,240, 52, 0, 31,187,219, 42, 0, - 23, 54,108,216,160,116,150,206, 23,107,191,160,232, 82,147,136, 54, 25,165,229, 48, 75, 69, 34,161, 80, 99,148, 82, 98,177,129, - 19,248,121, 51,180,204,108, 22, 22,221, 49,125,255,205,122,227,235,147, 39,177,206,124,183, 74,165,250,183,237,255,156,156,156, - 82,111,111,111, 74,167,211,113,246,105,250,244,233,243,121, 3, 51,246, 89,245, 45, 83,161, 35,237,255,242,229,203,104,235,227, -103,111, 13,112,199, 10, 80,201,252, 75,245,101, 88,250,236,130,202, 7,111,236,120, 23, 8, 5,198, 44,143,195,182, 57, 91, 92, -105,100,117, 13,110,245,110,168,183,111,223, 6, 0, 52,111,222,188,202,255,112,193,156,221,128,130, 8,169, 77, 8, 48,155, 25, - 91, 60, 64,131,104, 1, 13, 80,150,246,204, 31, 0, 72, 66, 66, 2, 0,220, 73, 77, 77, 13, 76, 72, 72, 40,119,154,249,155,205, -160,105, 19, 76, 52, 13,115, 53,230,207,115,174, 85, 67, 92, 92, 28,178,179,179,255,234, 93,201,201,136,137,137,169,188, 78, 79, - 79,175,183,176, 99, 39,240,212,187,253,217, 51,254,113,227,198,161,103,207,158, 54, 1,192, 85,139, 64,131, 52,194,130, 27,249, -208,109,251, 23,124,222, 92,137,240,136,230, 8, 11,150,225,198,182, 27, 22,230, 31,224,103,113, 1,136, 4,206, 73,176, 13,228, - 99,107,119,233, 58,110,207, 95, 12, 67,218,250,186, 45, 4, 50, 25,140, 70, 35,114,115,115, 81,108,188,138,118, 8,175, 53,173, -213, 12, 94, 87,219, 39,182,126, 98, 77,155,233, 70,255, 34,118,253,154,119,179,159,145, 58, 24,183,211,109,176,166,239,141,137, -137,225, 9, 33, 54, 87, 78,125,190,215,214,151,121,161, 80, 88,175, 58,143,143,143,247, 7, 48,230,224,193,131,255,226, 56,206, -100,215,150,132, 2,129,192, 59, 62, 62,126,242,134, 13, 27,246, 56,228,152,115,103, 9, 75,239,148, 72, 69, 34,137, 55, 37, 36, -126,188, 64,226,197, 9, 4, 66,142, 80,224,136,144,229, 5, 2,147,128, 35, 70,157,128,213,123,139, 69,228,155, 99,123,140,137, - 73,147, 56,228, 59,206, 99,121,121,185, 70,175,215, 51, 0,160,211,233,184,143, 62,250,168,146,225, 47, 89,178,228, 31,245,109, -239, 67,135, 14,157,106,251,255,192,129, 3, 41, 13,209,135, 40, 71,218,255,226, 87, 98, 96, 44, 41,193,236,206, 29, 96,239,187, -119, 90, 11, 25, 61, 58, 10, 64, 21,230, 63,122,244,232,104, 0,100,244,232,209,209,235, 70,127,101,177, 44,182,111, 84, 37,189, - 51,152,179, 38, 7,115,214,228, 96,218,138,203,120,125,209, 31, 24,251,207,115,245, 31,232, 10, 10,156, 18, 12, 30, 22,243,183, -250,252,249, 90, 44, 1, 48,211, 52,250,246,233,211, 16, 66, 6,191,101,203, 22,108,217,178, 5, 10,133,162,242,112, 81,224,225, - 21, 10, 5,162,163,163, 43,153,191,253,195,132,132, 4,149, 51, 3, 19,195,176, 22,205,223,100, 49,253, 87,103,254, 44,203, 66, -103,208,185,244,129, 54,139, 65,117,171, 65,122,122, 58,210,211,211,171, 8, 3, 46,125,111,102,213,241,208,122, 93, 47, 33,209, -198,252,199,141, 27,135,229,203,151, 87, 50,127,145, 80,228, 42,243,183, 13,224,181, 29, 78,195,128,124, 84,140,233, 11, 62,109, - 54, 10,110,228,131, 31,211,241,175, 66, 72,155, 13, 97,147, 16, 32, 32,224,161, 74,198,186,210, 92, 24,210,214,131,231,121, 92, -188,120, 17,131, 7, 15,134, 76, 38,171,194,248, 3, 3, 3, 97, 48, 24, 96, 48, 24, 80, 88, 88,136,241,134, 25,248, 38,240,189, - 90,105, 58,105,242, 38,213,210,186,202,184, 27, 74, 89, 33,181, 48,127,167,219, 96,245,239,141,137,137,225,211,211,211,145,150, -150,134,216,216, 88,190,190,223,107,101,254, 96, 24,198,237, 62, 17, 31, 31, 47, 5,240,246,129, 3, 7, 62, 90,180,104,209, 9, - 66,136,220,118, 0,104, 22, 28, 28,236,117,232,208,161,181,241,241,241,131,235,162,243, 85,202, 90,129,128,136, 36, 52,195,251, -153, 76,230, 80,150,227,154,177, 28, 23,193, 18,210, 2, 2, 65, 48, 33, 36, 0, 68,224,199,241, 8,226,105, 46, 64, 99, 48,123, -135,250, 49, 2,170,143,214,169, 58,210,235,245, 76,117,173,255,113, 7, 85, 23,227,110,215,174, 29,218,250,248, 65, 95,116, 23, -207,247,236,229, 50,131,182, 9, 17, 11,183, 44, 6,128, 74,230,111,179, 34,236,216,177, 35,211, 38, 4, 20,104,238,160,215,156, -126, 46, 9, 25, 58, 3, 11,157,129,197,221, 50, 19, 10, 75,140,184,125,207,232, 22,227,179,117, 22, 71,204,255, 81,161, 14, 33, - 0, 70,218, 4,163,209, 88, 31,242,188, 66,161,128,205, 71, 30, 18, 18, 98,175,205,194,133,193,164,138, 38, 92,135, 41,209,225, -160, 71,155, 77, 22,205,223, 68,131, 54, 87,101,254,102,179, 25, 58,157, 14, 90,141,246, 81, 87, 11,191,101, 75, 90,213, 79,178, -252,193,122,223,173, 1,207,158,249,219, 24, 63, 69, 81,144, 74,165,240,246,241,170, 87,134, 71,191,148,192,215,118, 56,122,119, -223, 63, 23, 32, 24, 3,192, 12,157, 14, 0,240,201,186,142,243,185,101,150, 65,126,232,116,152, 47, 46, 4, 74,203, 92, 43, 64, - 43,220,253, 30,111,148, 2, 0,214,175, 95,143, 29, 59,118,224,211, 79, 63,197,201,147, 39, 97, 50,153, 80, 92, 92,108,211,202, - 42,211,135,135,135,195, 0, 64,128,155,143,164,189,212,209,238, 73, 61,132, 70, 82,135, 5,207,101,154,246,150,176,154, 98, 2, -220, 97,254, 0,224,174, 16, 16, 31, 31,223,216,202,252,167,124,255,253,247,151,230,205,155,247,210,198,141, 27,209,174, 93, 59, - 0, 64,203,150, 45,161, 86,171, 37, 11, 23, 46, 60,125,232,208,161, 31,227,227,227,229,181,150, 18,199, 19,112,140,148,101,153, - 32,150, 97,155,153, 89,115, 27, 1, 69,154,138,133,148, 72, 42, 18, 24,132, 94, 98,149,183,175, 64, 35,144,242,140, 84, 32,240, - 22, 50,180,223,205, 51,103, 37, 19, 67,190,112,152,239,156,156,156, 82,157, 78,199,213,100,230,239,222,189,251, 85,154,166, 27, -172, 33,117,239,222,189,193,104, 9,235, 98,220,255,153,242,214, 95,204,182,224, 54,102,119,238,128, 21, 22, 6,237,146,212,106, -211,254,109, 76,191,218,239, 84, 94, 7,119,109,236, 82,230, 43, 12, 44,180,122, 6, 26, 29, 3,117, 5, 3,149,150,113,189, 87, -214, 16,249,111,175,229,219,255,127,227,198, 13,168, 84,170,135, 54, 98,164,164,164, 64, 46,151,195, 22,244, 87,205,215,207,167, -164,164,192,104, 48,212, 71, 0,224,215,173, 91,135,130,194, 66,136, 4, 2,132, 53,110, 92,133,249, 63,251,236,179, 56,120,240, -160,179,131, 19,137,142,142,174, 46, 4, 84,177,100, 56, 27,171, 64,155,104,208, 38, 19,204,102, 26, 12,195, 86, 50,127,147,201, - 4,189, 94,143,138,138, 10,104,181,174, 11, 0,246, 46, 0, 27,220,213,252,183,164,109, 1,120,160,212,202,104,172, 78,109, 16, -158,183, 8, 1,105,105,136,179,104, 80, 46,245,149,234,204, 95, 36, 18, 65, 34,145, 64, 42,149, 66, 42,149,214,187, 77,213,230, - 18,168,105, 94,188, 61,198,166,108, 5,255, 98, 4,238,245,239,133, 96, 12,128,236,229, 85, 96,238,150, 0, 1,126, 16,150,109, -194,174, 47, 78, 3, 2,129, 75,121,169,175, 43, 64, 39,176,140, 41, 75,151, 46, 69, 73, 73, 9,214,174, 93,139,238,221,187, 99, -209,162, 69,232,213,171, 23, 12, 6, 67,117, 13,205, 38, 82, 63,108,198,239, 44,131,118,215, 29, 80,155, 32,225, 50, 29,235, 44, -142,202,190,225,174,107,204,158,249, 87, 50, 27,171, 16,224,162, 59,192,247,194,133, 11, 95,190,243,206, 59, 71,186,118,237,234, - 7, 0, 11, 22, 44, 64, 78, 78, 14, 0,160, 95,191,126,248,229,151, 95, 48,112,224, 64,239,241,227,199,231,102,102,102, 30,120, -227,141, 55,198,159, 61,123,246,190,146, 13, 10, 14,226,110,220,200,101, 50, 21, 7,247,182,105,211, 54, 51,162,165,252,146,192, - 87, 86, 44, 32, 98, 29, 37, 17,233, 41,169,151,150, 22, 10,104,240,102, 1, 39, 53,251,106, 11,203,124, 78, 30, 58,215,167, 81, - 96,216, 47, 14,133, 81, 59,159,255,182,109,219, 94, 31, 51,102,204,247, 54,179,191, 70,163,161,196, 98,113,189, 27,146,205,236, -127,224,192,129, 7,107, 1,176,105,249,145,173,219,194, 88, 82, 2, 93,129,133, 9, 14,182,106,135,174, 90, 1,110,252,113,253, - 62,218, 53, 93,151, 93, 44,114, 41,243,245,101,254,246,140,159,231,121,155,143,191, 18,102,179,185,242, 80,169, 84,208,233,116, - 80, 42,149, 15,109,228,176,205,243,223,183,111, 95,117, 75, 0,159,146,146,130,110,221,186,193,104, 52, 84, 14,116, 41, 41, 41, - 46,153,235,215,124,181, 6,102,179, 25,205,194,195, 97,102,217,218,152,191, 43, 3, 9,169,193,244, 95, 57,117,177, 46, 75,198, -125, 2, 0,109,174,100,254,167, 78,158,130,222, 96,128, 86,171,133, 90,173,134, 74,165,170,162,217,185, 10,155, 27,160, 30,126, -127,148,149,150,161,172,172, 20,165,101, 74,148,150,149,161,172,172, 12,101,165, 22,141,180, 67,199,142, 80, 90,255,119, 85,251, - 7,128,158, 61,123,254,165,245,123,123,195,199,199, 23,190, 62,190,208,106,181,209,245,100,254,110,187, 3,114, 63,157, 2,209, -203,171, 16,140, 1, 16,102,173,130,121,235,116, 32,192, 15, 59,223,141,193,173,157, 55, 49,106,249, 6, 64,248,144,151, 21, 49, -222,130, 44, 92, 6,157, 78, 7,163,209, 8,189, 94,143,172,172, 44, 44, 91,182,172,198,228, 94, 94, 54, 11,202,117,119,152,183, -187, 90,181,125,249, 18, 39,175,235, 35,100,184,218,103,171,208, 73, 75, 75, 35,177,177,177, 54,230,239,182,101, 66, 40, 20, 18, -134, 97,170, 11, 5,112, 53, 22, 96,195,134, 13,215, 98, 99, 99,187,111,220,184,113,240,209,163, 71,125,135, 14, 29,122,210,198, -252,173, 10, 36, 36, 18, 9,127,235,214, 45,209,222,189,123,219, 7, 6, 6,158, 26, 48, 96, 64,110, 77,180, 94,125,229, 85,174, -109, 68, 59,109,191,126,253, 98, 46, 93,250,243, 25,141, 78,219,152,103,204, 12, 40,152, 25, 19,101, 50,153, 76, 6, 13,138, 52, -156,201,168, 45,204, 47, 98,118,237,222,147,212, 40, 56,164,152,166,245, 14,213,247,154,180,255,242,242,114, 33, 0,248,249,249, - 61,182,110, 1,170, 54,237,127,203, 39, 31, 89,164,230,162,187, 85,158,185, 26, 11, 48,122,244,232,232, 53,111,175, 4, 96, 9, -248,219,177, 99,135,194,198,244,109,107, 2, 12,251,225, 37, 0,192,153,229,191,219,226, 3, 30, 22, 42, 27, 99, 65, 65, 65,165, -182,111, 99,250,118,149, 11,173, 86, 11,163,209,104, 55,136, 60,188, 60, 78,157,106,137,253, 48, 51, 12, 46, 93,186,132,179,103, -206,160,123,183,238, 48, 26,141, 48, 24,140, 48, 26, 12,248,241,135, 31, 96, 75,231, 76, 71, 79, 78, 78, 70,167,142,157, 96, 54, -155,113,237,218, 53, 48,102, 26,133, 5,133, 13, 90,166,182,107,235,154, 5,182,181, 11, 28, 91, 0,204, 38, 48,172,197,236,127, -226,196,239,208, 25,116,168,208,106,160, 86,171, 81,174, 82,161,188, 92, 89, 47, 65,204,102, 9,112, 83,251, 7, 0, 28, 57,114, - 4, 90,173, 22, 90,173,198,122,214,162, 81,112, 48, 58,116,236,136, 43,151, 47,227,240,145, 35, 46,211,180,105,255, 66,161, 8, - 94, 94, 94,240,241,241,129,175,143, 15,124,124,188,160, 44, 87, 70, 39, 36, 36,100, 58,213,231,234, 97,234,175, 13,231,115,203, - 96,190,184, 16,101, 56, 6, 50,114, 5,200,128,127, 33,247,211, 41,120,113,249,247,144,138, 40, 64, 36,180, 28,238,112, 29, 55, - 93, 1,133, 47,124,133,160, 77, 47, 64,175,215, 35, 40, 40, 8,229,229,229, 40, 47, 47,199,241,227,199,113,247,238,221, 74, 51, -113,101,250,194, 66,188, 27, 40, 67, 35,175,146,186, 52,224,104,123,166, 26, 27, 27, 27,101,247, 44,170,218,179,104, 23,251, 5, - 95, 7, 3,111,136, 25, 5, 46,107,254, 53,125,111, 90, 90, 26, 73, 79, 79, 39,245,252,222, 42, 66,128, 59,204,223,134,143, 63, -254,248,194, 75, 47,189, 52,126,233,210,165,237,207,159, 63, 63, 64, 38,147, 9, 94,124,241, 69, 34,145, 72,192,113, 28, 25, 57, -114,228,133,153, 51,103,118,235,210,165,203,206,201,147, 39,191, 62,121,242,228, 90,125, 81, 9,211, 18,184, 63, 47, 95, 59,213, -165,107,183,215, 78,157, 60, 57,118,231,238, 95,151,100,159, 60,217,248, 82,206, 21,233,181,194, 92,254,199,149,155,101, 75,147, - 63,237,116, 96,247,238,228, 54,173,219,236,242, 9,243, 62,178, 97,195, 6,214,217, 18, 29, 58,116, 40, 78,157, 58,213, 35, 37, - 37,101,161,209,104, 20, 45, 90,180,232,179,157, 59,119,142, 43, 44, 44,124,232,140,195,169, 58,170,237, 65,240,205, 60, 40,129, - 74,237,223,134,193, 33, 33, 88,129, 43,206,107, 29, 86, 19,255,149,211,151, 16,208,190, 17,134,253,240, 18,118, 76,220,174,176, - 73,111, 54,230,111,211,254, 93,153,101,240,203,210, 30, 13,195, 97, 9,193,229,203,151, 97,107,172,213,205,203, 34,145, 8, 34, -145, 8, 37, 37, 37, 24, 57,114,228,163,168, 39, 34,151,203,249,148,148, 20,244,233,211, 7, 70,147, 9, 6,163, 1, 70,107,112, -147,193,104,113, 3,172, 94,189, 26,137,137,137,142, 6, 19,126,249,242,229, 96, 89, 22,167, 79,159,129, 72,104, 49,219,182,109, -219, 22, 55,243,242, 80, 88, 88,136, 77,155,126,198,184,113,175, 2, 0, 95,205, 18, 80,235, 0,148,154,154, 42, 6,192, 36, 36, - 36,112, 53,105, 64,174, 76, 85,180,105,254, 89, 89, 89,208, 85,232, 43, 5, 48,141, 86, 3,141, 70, 13,141,198, 61, 23,128,189, -246, 63,110,220,184, 74, 11,128,171,130,192,184,113,227,170, 92, 71,200,229,232,208,209, 18, 20,119,229,242,101,220,180, 90, 60, -198,141, 27,231,114,212,126,255,167,251, 67, 34,150, 64, 38,147, 65, 42,149, 66, 34,145,160,168,168,200,105,230,111,167,237, 55, -104, 3, 28,187,108, 29,126, 1, 48, 98,233,255,129, 79,155, 13, 18,151,140,243,185,101, 32, 65,129,184, 94,160,177,104,255, 46, -186, 0,236,250, 31,177, 9, 2,246,215, 14, 97, 48, 0, 2,139,178,247,151,121,223,194,232,205,102, 51,190,249,230, 27, 12, 30, -252, 87, 92,216,193, 73,225, 64,177, 30,237,247,148,163, 71, 72,203, 26, 73,214, 16,229,110,239,242, 84, 56, 72,235, 44,195, 38, -245,176, 40,212,101,141,112, 89,144,120,208,223,107, 21, 2,234, 61, 11, 96,233,210,165,155,102,204,152, 17,114,238,194,133, 56, -131,193,208, 77,161, 56, 36,147, 72, 37, 66,138, 80, 56,116,232,144,111,167, 78,157, 54,196,198,198,254,107,236,216,177, 14,181, -245,204, 67,251,185, 81, 47,141, 58,220,189,123,207, 57, 52, 99, 26,113, 61,231,218, 18, 46, 47,151, 1,192, 75, 65,153,187,182, -105,159, 22, 26, 26,178, 71, 32, 20,255,248,239,121, 73,244, 23,139, 62,119, 88, 75,125,250,244,249,124,232,208,161, 0,128,146, -146, 18, 28, 56,112,192,239,187,239,190, 91, 2, 0,167, 78,157,234,211,185,115,231,125, 79,132, 0, 96, 91,248,231,217, 31, 55, - 58,210,236, 93,153, 18, 72,182,205,217,194,247,154,211, 15,193, 93, 27, 87, 50,253, 74,115,234,197, 34,156, 89,254,187,171,102, -171,134,154,147, 74, 0,240, 29, 59,118,196,197,139, 23,171, 48, 22,149, 74,149, 11,160,181,139,210,252,131,180, 4,220,247,155, - 63,254,240, 35,140, 70, 35, 76,180, 9, 52, 77, 99,249,242,229,117, 45,146,195, 47, 95,190,188,242,130,227, 88, 72,101, 62, 48, - 24,140,184,124,233, 18,132, 34, 17,204, 52, 13, 47,111, 47,108,218,180, 9, 2,129, 0,113,113,113,120,246,217,103,249,178,178, -218, 3,188,150, 47, 95,190, 47, 33, 33,129, 78, 77, 77, 13,181,149, 77,181,117, 0, 92, 50,109,206,153, 51, 7,199,142, 29, 67, - 69, 69, 5, 42,116, 58,104, 53, 26, 43,243,215, 64,171,209,162, 66, 91, 1,157,221,128,239, 76,217, 69, 70, 70,242,217,217,217, -149,218,127, 77,211, 0,157, 93, 4,200, 58, 23,191, 74, 93,216,152,190,205,247,232,202, 42,133,182, 21,254, 0,192,199,203, 7, - 82,153, 20, 90,173, 54,218,230,218,113,131,249, 63,144,249,218, 54, 33, 96,204,210,239,192,111, 5, 26, 77, 74, 69,230,123, 49, - 24,152,244, 19, 32, 18,193, 91, 90, 63, 63,103,117, 65, 0, 0,198, 29, 27,231,224,173,123,232,186,207, 11, 69,191,234, 81,190, -248,175,187,102,179, 25,131, 6, 13, 2, 0,132, 7,202,240,223,212,230,248,116,217,109,124,117,198,224, 72, 35,182,159, 22,135, -218,254,183, 75,155,233,198,152,213, 80,115,235, 27,194,231,255, 32,191,183, 82, 8,104,136,246,247,229,151, 95,126,249,198,164, - 55,246, 62,213, 59,178,143, 86,163, 9, 98, 88,198, 20, 22, 22, 86, 18, 30, 30, 94,164,209,104,206,143, 29, 59,214,233, 65,225, -215,237,191,114, 0, 54,189, 54,225,173,172, 1, 3, 7,110,151,201,100,254, 4, 60, 71, 8, 1,199,241,106,131,174, 92,113,245, - 66,190,214, 91, 34,118,106,156,183, 49,127,192, 18, 72, 93, 61, 80,111,217,178,101,255,122, 34, 4, 0, 43, 83,119, 88, 97, 59, -118,236,112,185,177,158, 89,254, 59, 15, 0, 54, 65,192,142,241, 55, 36, 67,119,187, 35,117,237,218, 21,167, 78,157, 66, 73, 73, -165,137,176, 53, 0,216,152,223,196,137, 19, 31,117,125, 85, 41,163,148,148, 20,254,181,137,175, 97,245,234, 53, 86,159, 57,131, - 57,115,230,212, 57,125,201,197, 21,244, 44,154,211,193,131,142, 54,155,232,184,124,249,242,107, 9, 9, 9,197,169,169,169,130, -132,132,132,202,128, 64,235,180, 64,167, 7, 58,155,198, 60, 96,192,128, 6, 47,187,200,200, 72,222, 94,139,183,143, 1,112, 99, - 5, 64, 2,128,223,180,105,211,125, 90,190,213, 66,224,114,123,222,180,105, 19,113,213, 98,224, 12,234, 50,253,187, 42, 44,140, - 93,182, 14,176, 91,248,103,200, 71,127, 77, 71,214, 53, 84, 69,217, 89, 0, 28,173, 4, 88, 56,160, 16,133, 0,122,125, 26,136, -197,167,219, 33, 4, 64, 73,174, 14,109,218,180,177, 48,141,197,129,120,238,169, 16, 68, 60,151,227,172, 70,236,180,123,211,154, -150,184, 59,222, 52,208,152, 87, 47, 90, 15,233,123, 27, 12,235,214,175,187, 6,224, 90, 67,209,251,241,167,111,243,208, 0, 81, -161, 13, 25,152,103,197,172,135, 81,158, 15,123, 51, 32, 50,122,244,232,168, 29,203, 31,203,189, 0, 8, 0,254,169,167,158,194, -158, 61,123,140, 86,166,207, 1,240,122, 64,150,135,122,195, 22, 36,152,152, 56,141,183,106,254,143, 36,111,115,230,204,105, 89, -147, 89,210,110, 26,161, 43,218, 14,121,192,117, 92,153,159,250, 46,251, 91,219,170,124,174, 50,113, 71,107,251, 55, 4,234,227, - 18,152, 59,119, 46,110,220,184,209, 96,121,113,102,121, 95, 87,113,230,131,114,156,129, 37, 48,116,112,172, 12,191,157,104,135, - 48, 47, 31,252,153,125, 15,237,157,100,254, 78,180,191,199,117, 57, 92,242,128,222,245, 44,207,238, 28,154, 54, 48,189,228,135, -149,241,135,190, 27, 96,117, 11,131, 27,150,132, 7, 46, 4,140, 28, 57, 82,250,132, 53, 64,183, 52,251,134,250,237,212,212, 84, -219, 10, 53, 76, 66, 66, 66,125,167, 50,121,208,240,204,191, 94,117,145,148,148,212, 32,117,153,154,154, 42, 76, 24,152,240,192, -219,197,145, 52, 3,142,164,229, 60,246,125,214,211, 50, 61,120,228,141,208,221,125,132, 61,240,192, 3, 15, 60,240,192,131, 39, - 23,148,167, 8, 60,240,192, 3, 15, 60,240,192, 35, 0,120,224,129, 7, 30,120,224,129, 7, 30, 1,192, 3, 15, 60,240,192, 3, - 15, 60,240, 8, 0, 30,120,224,129, 7, 30,120,224, 1, 0,156, 4, 80, 98, 61, 63,145,168, 50, 11,224,220,185,115,110, 71,166, -214, 20, 76,232,161,231,161,231,161,231,161,231, 36,189, 58,167,137, 62, 6,244, 60,245,235,161, 87,133,249,159, 61,123,118, 24, - 96,217, 96,146, 16, 98,124,220,190,215, 99, 1,240,192, 3, 15,224,239,239, 79,249,251,251, 19,127,127,127, 17, 0,193,227,150, - 63,219,190,243,118,251,207,215, 23, 53,173,143,239,193, 99,132,255,251,191,255,139,122,194, 63,161, 15, 0,219,178,195,162, 39, -245, 35, 60, 2,192,223, 28,245,216,110,221,101, 12, 27, 54, 44,202, 58,232, 86, 30,214,123,127, 75,122,143, 57, 72,203,176, 48, - 2, 0,106,181,154, 83,171,213,188, 90,173, 54, 3, 96,221, 33,246,246,115, 93, 11,166,140,232, 58, 26, 0,166,140,232,250,195, -219,207,117, 93, 3, 0,115,198, 60, 69,230,188, 28, 41,122,123,120, 23,183,214, 20,177, 95,138, 54, 45, 45,173,202,230, 59,245, - 97,254,118,237,190, 33,215,218,175, 47,205,134,166,247,196, 50,255, 61,123,246, 40,254, 6,159,194,160,225, 86,116,172, 21, 77, -130, 37,164,109,227, 80,170,133,188, 25, 9, 11, 8, 22,120, 75, 68, 13,246,123,194,191, 73,155,162, 0,200, 96, 49,199,112,240, -160,138, 0,224,196,222, 42, 38, 0,146,250,254, 84, 70, 70, 6,146,147,147,171, 44,255, 55,107,214, 44, 91, 71, 39,238,208,227, - 54, 7, 86,173,232, 87, 50, 30, 23,122,143,125,213, 71,120,203,248,136, 86,114, 0, 64, 17,205, 76,104, 44, 22,254,100,123,120, - 69, 83, 33, 41, 42, 45,165,157, 33, 52,121,120,151, 28,150,229,195,159,238,223,200,175,125,251, 1,251, 37, 18,234,214,180,164, - 62,255,254, 15,185,136,123,106,253,255,137,132,228, 87,128, 92, 2,208,217,213, 76, 86, 95,138,182,158,203,205, 86, 97,254,118, -109,223,221, 65,154,184,120,255, 97,211,123, 98,153, 63,199,113, 32,132, 96,240,224,193,252,145, 35, 71,136,139,117, 44, 6, 96, -110,136,252, 4, 5, 5, 77, 81, 42,149, 95,187,249,186, 4,128,209,206, 18,208,160, 24,208,173, 7,121, 45, 60, 66,168,106,209, - 72, 16,218, 49,156, 18,146, 80,162, 87,171, 57, 41,194, 88,170,103, 51,246,245, 81,195,217,250,254,134,179, 2, 64, 8,128, 72, - 0,217,176, 4, 61, 60, 78,240, 3, 48, 20,192, 24, 0,219, 0, 28, 0,160,105, 0,186, 63, 3,120,181,129, 24,236,163,147,140, - 40,135, 70,158, 62,214, 14, 21, 10,160,216,221,129,119,230,204,153,104,209,162,197,125,219,133, 38, 39, 39, 71,231,231,231, 43, - 86,174, 92,233,202, 32,204,175,159,238,141,248,129,247,111, 46,195,109, 14,196,134,255,210,152,180, 74,247,200,232, 45, 95,190, - 60,234,195, 15, 63, 84,196,197,197,225,231,159,127, 38, 0,240,206, 59,239, 68,173, 93,187, 86,209,162, 69, 11,112, 28, 7,131, -193,128,168,168, 40,108,221,186,213, 33,205,117,203, 63,139,106,255,225, 22, 69, 70,175,102,209,243,179,211, 51, 1, 96,205,194, - 53, 81, 87,231, 51, 10,182,133, 31, 52,156, 55,202, 13,126, 40,246, 63, 21,125,242,198, 39,153,142,232,181,106, 22,214,184,133, - 88,118,119,250,180,137,166, 48,153, 88,172, 81, 26,200,242,239, 54,254,244,209,212,215, 16, 40,147,241, 70, 51,203,127,178,250, - 59, 83, 81,105, 41,105,220, 56, 88, 88, 84, 84, 86,107, 35, 57,179,237,229,182, 59,118,222, 14, 24,240,116, 72,114,207,222, 65, -162,245,235,175,203, 67, 26,201, 74, 63,127,239, 68,242,140,151,122,176, 79,247,111,148,149,115, 77,155, 63, 41,190,245,200,111, -246, 95,172, 15, 83,172,175, 38,197,215,100,241,170,167, 16, 80,219, 59,238,230,181,161,233, 61,177,204,127,214,172, 89, 24, 60, -120, 48,255,223,255,254,215, 29, 82, 52, 44,102,119,166, 1,178, 85, 20, 20, 20, 52, 70,169, 84,110,115,227, 93,127,171,210, 25, - 8,224,110,124,124,124, 0,128, 41,214,107, 27,238, 1,248,117,195,134, 13,185,206, 18,253, 98,237, 23, 20, 93,106, 18,209, 38, -163,180, 28,102,169, 72, 36, 20,106,140, 82, 74, 44, 54,112, 2, 63,111,134,150,153,205,194,162, 59,166,239,191, 89,111,124,125, -242, 36,182, 62,109,199, 25, 23, 64,115, 0, 63, 0,136,177,158,155, 63, 70,109, 42, 24,192, 38, 0,207, 3, 56, 14, 96,132,245, - 58,184, 1,104,191, 2, 39,252,165, 15,211,196,254,128,208, 15,192, 85, 0, 17,238,104, 35, 54, 19,186, 61,243,159, 53,107,150, -194, 78,243,175,124,230,140,185,221,150,198,158, 89, 83,175,148,131,122,165,188,242,218,246,236, 81,208, 3,128, 19, 39, 78, 40, -164, 82, 41,178,178,178,238, 19,182,242,243,243, 73, 65, 65, 1,233,215,175, 95,244,238,221,187,157, 42,195,198, 39, 46, 41,120, -169, 8,221, 74,196, 85,180, 97, 66,241, 88,147,255, 6,249,161, 32,142,200, 71, 92,140,102,238,188,224,208,108, 26,213, 74,206, -183, 16,203,238,190,255,238, 4, 83, 51, 31,177, 88,125,233, 24,241, 42,190,128, 25,131,218,162,105,128, 12,197,103,142,146,123, -167,143, 81,179,166, 76,164,163, 90,201,249, 14, 94,190,230,186, 52,152, 70,141,196, 67,196, 98, 74,122,252,248,221,153,167, 78, -222,233, 24,214,172,149, 57,160, 81, 51,226,235, 11,175, 86, 17, 94, 17, 65, 65,146, 54, 28,207,155,118,157, 44,214, 61,194, 54, -204,219, 51,123,219, 81, 67, 31,229,157,165, 85,237, 92,253,168, 41,221,195,162,247,196, 50,255,221,187,119, 43, 8, 33,160, 40, - 10,217,217,217, 56,122,244,168, 91,180, 88,150,189, 96,181, 0, 52, 68, 60,139, 76,169, 84,110, 11, 10, 10,122,217,141,119,205, -214,250, 50,197,199,199,135, 1, 88,113,240,224,193,127,103,100,100,188,111, 59, 14, 28, 56,176, 92,161, 80,228,196,199,199,207, -119,134,224,172,185,179,132,165,119, 74,188, 12,188, 41,128, 23,146, 80, 94, 34,105,204,137,196,141, 57, 66,133,114, 68, 24,194, - 8, 4, 65, 28, 71,252,117,132,245, 97,196,148,236,155, 99,123,132,210, 23, 67, 31,168, 0,240, 5,128,131, 0,102, 88,207, 95, -212,163,176, 3, 1, 44, 0,176,219, 90,112,187,173,215,129,110,210, 59, 2, 96, 15,128, 4, 0,107, 1,252,195, 74,243, 72, 61, - 27,133,191,245,236,221, 0, 26, 54,172, 26,246, 2,235,249,113,195, 83, 0,142, 1,104,108, 21,158, 94,115,229,229,140,140, 12, -133,189,217,127,214,172, 89,138,228,228,228,232,228,228,228,104,123, 33, 32, 57, 57, 57, 58, 35, 35, 67,225, 12, 61,123, 51, 61, -245, 74, 57,174,237,153,136,107,123, 38, 86, 97,218,220,230, 64,184, 75,207, 42,228, 16,119,232,165,164,164, 68, 29, 63,126, 28, - 19, 38, 76, 64,126,126, 62, 18, 18, 18,162,106, 74, 35,149, 74, 21, 77,154, 52,113, 88,126,169, 41, 41, 81, 77,142,255,129,130, - 9, 3, 32,206, 87,227,235, 5,159, 71, 85, 87,142, 83, 82, 82,163, 68,198, 22,138,160, 38, 6,135,204,127,202,228, 87,232, 79, -102, 78,228,197,183,206,136, 3,239, 93, 36, 23,239,106, 16, 30,226,141,167, 59,133,161,169,234, 42,110,104, 13, 16,114, 60, 2, -136, 64,244,207,183, 38,240,211,223,121,243,106, 84, 43,121,173, 76,167, 92,165, 13,234,211,199, 39,185,107,191,231,205,190, 65, -173, 37, 62, 1,161,156,204,199,219, 20,212, 40,216, 24, 18,222, 92, 88,174,212, 74, 52,106, 6,229,106,147,211,131,144,213,207, -239,144,113, 58, 25, 15,112,159,230, 95,147, 80,238,130, 16, 64,106, 56, 87, 63,106, 74,231, 20, 61,126, 75,224,125,135,139,244, -158, 56, 80, 20,197,239,221,187, 87,193,113, 28,222,123,239, 61, 16, 66,112,244,232, 81, 88,182,222,229,136, 27,244, 64,211,244, - 89,171, 5,160,190,110,108, 37, 0, 40,149,202,173, 65, 65, 65,209,238,240, 79,154,166,133, 0,190, 62,112,224, 64,252,162, 69, -139,238, 16, 66,196,182, 3,128, 40, 56, 56,152, 28, 58,116,104, 94,124,124,252,116, 71, 4, 5, 68, 36,161, 25,222,207,100, 50, -135,178, 28,215,140,229,184, 8,150,144, 22, 16, 8,130, 9, 33, 1, 32, 2, 63,142, 71, 16, 79,115, 1, 26,131,217, 59,212,143, - 17, 80,125,180, 15, 76, 0, 8,183,106,252,159,194,178,219,231,167,214,235,112, 55,126,107, 34,128,124,107, 3,159, 11, 32,200, -122, 38,214,251,174,238,181,251, 47, 0,215, 1,172,177,154,131, 36,214, 6,241,149,245,126,125,246, 95, 30, 12,139,171, 99, 72, - 3,245,129, 55, 1,204,183,158, 31, 55,116, 6,176, 29,192,179, 86, 75, 74,103,119, 9,217,152,191, 61,211,183, 23, 2, 92,110, -156, 86,230,111, 67,117, 33,192, 29,122,213, 6, 88,226, 42,189,195,135, 15,131,166,105,244,238,221, 59,186, 67,135, 14,200,203, -203,171,252, 62,142,227, 32,151,203,249,121,243,230, 41,142, 31, 63,142,145, 35, 71, 58, 28, 80,140, 89,167, 64,209, 12, 84,189, -229,209,166, 14,193,184,190,238,240, 95, 76,139,227, 49, 77,190,142, 63, 60, 47, 88,113,243,184, 63,134,189,113,205,241, 0, 69, - 9, 42, 74, 46,102,113, 69, 42, 35,202, 42,104, 62,166, 71, 11,222, 95, 38,198, 29,149, 14, 37,106, 3,226,122,182,224, 41, 66, -248,223,127,221, 7,245,145, 19,252,153,109,187,110,213, 69, 46,235,108,211,105, 33,161,126,173,155,182,136, 96,188,100, 92,235, -193,207,199,249,180,234,157,240, 66,227,118, 47, 14, 11,106, 26,217, 93, 89,209, 56,198, 76,155,205, 55,114,117,126, 78, 50,127, -222,217, 45,104,211,210,210, 20, 14,102, 6,212,248,204, 9,151,156,103,118,192, 67,212,252,121,158,135,217,252,151,203,126,224, -192,129,182,254,226, 46,227, 50,139, 68, 34, 51,199,113,199,173, 90,120,125,132,128,208, 74, 73, 64,169, 84, 4, 5, 5, 37,184, -240,110,185, 74,165,146, 28, 62,124,248,181, 3, 7, 14, 60,255,253,247,223,151,205,155, 55,175,197,198,141, 27,209,174, 93, 59, - 0, 64,203,150, 45,161, 86,171,201,194,133, 11,139, 15, 29, 58,244,121,124,124,252,192, 58, 41,114,140,148,101,153, 32,150, 97, -155,153, 89,115, 27, 1, 69,154,138,133,148, 72, 42, 18, 24,132, 94, 98,149,183,175, 64, 35,144,242,140, 84, 32,240, 22, 50,180, -223,205, 51,103, 37, 19, 67,190,112,187, 61, 59, 18, 0,158,179,106,135,246, 56,102,189,239, 10,198, 3,120, 15,128,220,202, 8, -255, 0, 80,110, 61,207,183,222,127,207,154,206, 25,120,193,226,107,137,183, 94,155,236, 14, 88,239, 79,193,253, 91,249, 58,139, - 87, 0,124,103, 61,215, 23,111, 0,152,102, 45,179,105,214,235,199, 5,109, 96, 9,154,220, 5, 32, 17,192, 84, 0, 81,158, 97, -171,118, 20, 22, 22, 42,250,246,237,139,169, 83,167,102,246,237,219, 23, 39, 78,156,192,218,181,107,163, 26, 55,110,172,160, 40, - 10,121,121,121,164,180,180,148, 76,159, 62, 61,250,200,145, 35,138,201,147, 39,215,217, 57,251,223,188,163, 40,234,219, 17, 9, - 83,167,102,254, 25,198, 70,119, 86, 7, 41, 82,215,166, 70, 89,164, 19, 96, 77,222, 27,100, 83,105, 12, 25, 60,189, 48,250,104, -154, 92, 17,253,244,167,181,214, 79, 1,205,172,248,250,235,141, 65, 91, 47, 20,222,222,120, 38, 95,181,238,248, 13,221,205, 34, - 35, 79,241, 20,140,122, 22, 37, 37, 52,178,243,203,217, 29,121,133,218,221,119,138, 84,191,220, 42,184,114,172,168,120,248,109, -147,249,179,218,104,250, 5,134, 55, 51, 84,148, 55,237, 20,249, 12, 69,147,150,131, 11,175,108, 55, 4, 6,121,203, 90,117,236, - 81,194, 51, 37, 23,136,192, 47,132,227, 56,193,189,123, 6,103,172,120,188, 45,226,223,142, 17, 87, 55,131,219, 95,195,154,158, -119, 66,195,174,212,244,109,135, 51,233, 61,120,176,168,168,168, 80, 0,128, 80, 40,196,236,217,179,145,157,157, 13, 55,253,254, -246, 48, 1, 48,153, 76, 38, 83, 97, 97, 97, 6,234, 23, 16,168,173, 98, 14, 80, 42, 83,131,130,130, 70, 57,249,174,212,104, 52, -134,207,153, 51, 39,249,157,119,222,209,119,237,218, 85, 2, 0, 11, 22, 44, 64, 78,142,101, 55,202,126,253,250,129,227, 56, 12, - 28, 56, 80, 50,126,252,120,237,149, 43, 87, 14,189,241,198, 27,125,188,188,106,102, 77, 28,199, 51,153, 7, 15,238,205,203,187, - 49,158, 53,179,141, 4, 34,153, 73, 64,164, 58, 74, 34,214, 83, 82, 47, 45, 45,242,170, 0, 37, 81,115, 82,214,172, 85,151,249, - 40,118,158, 27,197,158, 58,235,118, 0,183, 35, 1, 96, 56,128, 67,213,238, 29,178,222,119, 22, 2, 0, 31, 1,136, 3, 80, 86, - 75,154, 50,235,243,143,224,156, 95,103, 60,128,253, 0,212,181, 60, 87, 91,159,143,119,163, 76,158,129, 37,134, 96,153,245,252, - 76, 61, 26, 87,140,213,106,210,207,154,159,126,214,235, 24, 23,233, 4, 2, 8,112,226,112,213,149,210, 31,150, 85,172,108, 65, - 72,183,172,150, 30,183,226, 60,170,107,252,213, 45, 2,174,130,219, 28,136,182, 35,127,168,188,110, 59,242,135,251,162,248, 93, -165, 87,141,153,240,174,208, 91,189,122, 53,159,157,157,192,140, 1,163, 0, 0, 32, 0, 73, 68, 65, 84,141,211,167, 79,163, 89, -179,102,252,111,191,253, 6,141, 70,131,203,151, 47,223,167,209,126,244,209, 71,153,157, 58,117,138,222,178,101, 75,173,244,190, - 89,189,154,111,158,125, 17,161,167,115,160,104, 54,146,239,122,149, 81, 80, 26, 51,216,203, 21,247,165,125,255,163,183, 50, 91, - 68,158,142,190,245,199, 43,181,106,207,215, 11, 10, 62, 40,160,153, 21, 37,165, 6, 57,109, 96, 3,115,238,104,124,118, 95, 41, - 44, 51,181,236,142, 78,161, 65, 0,128,221,231,238, 9,115,139, 42,252, 0, 4, 22,209,198, 78,183, 77,230,216,220,194,194, 15, -106,163, 57,228,133, 56,170,195,224, 37, 93, 25,221, 31,249, 45, 58, 14,149,137, 68, 44,125,253,143, 12, 85, 97,254,229,123,197, -249,191,231,107,148,133, 0, 69, 17,165,150,246,159, 18,215,211, 81,187, 33,177,177,177,213,153,113,117,179,186,253, 53,172,233, - 31, 86, 52,190, 7, 13,136,193,131, 7,243,135, 15, 31, 6,183, 57, 0, 60,207,227,243,207, 63,199,145, 35, 71,108,130,154,219, -117, 80, 94, 94,110, 34,132, 12, 58,117,234,148, 49, 60, 60,124, 88, 61,173, 58, 1,128,101, 54,128,245, 60, 17, 0, 23, 20, 20, -228,140,162,102,108,220,184,177,122,223,190,125,111,110,220,184,209,255,232,209,163,226,161, 67,135,170,109,204, 31,176,108,119, - 47,145, 72,112,235,214, 45,106,239,222,189,126,129,129,129,119, 7, 12, 24,144,203,113, 53, 79, 86,107, 27,209, 78,219,175, 95, -191,152, 75,151,254,124, 70,163,211, 54,230, 25, 51, 3, 10,102,198, 68,153, 76, 38,147, 65,131, 34, 13,103, 50,106, 11,243,139, -152, 93,187,247, 36, 53, 10, 14, 41,166,105,189,219,179, 16,168, 26, 58, 6,101, 61,154,194,226, 23, 62,108,119,143,178, 94, 55, -182, 62,183,221,171,171,131,206,128, 37, 64,239,102, 53, 58,213,143,155,214,116, 51, 28,208,163, 0,140, 5,240,189, 3,122,223, - 91,211, 81, 78,208,179, 29,173, 96,137,115,248, 24,150,153, 4, 31, 91,175, 91, 85, 75,231, 12,189,241, 0,222,177, 50, 89,131, -245,158,193,122,253,142,245,185, 51,244,226, 97,137,115,112,246,136,119, 34,127,159, 1,248, 15,128, 81,214, 50,167, 0, 72, 1, -156,176, 90,101,250, 2, 72,178, 62,175, 43,127, 24, 54,108,216,125,190,126, 91, 16, 96,245,216,128, 97,195,134, 57, 20, 6,134, - 13, 27, 22, 93,221, 55,223,118,228, 15,247, 49,127,234,149,114,184, 75,207,166,101,186, 74,239,220,185,115,104,209,162, 5,238, -221,187, 71, 10, 10, 10,200,221,187,119, 73,255,254,253,239, 11, 6,172, 52, 83,121,121, 41,164, 82,105,173,244,228,231,206, 65, -213,162, 9,122,220, 59, 65,162, 11,246,144,151,238,110, 38,103,125,138,163,217, 44,117,141, 76, 62, 63,135,134, 68, 90,183,178, -115,189,160, 96, 78, 1,205,196, 20,208,204,138,219,180,249,243,115, 55, 75, 66,244, 12, 3,181,209, 98, 28,187, 84, 82,130,155, - 70,122,195,109,147,121,205,109,154,249, 34,183,176, 48, 29,117, 76,157,109, 42,239, 48, 39,160,105,191,208,210,252, 3, 90,134, - 49,149, 23, 22, 73,155, 93, 56,113,202,255,242,185,243,109,242,110,177, 61,111,223,188, 13,177, 72, 24,218, 57,204,123,188, 74, -107,110,227,168, 62,210,210,210, 72,108,108,172, 83, 66, 97,108,108,108,116, 90, 90,154,203,140,194, 62, 16,240,113,158,161,243, -119,198,144, 33,131,249,204,204,204,202, 24,135,253,243,124,193,243, 60, 6, 15, 30, 92, 31,211, 63,172, 76, 58, 26, 0,158,126, -250,105,125, 53,193,209, 45,121, 34, 40, 40,104,130,157,114,106, 82, 42,149,187,149, 74,229,186, 58,222,177,165,229, 0, 84,132, -133,133, 93,120,233,165,151, 86, 47, 93,186,212,235,252,249,243,254, 50,153, 12, 47,190,248, 34, 36, 18, 9, 56,142,195,200,145, - 35, 43,102,206,156, 25,208,165, 75,151, 43,147, 39, 79,238, 60,121,242,228, 50,163,177,230,133, 3, 19,166, 37,112,127, 94,190, -118,170, 75,215,110,175,157, 58,121,114,236,206,221,191, 46,201, 62,121,178,241,165,156, 43,210,107,133,185,252,143, 43, 55,203, -150, 38,127,218,233,192,238,221,201,109, 90,183,217,229, 19,230,125,100,195,134, 13,110, 79, 7, 20,214,160,173, 71, 2, 24, 0, - 96, 17,128,233,214,193,210,187,154,217,238, 7, 88,252,236,159,192,226, 18,200,174, 67,192,120,202,170,253, 58, 99,142, 63,110, -181, 46, 80,117,208, 11, 1,208, 18,192,105, 7, 52, 79, 91,211,133,162,246,169,139, 20, 44,129,121,129, 86,198,249, 18, 44, 83, -255,114,172,180,115,172,215, 27, 97,241,147,111,128,197,117, 65, 59,160,247, 10,128,111, 0,116, 0, 80, 84, 45,159,119, 97, 9, - 90,188, 98, 77,187,217, 1,189,247, 96,153,221,160,119,162,252,188, 0,236, 3,240,147,131,250,120, 25,192,191,173,231,179,118, -249, 19, 89,235, 50, 13,192, 42, 0,139,173,207,239,214,246,131, 25, 25, 25,153, 0,144,159,159,175,176, 69,251, 87,215,250,243, -243,243, 21,246,105,235,130, 45,205,134,255,210,149,209,249,213,181,244, 13,255,165,241, 40,232,101,101,101, 97,208,160, 65,184, -114,229,202, 95, 76, 92, 46,143,222,178,101,139,162, 85,171, 86,209, 28,199, 41, 90,182,108,201,219,166, 1,238,218,181, 11,145, -145,145,209,123,247,238,173,145, 94,251,172, 44,252, 28, 28, 90,165,172, 58, 38, 14,135,238,211,219,192,179,161,224, 57, 96, 90, -203,239,248, 10,206, 7, 74,131, 31,148, 57, 65,232, 62,104,103,244,229, 95,234, 54,179, 95, 47, 40,216, 10, 96,107,235, 22, 77, -219, 3,248,135,137,229,144,126, 33, 15,131,194, 44,238, 78,194,243, 90, 45,195, 44, 42, 46, 46,190,231, 4, 51,253,148,231,121, -239,156, 43,202,215, 84,167,183, 52, 42,190,171, 68,241, 61, 45,132,194, 50,239,138,114, 30, 42, 13,203,135,134,136, 3,132, 28, -198, 24, 76,236,207,139,222,123, 58,224,147, 47,142,171, 28, 8, 1,153, 78, 12,216,164,154,187,192, 53, 12,181, 90, 94, 14,196, -185,250,166,205, 26,230, 40, 42,223, 62, 29,113,150, 30,137, 43, 71, 61,233, 61, 9,224, 51,167, 93, 4,210, 45,147,177,246, 95, - 96,176, 78, 97,233, 99, 46,206,249,175,181,109, 8, 4,130, 16,161, 80, 88,124,252,248,241,111,159,126,250,233,250,148, 89, 11, -165, 82,185,198, 42, 88,188,162, 84, 42, 55,219,206,117,188,179, 9, 22,151, 41,111, 29,187, 43,150, 46, 93, 58,125,198,140, 25, - 77,207, 93,184, 48,212, 96, 48,248, 42, 20,135,136, 68, 42, 1, 69, 40, 28, 58,116, 72,212,169, 83,167,179,177,177,177, 35,199, -142, 29, 91,225, 40, 67,153,135,246,115,163, 94, 26,117,184,123,247,158,115,104,198, 52,226,122,206,181, 37, 92, 94, 46, 3,128, -151,130, 50,119,109,211, 62, 45, 52, 52,100,143, 64, 40,254,241,223,243,146,232, 47, 22,125,238,118, 65,214, 36, 0,252,195, 42, -225,188, 0,224, 50, 0,159, 26,222,219, 99,213,216, 99, 96,153, 71, 30, 95,135,249,191,173,181,192,156, 17, 0,202,172,233, 5, -117,208,139, 2,112,205, 73,122,215,172,233,127,169,131,222, 20, 0,147, 0, 92, 4, 48,211,250, 93,246,180, 21, 0,242, 96,241, -223,239, 6,176, 30,150, 25, 7,181,209,155,104, 45,143, 30, 86, 43, 66, 77,249,212, 88,159,167, 88,133,128,245,117,208,251,222, -218,208,188,156, 28,188,190,119, 80,126,159, 89, 45, 27,251,173, 66, 13,170,209,254, 13, 64, 39,107, 93,228, 88, 5, 41,135,166, - 93,235, 60,127, 69, 3, 45, 4, 68, 38,173,210,241,147, 86,233,106, 88,184,167, 28,143,138,222,159,127,254, 73,254,252,243,207, - 42,247,126,250,233,167, 76, 0,100,243,230,205, 0, 64,110,221,170, 26, 83, 87, 27,243, 7,128,230,127,254, 73,128,170,244,222, - 94, 50,203,194, 28,151, 89,243, 84, 61, 68,239, 23, 23, 70, 97,150,207,131, 16, 16, 84,160,146,249, 91,185,250, 61,169, 84,234, -148,217,144,231,121, 66, 8, 89, 48, 39,174,179, 87, 88,179,150,163, 56,120,181, 45,200, 47, 18,152,141, 42,190,113,168, 15,241, -241, 22, 17,198,204,161, 92, 69, 51, 68, 70,100,106, 45,211,166, 14,133,160,182, 54, 91,253,255, 71,201, 0,237,221, 17,206,204, -219, 39, 15,153,222, 99,207,252,185,205,129,216,127,193, 50, 69,127,189,130,198,207,199,105, 91, 76, 6,105,168,250, 97, 89,182, - 12, 0,122,245,234, 85,175, 5,129,108,204,223,138, 82,235,217, 81,223, 72,180, 27, 79,205, 0, 10, 0,224,203, 47,191,124,249, -141, 73,111, 12,123,170,119,228, 24,173, 70, 19,194,176,140, 49, 44, 44,172, 48, 60, 60, 60, 87,163,209,108, 27, 59,118,108,169, -179,249,250,117,251,175, 28,128, 77,175, 77,120, 43,107,192,192,129,219,101, 50,153, 63, 1,207, 89,102, 78,240,106,131,174, 92, -113,245, 66,190,214, 91, 34,174, 87, 64,107,117, 1,128,133, 37, 72,205, 25, 63,252, 41,235,193,162,246,229, 69, 89, 88, 34,234, -157,157,175,169,128,101, 33,159,186,232,237,128, 37,104,205, 25,188,230, 68,254,190, 6,240,173,163,177, 31,192,187,118,239,212, - 69,239, 7,171,197,192, 17,242,172,154,189, 51,249,115,101,190,235,215, 14,232, 61,235, 4, 61,155,181, 97,189,181,108,156, 49, - 49,145, 97,195,134, 69, 85,143,250, 31, 54,108, 88,180, 51,154,122,109,244,236, 86,234,123,220,232, 61,246,184, 81,120,215, 68, - 53,107,182,254,157, 79, 83, 38,217,238,209, 34,234, 39,163,158,219, 87,148,159,175,117,170,208, 8,225,255, 61,165, 31,249,248, -235,223,231,236, 90, 21,186,237,196,201,187, 83, 67,252,185, 23,169, 32,191, 0,158, 7, 8,225, 77, 38,134, 43,226,128, 82,218, -196, 5, 20,222, 53,184,228,143,180,154,249, 21,213,174, 31,151, 34,244,172, 4,232, 38,158, 91,172,125,208,223,200, 1,104, 34, -149, 74,239,246,234,213,235,217, 51,103,206,212,155,160, 82,169, 60, 24, 20, 20, 52, 73,169, 84,174,119,242, 21,129, 53, 31,149, -227,233,186,245,235, 50, 0,100, 52,212, 71,254,248,211,183,121, 86, 94,241, 64, 80,147, 0, 96,116,131, 14, 95, 71, 37,153, 60, -244,254,182,244,170,192,202, 72, 73,181,123,110, 55,206,199,157,222,147, 0,165, 94,255, 38,224,101, 6, 16,194,129, 47, 52, 26, -233,141, 69, 69, 37,231,225,194, 42,106, 31,127,253, 59,191,253,179, 17,228,133,233,251,178, 0,100,197,246,109,255,143,160, 32, -201, 92,161,128,240,119,203,140, 87,239,210,204, 6,153,136,146,202,132, 2,129,153,225,164,174,228, 47, 45, 45, 45, 51, 54, 54, -214,182, 15,128,205, 61,224, 58,103,173,238,235,183, 51,253,215, 35, 14,192,179, 18,160, 27,160, 94, 41, 7, 33, 4, 47,142,158, - 82,227, 24,178, 99,123,106, 67,125,107, 17, 0,210, 16,204,223, 78, 8, 88,239, 66,114,153,117, 76,165,159,212,186, 18,214,208, - 16, 27,114,142,172,135,222,223,155,158, 7,143,187, 0,160, 84,242, 74,165,114, 74,125,233,188,244,254, 62, 30, 0, 94, 27,220, -137,252,120,228,210,231, 6,126,218,170,233,227,142,119,162,117, 36, 34, 72, 36,108, 4, 66,244, 62, 50, 97, 73,151, 14,126, 57, -233,251, 93,163,109, 13,244,227,221, 9,248,123,192, 26,180,199, 2,224,198, 55,166,166,166,240, 9, 9, 83,201,142,237,169,127, -247,238,229,111, 21,164, 37,110, 42,206,143,190,178,220,221, 71,216, 3, 15, 60,120, 2, 37,126, 1,224, 37, 33,224, 56, 30, 32, - 4, 21, 6, 79,247,247,192,131,255,217,241,192, 83, 4, 30,120,240,191, 3,134, 5, 52,250,191,245,178,243, 30,120,224,129,147, -160, 60, 69,224,129, 7, 30,120,224,129, 7, 30, 1,192, 3, 15, 60,240,192, 3, 15, 60,240, 8, 0, 30,120,224,129, 7, 30,120, -224,193,223, 17, 85, 98, 0,206,157, 59,231,118, 52,106, 77,193,132, 53,209,123,225,153,200,168, 46,221,218, 40,154, 52, 11,143, -214, 26,116,138,195,138,172,232,140, 67,231, 51,221,165,215,181,239,240,168, 30,221,250, 42,238, 21, 22,194, 91,230,141,219, 5, -185,209,217, 39,246,184, 77,175,161,191, 55,113, 60, 21,213,175,111, 43,133,204, 91, 0,161,128, 2,145, 18,188, 56,238, 18,113, -151, 94,194,255,203,138,122,170,239, 83, 10,127, 31, 1, 32, 4, 98,251,214, 60,199,233, 81,125,175,135,222, 99, 75,175,206,169, -102,143,251,247,182,234,245, 50,239,199,229, 62,208,252,157,253,232,150,219, 3,105,207, 37, 45,239,187,247,121,163, 66,183,233, -253,163,244,254, 13, 87, 61,237,249,161,208, 19,162,134, 41,178, 79,226,247,186, 44, 0,212,134,149, 81,104, 11,203,122,248, 44, -128,220,153,153,184,233,236, 15, 12, 31,216, 42,138,128, 67, 72, 64, 16,178, 14,159, 81,124,152, 56, 17, 3,134, 14, 0,163,211, - 43, 58,117, 24, 12,142,131, 98,198, 91, 79, 71,247,236,217, 13,215,175,223,130, 90,165,195,234,245, 71, 50,107,163,215,123,208, -171, 81, 60, 8, 90,182,105,165, 72,120,127, 49,222,124,245, 57,252,240,159,175, 0, 72,177,231,124, 1, 40, 10,138,149, 11,230, - 33, 39,231, 42,228,242,150,144,200,132,184, 83,144, 19, 13,125,205, 89,158,251, 92,119, 94, 44, 22, 67, 38,147, 33, 55, 55, 23, - 77, 67,253,208, 72,232,131,166, 45, 2, 16, 40,243,135, 55, 97, 65, 81, 20,120,142,133, 94, 34,132,250,158, 26, 99,254,147,225, -176,162,150,207,233,198,251,202,212,240, 11, 16,195,199, 91, 8,177,140,130, 80, 0, 80, 98, 33, 50,119, 69,242,102, 94,128, 97, -163, 78, 56, 93,225, 93, 95, 90, 25, 21, 30, 30,142,102,173,155, 41, 12, 70, 19, 40,137, 12, 48, 3,211,146, 79, 69, 25,244, 58, -124,247, 73, 84,230, 35, 20, 36,255, 86,243,152,159,112,184, 90, 23, 78,167,143,253,112,174, 55,128,167, 26,203,188,254, 93, 88, - 88,216, 65, 36,149,128,243,242, 90, 6, 96,109,218,178,164,138,199,165, 0, 34, 58, 13,137,186,121,233,112, 77,251, 41,252, 45, -218,104,106,106, 42,249, 97,195,134, 43, 18,177, 88,198,113,156,191,183,143,143,207,168, 23, 95,244, 2, 64, 39, 36, 36,240,143, -105,158, 41, 0, 72, 72, 72,224, 26,128,156,159,191,191,255,172,246,237,219,143,149, 72, 36,205, 10, 10, 10, 10, 10, 11, 11, 79, -210, 52,189, 4, 64,174, 27,244, 2, 2, 3, 3, 23, 63,243,204, 51,207,135,133,133,201, 79,157, 58,117,239,226,197,139,199,141, - 70,227, 66, 88, 86,136,253,223,176, 0,212,194,252, 5,222, 18,225, 83, 19, 7,182, 94,193,241,188,241,232,213,123, 95,174,140, - 82,239,159,153,137, 75,142,222, 85,222, 61,200,155, 42,148, 48, 87,168, 32,100, 41,252,113,233, 42, 94,127,125,102,229,115,138, - 2,126,207, 90,143, 70, 45,194, 21, 92,133, 6, 52, 71,112,232, 80, 86,244,234,245, 71,106,161,216,146, 63,125,226, 18,136,151, - 31,206, 92,202,199,249, 75,111,224,187,159,127,171,124,202,113,192,136,254,253,129,138, 34, 0,190,200,189,120, 25,162, 70, 1, - 24,208,175,139, 66,165,175, 67,102, 33, 20, 64, 40,244,232,214, 11,141,189,197,104,218, 72, 10,191,224, 32, 4, 74,124, 17, 40, - 21, 64, 36, 16,192,204,178, 80, 49, 28, 78,149,158,118, 88,168, 11,223,109,206,203, 4,229,240,243,242, 66, 72,163, 96,248,249, -121,129,167, 88, 48, 92, 5, 88,176,240,241,241, 66,163,198,205,144,123,165, 29,223,186,195, 15,117, 14, 74, 61, 99, 86,241,254, -190,222,240, 15, 8, 68, 72,163, 96,232,116, 58,136, 37, 82,136,140,150,197,249, 34,228, 45, 21,202,114, 21,158,121,107,125,116, -126,193, 29,148, 23,221, 66,217,249, 84, 71,194,128,211,131,196,208, 73, 67,163, 15,172, 63,144,233, 4,173, 7, 42, 4,228,229, -229,241, 0, 32,151,203,201,227, 66, 47, 60, 60,252,117,154,166,215, 3,192,216,232,104, 42,117,203, 22,119, 6, 95,203, 26,169, -118,134, 28,158,231, 65, 8,169, 60,219,238,217,210, 57,216, 73,205,149,245,228, 93, 97,254,157,188,205,204, 86,223, 0,255, 14, - 0, 32,150, 73, 65, 27,140,224,116,250,229,199,143, 28, 94, 16,251,225,220,142,105,203,146,242, 29,209,249,242,163, 68,222,170, - 97, 49,176,184, 32, 57,235, 56, 84,227, 88,212,125,200,243, 24,242,220,255,185, 84, 71, 55, 47, 29, 86,180,233, 18, 21,125,253, -143, 76,215,133,226, 88,165, 75,201,227,226,226,176, 37,246, 64,157,105,162, 15, 84,221,138,164, 83,128,229, 83,139,141, 28, 12, -140,165, 94,117,214,115,106,223, 0,180,243, 21,213, 73,111,197,138, 21,153, 31,189, 55, 59,116,244,216, 49, 62, 70,163, 1, 43, - 63,255,140, 90,189,122,181, 49, 49, 49, 49, 28,192,157,134,238,123, 99,198,140, 25,186,109,219,182, 12, 87,133,168, 73,147, 38, -241,121,121,121, 40, 43, 43,195,210,165, 75,225,235,235,139,168,168, 40,200,229,114,172, 95,191,222,221,126, 55,184, 87,175, 94, - 27,222,127,255,253,235,237,219,183, 95,223,179,103,207,203,247,238,221,107,150,149,149,213,235,205, 55,223,220,173,209,104,150, -195,178,149,187,179,136, 30, 59,118,108, 90, 82, 82, 82,176,217,108,134, 76, 38,131,183,183,119, 19,157, 78,247,242,232,209,163, - 71, 93,184,112, 33, 17,150,141,211,158, 56,156, 59,119,174,186,149,192, 57, 1, 96,101, 20,154, 3,104, 13,203, 18,135,172,206, -196,220,206,186, 86,252, 69,255,182,161, 51,159,233,212,100, 65, 99,127, 89,211,149, 40,218, 4,224,234,204,204,218, 55,169, 49, - 85, 40,209,184,205,179, 88,252,193, 88,172,183,227, 73,135,143,167, 64,167, 55, 97,228,208,153,120,122,192, 36,188, 26,247, 12, -100, 50, 9,104,150,129, 86, 79, 43,106,111,100,183, 0, 26, 24, 59, 97, 45,222,126,127,106,229,221, 17, 79, 71, 65, 42,149, 96, -251,161,223,176,231, 88, 22, 54,172,251, 10, 70,131, 9, 98,129, 16, 62, 94, 98,232,202, 10,162, 85, 5,168,113,135, 53,158,231, - 1,158,179, 28, 20, 7,158,231, 97,162, 37,149,203, 59,240, 52, 11, 86, 0,176, 96,193,210, 28, 24,182,110, 1,118,206, 91,114, - 62,208,143,129,159,175, 55,194,155, 69,160, 67,215, 54,240,245,145, 65, 93, 81,130,162,146, 34,148,171,239,193,108, 36,240,242, -242, 66, 72,200, 0,148, 22,135,240,141, 66, 63,171,217,140, 63,120, 30,207, 24,244, 48, 8, 1,177, 84, 12,131, 94, 12, 90, 47, -134, 81, 42,129,144, 48,224, 33,128,209, 80, 1,131, 94,139,102,205,154, 42,196, 2, 33,148,208, 32,148,158,128,234,107,204, 87, -199,167, 27, 62,117,216,128, 62,136,255,160,238,177, 50, 54,182,202,254,238,177,177,177,189,131,130,130,114, 8, 33, 70,158,231, -133,129,129,129, 94,185,185,185,193,214,213,221,154,186,219,144, 19, 19, 19,199,217,253, 70,148,187,171,197,213,200, 45, 9,225, -167, 77,155, 22,189,122,245,106,151,104,134,135,135, 39,244,233,211,103,201,192, 30, 61, 96,150, 72,144,156,156,204, 77,125,229, -149, 97, 41,155, 55, 31,112,241,247,177, 98,193,130,202,235, 89,243,231, 35,121,225,194, 58,175,157, 33, 91,141,185,243,189,123, -247, 6, 0,126,232,208, 86,157, 1,220, 72, 74, 74, 51,184,200,252,179,186,118,238,236,103,235, 51,222, 82, 25,238,150, 20, 67, - 83,174, 66,175, 62,125,189,118,125,183,238, 64,236,135,115, 59,167, 45, 75,114,180, 54, 59, 51, 99,201,106,225,107, 47,143, 18, -182,149,203, 57,171, 16,128,249,201,171,170, 10,209,179,166, 3, 0, 62,122, 47,209,173,237,164,221, 98,254, 54,164, 5,185,144, -120,168, 75,164,189,133, 4,231, 23,190, 5,226,215, 8,236,141,243, 48,221,248, 19, 57, 74, 29, 34,247, 22, 59,245,126,207, 94, -189,142, 78, 25, 31,223, 50,126,242,155, 1,105, 63,253,204,201,229,114,106,113,210,114,248, 46, 88,140,237,219,183, 23,166,166, -166, 82, 13,101, 5, 24, 51,102,204,176,109,219,182,237,223,182,109,155,237,122,184,237,127, 7, 2, 74,212,254,253,251, 21,183, -110,221, 66,235,214,173, 49,104,208, 32,248,251,251, 67,165, 82,225,206,157, 59,184,121,243, 38,134, 15, 31,206, 15, 31, 62, 60, -122,246,236,217,174,212,211,152,103,158,121,102,229,138, 21, 43, 54,245,236,217,115, 37, 33,228,142,221, 56, 78, 98, 98, 98,124, - 0,100, 89, 15,167,232, 37, 38, 38,166, 79,155, 54,141, 58,125,250, 52, 8, 33, 8, 14, 14,174, 60,246,238,221, 43,238,215,175, -223, 87,183,111,223, 62,241,164, 51,127,219,189,234, 66,128,176, 6,230, 31, 28, 25, 17, 28,223,163,101,208, 4, 66,136,136,231, -121, 51,103, 57,104,214,108, 52,136, 41,174,105,215,198,210, 15, 26,249,181,110,179,237,212,205,159, 87, 70,113, 71,103,102,214, -190, 91, 28, 32, 70,167,142,237, 65, 81,153,200, 81,149, 1,184, 12,117,225, 53,136,164, 18,236,216,253, 37,244,165, 44, 38,188, -241, 15,112, 28,240,226,168,254, 96,133, 62, 14, 63, 46, 39,231, 50, 56, 14, 24,217,157, 88,249, 74, 75, 24, 77, 52, 98, 70, 12, -135, 52,128,194,134,141,251, 64, 81, 64,250,207,235, 81,120,227,207,232,189,155, 86,100,214, 36,253, 0, 0,199, 3, 28,199,129, -227, 56,176, 44, 11,147,136,135,153,152, 65,211, 52,244, 94, 70,128,147,130,226, 89,176, 98, 30, 21,180, 17, 58,141,186,206,188, -133,248,152, 32, 20,202, 16, 28, 28,140, 54,109,218, 32,172,113, 95, 64, 64,129,101, 79,131,226, 85, 48,234, 24,176,156, 14, 69, -119,148, 8, 9, 46, 69,112,192, 0, 44, 91,177, 43,234,231, 31,239,167, 37, 51, 50,224, 77,165,128, 81, 2,154, 50, 67, 39, 22, -162, 66, 38,130, 80, 36, 6, 56,111, 16, 1, 65,133, 78,143,242,162, 91,200, 61,125, 12,202,252,124,112, 28, 7,138, 23,184,213, -104,190, 91,251,151,224,252,230, 59,111, 58, 30, 39,171,174,217,110, 76, 75, 75,155,251,254,251,239, 79,205,207,207,167, 8, 33, - 33,169,169,169, 63,195,178,185,147,151,187, 13,121, 74,108,172,104,205,154, 53, 27,239,221,187,135,244,244,116, 68,182,111, 47, -104,136, 14, 34,151,203, 73, 92, 92, 92, 20,207,243,138,213,171, 87,187,188, 97, 17, 77,211, 41, 3,173,109, 74, 44, 22,163, 93, -187,118,216,122,232, 80, 70, 72, 72, 8, 74, 74, 74,156,166, 99,211,236, 31, 0, 72,239,222,189,249,211,167, 45, 22, 43,187,243, -159, 67,134, 12, 41,156, 59, 55,214, 63, 41,201,241,154,251,177, 31,206,245,246, 54, 51, 91,187,118,238,236, 39,160, 40,188,251, -218, 4, 24,140, 38, 36,127,251, 45,188,100, 50, 24,141, 70, 24, 13, 6,116,239,217,163,237,111, 63,253, 52, 13,192, 23,142,172, -142, 11,103, 77,231, 0, 80,215,242,242,168,234, 12,191,122,247,116,231,195,155,119, 24, 28,125,251,202, 17,126,216,139,111, 69, -103,236,252,214, 45, 65,192,126,215, 62,219,150,182,117,221,119,132, 78, 1, 66,220,170, 96,113,120, 88, 8, 68, 51, 83,161,153, - 16, 1, 97, 96,168, 75,204, 63, 46, 46,174,200,172,211,223,153,252,238,212,230, 31,254, 99, 14, 86,175, 75,185,212,167, 87,175, - 86, 41,171, 82,188,222,155, 51, 27, 63,245,239,139,141, 27, 55, 78,132,101,215,210,250, 48,254,168,109,219,182, 41,108,204, 62, - 53, 53, 53, 23,150,109,218, 15, 58, 35, 0,236,223,191, 95, 17, 18, 18,130,158, 61,123, 50, 20, 69, 9, 45,214, 89, 14, 34,145, - 8, 65, 65, 65,104,220,184, 49,110,222,188,137,253,251,247, 43, 92,232,115,177, 47,188,240,194,103, 43, 86,172, 88,213,190,125, -251,181,132, 16, 14,192, 87, 0,158, 3,112,132, 16,178, 16,150, 53,243,103, 3, 88,232, 12,189, 21,137,137,155, 7,198,198,146, -157, 59,119, 66, 40, 20, 66,161, 80,224,252,249,243,104,211,166, 13, 22, 45, 90,132, 46, 93,186, 96,234,212,169,194,143, 63,254, -120,197,147,200,252,167,204, 93, 86,121,239,235,164, 15,107, 20, 2,106,154, 5, 64, 9, 5,148,144,225,120,173,193,204,220, 33, -132, 72,124, 36,130,110,126, 98, 68,202, 58, 15,105,141,232,183,129, 14,131,208,196,155, 31, 51,113, 64,196,135, 65,126, 94,195, - 86, 70,193,191,246,236,112, 16, 8,108, 99,182, 31,128,102,240, 15,127, 1, 6,214,136,181,169,235,240,195,198,116, 12,143, 30, - 0, 0,208,235, 1,129,176,118, 82, 50,175,246, 0, 0,150,181,223,155,166, 8, 64, 22, 40,129, 4,241,175,191,133,152,184, 56, -236,218,109, 97,100, 94,222,128,174,226,110,157,133,101,134,160,146,249,155, 25, 22, 38,141, 25,122,149, 30, 42, 51, 13,165,158, - 70,185, 73, 11,149,182, 2,229,197, 90, 40, 85, 70, 40, 43,106, 95, 66,253,221, 87, 91,241,132, 16, 8, 4, 4,132,146,128,101, -121, 48,250,124,232, 84,215, 80, 88,164,134,178,188, 2,106, 45, 11,101,185, 17, 5, 5, 69,184,116,229, 28, 84,234,115,232,219, -171,183,162, 54,154, 2, 0,148,214, 8,195,245, 59, 40,251,227, 50,202,242,111, 65,163, 86, 66,163, 86,226,214,165,211, 56,158, -246, 29,178,182,108, 64,201,245,235, 96,105,206,210,155, 4, 15,205, 13,104,219,135,155,142,137,137,233,184,120,241,226,247,155, - 52,105,162, 75, 79, 79,239,150,150,150,246, 43,128,158,214, 74,119,123,193, 41,113, 88,216, 44, 0,232,215,165, 11,166, 77,155, - 86,124,234,202,149, 3, 79,117,232, 16,213, 16,153,223,178,101, 75, 38, 0,146,152,104,209, 50, 19, 19, 19, 93,162,107,150, 72, - 0, 0, 91,183,110, 69,104,104, 40, 62, 76, 76,196,172, 89,179, 16, 18, 18,242, 88,248, 97,109, 76, 63, 53, 53,181,242, 0,128, -195,135, 15,135, 3, 24,229, 36,153,167, 2, 2, 3, 59, 8, 40, 10,111,196,196, 64,165,214,160,224,238, 29,136, 68, 66, 8,133, -150, 67, 36, 18, 65, 34,243, 66,107,185,252,243,158, 67,135, 58,165,177, 95,203,203,195,143, 91,127,173, 60,108,152,159,188, 10, -243,147, 87, 97,143,226,176,203,223, 59, 52,246,227, 40, 0,184,125,229, 72,230, 80, 11,243, 87,224, 49, 89,237,232,194,247, 95, -160,248,237, 94, 24,146, 81,130, 78, 1, 66, 8,252,130,192,148, 23, 35,114,111, 49,188,133, 22, 30, 40,112, 48, 39,235,230,245, -235,101, 95,167,254,167,253,247,255,249, 30, 95,126,251,213,173,175, 86,124, 54,255,253,233, 51, 70, 45, 94,178, 24, 50, 95,111, - 12,234, 55, 0,167, 78,158,250,254,181,248,215,220,254,102, 27,243,183, 93,239,220,185, 19, 79, 61,245, 84,107, 0, 19,156, 53, -251,155,205,102,244,234,213,139, 99, 89, 86,168, 86,171, 97, 50,153, 96, 50,153,112,229,202, 21, 40, 20, 10, 28, 59,118, 12, 77, -154, 52,129,217,108,198,164, 73,147,156,201,235,184,184,184,184, 47,198,142, 29,235,183,118,237, 90, 63, 66,136, 24,192, 97, 0, -106, 0,189, 0,252,106, 39,120, 30, 4,208,197, 17,189,109,239,191,191,121, 84,247,238,228,167,152, 24, 20,158, 61,139,207, 62, -251,140,219,181,107,215,255,187,125,251,118,168, 66,161,120,123,238,220,185, 48,155,205, 24, 48, 96, 0,188,189,189,251,227, 9, -135,189, 48, 80,167, 5, 96,102, 38, 74, 86,162, 36,229,247,235, 37, 25,145, 17,193,209,189,229, 65,150,117,196, 95, 88,132,223, -125,134,227,224, 31,197,232,223, 57, 16,207,200,119,193,247,183, 37, 61, 71,244,144, 79,216,120,228,210, 31, 53, 17,111,210, 54, -150,240,124, 1, 63,250,245,153,152, 53,253, 43, 0, 74, 0,190, 0, 76,104,217,190, 23,164, 18, 33, 12, 58, 19, 64, 91, 4, 4, - 95, 95, 95, 20, 43,107,221, 47, 27, 6,253, 85, 2,128,191,244,251,183,160,168,213, 85,148, 4,206,240, 39,140, 38, 51,100, 62, - 82, 64,108, 17, 16,180, 26, 13,250,247,239,143, 35,191,254, 84,187, 58,194,209,224, 56, 33, 24,134,129,201,100, 66,133, 80, 0, - 33, 77, 1,119, 53, 96,188, 24,176, 98, 14,188, 72, 0,189, 64, 8, 70,167,135,202, 84,123,172,147,175,143, 14, 12, 67, 96,162, - 89,168,212, 26,228, 92,207, 71,193,221, 82, 24,104, 51, 52, 21, 74, 84,104, 85, 48,178, 52,136,144, 64,167, 87, 67,163,191,137, - 91,133,106,148,105,117,181,210,100,237,164, 52, 70,173, 67,193,185,203,184,119,249, 38, 52,218,235,208,170, 84,224, 33,132, 72, - 64,192, 19, 17, 40,202, 98,245,117,197,185,246, 65,252, 7, 78,185, 3, 28,224, 30,128,123,243,230,205, 51, 0,192,220,185,115, - 79, 37, 37, 37,121, 91,179,110, 4,144,239, 46,225, 53,107,214, 44,141,137,137, 1, 0, 68,132,132,132, 90,125,226,130,134,236, - 28, 54,243,191,213, 18,224,176,248,194,195,195,135,210, 52,141,228,228,100,188,252,242,203, 24, 59,124,248, 95, 3,253,133, 11, - 22, 75, 80, 72, 8,239,108, 92,192,172,249,243, 43,125,254, 0, 48,123,193,130, 42,150, 1, 39,205,254, 85, 96,211,254,109, 76, -223,134,212,212, 84, 36, 36, 36,224,192,129, 27, 63, 2,248,201, 17,157, 0,161,240,223, 70,218, 4,129, 64,128, 43, 55,114,193, -243, 60, 46,229, 92, 3, 77,155, 65,129, 64, 40, 20,130, 16, 2,142,101, 97,208,233,113,237,247,223, 15, 57, 81,134,148, 61,211, -127,237,229, 81,246, 26, 63, 5, 0, 39,206, 92, 64,219,136,150, 46, 77, 83, 62,144,246,239, 74,109,255,128, 69,243,183,185, 66, -248,231,199,188, 21,189,119,155,123,214,128, 6,129,242, 46,196, 45,218,161,120,154, 20,146,103,198,129,205,222, 7, 86, 99,137, - 55, 40,158,246, 52, 90,166,102,129,229,234,110, 42,237,219,182,111,234,229,229,237,245,229, 55,107,140,209, 67,134,136,251,246, -239,247,211,254, 61,191, 61,127,229,122, 14,192,241,144, 74, 36, 24,208,123, 0,118,239,220,141, 17, 35, 70,240,251,246,237,115, -122, 40,168,174,245,239,223,191, 31, 55,110,220,160, 1,136, 79,158, 60, 73, 79,157, 58,117,124,106,106,234,107,142,232,228,229, -229,161,117,235,214, 0, 64,229,229,229,225,252,249,243,104,217,178, 37, 34, 34, 34, 80, 94, 94,142,236,236,108,180,106,213, 10, -161,161,161,104,217,178, 37,242,242,242,234,110, 40, 20, 21, 31, 23, 23,183,100,240,224,193, 62,167, 78,157,242, 99, 24,102,178, - 76, 38, 27,109, 48, 24, 86,192,178,245, 57,172, 2,192, 42, 88,182, 86,167, 81,199,244,118,145, 72, 20,159, 54, 99,198,250,167, - 67, 66, 72,201,156, 57,232,207,113, 88,181,115, 39, 95,168,215,191,133,191,182,101, 95,127,233,210,165,181, 12,195, 8,125,124, -124, 16, 30, 30,238, 99, 54,155, 33, 18,137,240,119, 67, 77, 46,128, 48, 0,173,199, 68,182,120,183,121,176,247, 4,152, 13, 64, -251, 97, 56, 19, 50, 6,207, 36,126, 7, 67,169, 10, 2, 63, 95, 40, 86,198, 99, 80,167,223, 17,116, 33, 99, 48,128, 22,181,253, - 64, 27,191,102,248,227,194, 47,118, 6, 7, 29, 44, 91, 40,155, 1,179, 9, 66, 78, 0,202,202,196,183,109,119,188,139,200,190, -139, 60, 70,244,236, 82, 77, 9, 21, 2, 16, 1, 34, 41, 24,194,194,170, 7,227,149, 9, 51, 0, 64,145,244, 81, 98,173, 29,129, -229,120, 48, 28, 5,138, 97, 64,209, 38,232, 41, 75,219, 49, 8, 4,240,102, 12,208, 24,120, 16, 17, 1,203,178,208,179, 64,177, -174,246,141,159, 24,154,131, 81, 36, 0,167,103,192,112,106,104, 43,204, 16, 16, 17, 76,140, 25, 52, 79,131, 49,211,128,152, 3, - 69, 0, 34,225,160, 54,176, 40, 42,209, 67,103, 98,106, 84,146, 41,194, 86,238,195, 75,200, 95, 46, 93,179,209, 0,181, 82, 9, -138, 8, 32, 20,242, 0, 47,132,128,184,175,234, 92,189,117,149,110,223,178,189,216, 25,179,127,109,178, 25,236,118,196, 74, 74, - 74, 26, 5,224,246,220,185,115,123,250,251,251, 7,168,213,234, 91, 73, 73, 73, 46, 19, 77, 76, 76,124,115,205,154, 53,104,220, -184,177,253, 61,213,170, 85,171, 14, 60,213,161,195,208, 83, 87,174, 28,108,168,142,144,152,152, 24,109,231, 10,168,139,249, 71, -245,233,211, 39,124, 96,143, 30, 32,190,190, 72, 74, 74,194,156, 57,115, 32, 18,137, 96, 46, 47,135,191,191, 63, 62, 76, 76,172, -140, 11, 72,136,139,115, 40, 4, 84,247,241, 59,138, 9,168,203,163, 80, 93,251,119, 96, 29,112,216,100,202,149,202, 14, 62,190, -190, 40, 45, 47,135,226,196, 9, 8, 41, 1, 76,102, 51,244, 6, 3, 56,142,171, 20, 92, 24, 51, 13,218,100,114,198,165,193, 1, -160,172,110, 0,206,174,225, 27,173,247, 49, 63,121,149, 24, 0,218,202,229,197, 55,107,214, 45, 92,178, 82, 53,107, 29, 25,181, -119,219,183,174,152,155,107, 47, 96, 23,204,254, 85,204,178, 91,254,131, 30,175,255, 3,146,136,110,150,177,162,244, 46,114,148, - 22,193, 95,210,255, 5,228,179, 12,188, 86,215,237,106,214,104, 52, 1, 18,153, 20,109, 34, 34,164, 55, 11,110, 55, 41, 43, 41, -195, 43,175, 77, 80,236, 57,152,129,149,203,146,211,183,237,217, 25,211, 54,162, 45,226, 95,158,136,172, 51,199, 48, 98,248,112, -126,223,254,253, 14,191,217, 94,235,223,191,127, 63,134, 13, 27,102, 19, 22,197,119,238,220,193,212,169, 83,197, 0,224, 76,108, - 65, 89, 89, 25, 6, 13, 26, 4,150,101,145,151,151,135, 99,199,142,161, 83,167, 78,240,247,247, 71,243,230,205,209,163, 71, 15, - 80, 20, 5,138,162,208,164, 73, 19, 71,237,180, 83,151, 46, 93,190,232,223,191,191,224,194,133, 11,126, 44,203, 22,109,221,186, - 85, 99, 48, 24,146, 0,216, 59, 77,223,125,254,249,231,243,247,236,217, 19, 65, 8,185,139,218, 55,230,233,153, 48,112,224,250, -190, 66, 33, 41, 89,178, 4,188,217, 12,133, 64,192,101,233,245,147, 96,217,198,221,134,119,230,205,155, 39,164, 40, 10, 74,165, - 18, 55,110,220, 40,238,210,165, 75, 40,254,134, 16, 86, 99,254,109,195,252,101, 3,159,239, 30, 62,213, 79, 38,234,195,176, 92, -185,144,103,253, 16,208, 68,112, 87,101,132,161, 84, 13,136,133, 96, 85, 90, 20,148,211, 64,112, 11, 80, 28, 45,173,203,196,123, - 93,163, 65,187, 0, 63, 48, 38,224,122,230,143,104, 19,245, 92,165, 2,103,166,205, 16,129, 66,133,209,178, 67,237,136,168, 94, -144, 5,135, 99,197,250, 95,107,205,240,136,174, 4,123,206,243, 16, 73, 1,113,139,231, 64,231, 31,173,180, 2,136,196, 18,152, - 97,132,143,204,178, 35,233,206, 61,155,240,199,201,204, 58, 77,146, 28,199, 65, 76, 27, 96,134, 24, 20,197, 0, 70,203,192,102, - 54,155, 97, 50,138, 32, 16,138, 0, 35,192,115, 22, 23, 65, 75,121, 4,144, 85,243,140, 2,189,145,131, 64, 64, 96,102,204, 48, -154, 56,104,180,150,118,104,230,120,208, 38, 14, 16, 2, 2,145, 0, 66, 41, 64, 12, 44, 56,194,128,131, 1, 90, 3, 0, 56, 30, - 88, 88, 0, 20, 7,240, 4,160, 40, 14,132, 8,192,241, 4, 20,101, 85,156, 56, 10, 28, 69,129,112,206, 41,200,118, 65,126,226, -122,182, 35,111, 0, 33,115,231,206, 45, 78, 74, 74,138, 6,240,210,220,185,115,135, 39, 37, 37,233, 0,148,185,101,178,138,141, - 21,175, 89,179,230,219,152,152, 24,200, 27, 53,170,188, 47,111,212, 40,192,106, 5, 8,121, 20, 29,134,166,105,133,205,247,207, -107,181,248,228,147, 79, 96, 42, 43,131, 45,242,173,141, 85, 88, 17,153, 76, 24, 53,106, 84,113, 97,113,241,120,103, 52,237, 6, -116,201, 84,177, 0,212, 97, 33,192,233,211,167, 73, 77,194, 67, 21,161,214, 68, 67, 69, 43, 97, 52, 26, 17,224,239, 15,169, 88, - 2, 51,203,128,231,121,176, 44, 11,154,166, 97, 54,155,193, 49,172,179,241, 12,220,181,188, 60,170,173, 92,110,211, 8,184,107, -121,121,212,143, 91,127,149,218, 91, 4,218,202,229,170,134, 50,223, 23,228,102, 55,152,230,239,110, 12,192,144,140, 18, 20,203, -211, 33,110,209, 14, 36,162, 27, 90,174, 59,139, 82, 35, 7,111, 33, 1,253,223,237,184,122,227, 38, 28,237, 90,108, 96,104,156, -206, 58,137, 47, 86,124,142,167,163, 6, 98,222,255, 91,128,223,246,254,134,159, 54,252,128,254,131, 7,198, 52,151,183,128,208, - 75,132,131, 71, 15, 98,227,247, 63,224,151,237, 91, 33,150, 74,249,157, 59,119,214,185, 62,196,182,109,219,170, 48,126, 27, 84, - 42,149,203,229,163,213,106,225,239,239,127, 2, 64, 95,185, 92,142,222,189,123, 67, 32,176,184, 89, 91,182,108, 9,137, 68, 2, -181, 90, 13,185, 92, 14, 95, 95,223, 91, 90,173,182,101, 29,228, 46, 93,184,112, 97,233, 47,191,252, 50,178,109,219,182, 29,182, -110,221, 90, 81, 94, 94,190, 16,192, 70,123,249,101,200,144, 33,239,175, 91,183,110, 11,128, 98, 0,177, 0,126, 7,208,189, 6, -122,103, 87, 43, 20, 75, 3,178,179, 63,122,149, 97,240, 57,192,125, 91, 81, 49,177, 26,189,151,102,204,152,241,249,148, 41, 83, -112,243,230, 77,236,222,189, 27, 12,195, 28, 2,240,234,147,194,212,123,244,232,129,115,231,206, 85,250,253,235,180,176, 84,187, -110, 53, 38,178,197, 98, 63,153,168, 79,137,198,248,219,241,107, 37, 73, 16, 72,128,171, 71,241,172,156,199, 63,167,143, 66,239, -206,114,204, 72,120, 30, 47,182,166,129,139,251,193,139,100, 12,234, 12,214, 81, 33, 71,149, 15,161, 4, 24,241,226, 63,176,241, -203,101, 22,101, 81,111, 2,107, 0,182, 43,206,225,192, 41,203,140,194,102, 45, 34, 64, 9, 29, 51,175,145,221, 9,204, 70, 96, -231,238,125,136, 28, 62,221,162,253, 67, 4,129, 12,136,123, 33, 22, 35, 7,143,182,116,252, 91,185, 96,140,117,111,213,204,243, - 60, 24, 98, 97,240, 38,218, 18,252,103, 50, 26,160,215,235, 81, 81, 81, 1,173, 70, 13,173, 86, 11,141,202,162,101,189, 0, 0, - 32, 0, 73, 68, 65, 84,182, 2,198,138, 10, 24, 12,134,218, 27,127, 5,129,193,200,194, 96,100,161,211,155,161,173, 48,161, 92, -107,130, 74, 67, 67,173, 53, 67,165,178,156,149,101, 12,148,229, 12,148,106, 6,165, 74, 26,247, 74,107,207, 35,197,243, 96, 1, - 16,150,128, 80, 28,120,194, 3, 60, 15,158, 23,128,229,254,170, 62,206, 58,122,184,106, 27,239,216,191, 35,142,237, 57,134,223, - 14,253, 86, 41, 20, 92,189,117,213,213, 54, 23, 14,160,245,242,229,203,207, 3, 88,253,225,135, 31,190,215,170, 85, 43, 38, 53, - 53,149, 36, 39, 39,187,172,117, 77,137,141, 37,226,176,176,109, 0, 16, 22, 22,118,223,243,105,211,166, 49,217, 87,175,110,106, -168, 88, 0,155,249,223,217,125,227,109,190,127, 0,216,188,121, 51,174, 23, 21, 1, 0,118,101,102, 86,121,118,245,234,213,208, -144,144,144,242, 71, 49, 8, 12, 29,218,202, 54,239,186,202,125,219,181,237,185, 35,120,249,249, 94,225, 88, 22, 26,101, 57, 74, - 75, 75, 81,166, 42,135, 78,175,135, 78,175,135,182,162, 2, 58,181, 6, 90,149, 10, 70,131, 30,180,209, 8,142, 97, 29,142, 57, -109,229,114,219,152,193, 1,160,237,221, 1, 0,240,227,214, 95, 49, 63,121, 85, 0,128, 48,151, 27, 98,235,200,168,234,130, 67, - 68,167, 33, 81,143,122, 80,190,251,138, 28, 45,215,157, 5,137,232, 6,211,225,116,220,122,163, 39,188,133, 4, 71,135,133,128, - 81,151, 32,114, 95, 49,132, 14,154, 95, 70, 70, 6,121,123,230, 59,184,126,245, 42,178, 50,143,194,223,215, 31,227, 94, 25,135, -128,224, 32,156, 57,153, 13, 31,177, 20,222,222,222,104, 34,111,138, 77, 63,111,194,135, 31,127,132, 10, 55,152,184, 13,189,122, -245,114,249, 29, 95, 95, 95,168,213,234,190, 20, 69,209,205,155, 55, 71,159, 62,125,208,185,115,103, 52,106,212, 8, 82,169, 20, -114,185, 28,221,187,119, 71, 64, 64, 0,180, 90,109, 75, 95, 95, 95, 71, 36, 63, 61,124,248,112,198,134, 13, 27, 68,229,229,229, -243,170, 49,235,216, 65,131, 6,125,177,110,221,186,239,194,194,194,150, 16, 66,124, 0,124, 8,160, 46, 51,217,199,139,181,218, - 79,223, 98, 24,246, 91,131, 97,124, 53,122, 49,175, 38,252,235,151,233,239,205, 18, 92,189,122, 21, 39, 78,156,192,186,117,235, - 42, 0,252,243, 73,211,236,171, 7,189,215, 22, 4, 95,125, 16,144, 8, 40,226,155, 95,166,251,105, 83,214,205,127,158,187,165, - 60,105, 96,201,117,148,222,132,244,151,119,177,100,128, 22,217, 11,251, 96,101,116, 5,188,183, 79, 3,148, 5,168,224,165, 23, -173,146, 87, 45,248, 43,170,255,252,133, 95,241,175,127,109, 64, 27,191,174,248,243,248,121,236, 87, 92, 70,116,255,206, 24, 54, -200,210,208,120,129, 16, 52,235,252, 71,142,232,217, 1,139, 63, 93,134,125, 23, 53,240,145,119,194, 11, 47,140,194,111,135,182, - 97,247,111,155, 44, 31,199,154, 33, 17,213, 61,206,241, 28, 11,150,179,104, 51,176,106, 51, 52, 77,195,104, 52,194, 96, 48, 64, -167, 55,192,160,215,193,160,215, 65,111, 50,130, 54,213,190,237,115,153,193, 23,234, 10, 22, 26, 3, 7,141,129,179,252,175,229, - 80,161, 99, 80,161,103, 80,174,100, 81,166, 52,163,172,220,140,178, 50, 51, 74, 75,105,220, 43, 53,215, 41, 0,252,101,254,191, - 95, 85, 19, 10,120, 8, 8, 1, 95, 45,234,159, 39,142, 21,167, 15,226, 63, 64,199,254, 29, 43,175, 15,172, 63, 80,105, 17, 56, -182,231, 24,174,222,186,122,211,149, 6,151,158,158,254, 95,158,231,187,196,196,196,196, 71, 68, 68,132, 0,160, 56,142,147,152, -205,230,192,153, 51,103,250,213, 98, 10,174, 17,226,176,176,249,107,214,172, 25, 25, 19, 19,131,136,144, 16,167, 92, 87,245, 52, -255, 71, 1, 64,100,135, 14, 14, 3,216,218, 54,110, 28,157,156,156,140, 63,111,221,210,252,178,127, 63,174, 92,185, 82,169,245, -183,111,223, 30,214,103,244, 47,251,247,227,214,173, 91,184,154,157,109,112, 68,115,214,252,249,152,189, 96, 65,165,121,223,246, -191,237,218,246,191, 43,177, 0, 73, 73,105,252,144, 33, 67,222,181,103,250,182,115,239,222,189,145,148,148,230,148,118,125,237, - 74,110, 54,195, 48,160,105, 19,148,247,138, 81,114,183, 8,165, 69,247, 80, 90,116, 15,202,226, 18,168,202,202, 96,210,233, 44, -241, 51, 42, 21,156, 8, 2,100,230, 39,175, 18,206, 79, 94, 37, 4,160, 1,192,245,237,213,237,190, 68,118,113, 1, 78,163,105, -235,200,168,194,220,108, 69,247, 62,127,229,161,117,207, 23,163, 84, 37, 55, 20,245,105, 31, 36,174,188,138,230,239, 14,114,148, - 58,228, 79,126, 10,252,205, 11, 8,253,207, 25,120,175, 61,141,187,175,200,209,123, 95, 49,136, 72, 2, 33, 1,132,148, 99, 1, -244,194,197,139,228,147,101,139, 49, 99,246,251, 48,115, 44,174,228, 93,195,132,113,227, 33,150, 74,177, 99,251, 78,192,204,194, -100, 52,225,104,246,113, 24, 12, 21,152, 50,105,210,225,183,223,126,187,174,186, 38, 99,198,140,137, 30, 62,124, 56, 8, 33,200, -200,200,184,207,164,255,193, 7, 31, 56,253,157,193,193,193,184,115,231, 14, 0, 8, 83, 82, 82, 80, 82, 82,130,174, 93,187, 34, - 32, 32, 0, 20, 69,225,228,201,147,160, 40, 10,132, 16,220,185,115, 7,193,193,193,206,144, 93, 66,211,244, 96, 0,155,237,238, -141, 27, 52,104, 80,242,228,201,147, 3, 83, 82, 82,164,132, 16, 10,192, 54, 88,102, 1,220,115, 64,111,206, 9,179, 57,178, 58, -189, 87,231,254,178,229,229,241,211,200,200,119, 82,144,121,226, 18,146,147,147, 57,141, 70,243, 38, 44,179, 11,158, 56,244,232, -209,163,242,112,202, 5, 0, 32,119,211,241,155,137, 74,157,233, 52,128, 28, 0, 77,178,174,149,124, 61,184, 67,216,199,194,155, - 39,130,176,110, 34, 32,241, 6, 76, 58,128,231, 97, 22, 72,239, 29,253,243,238,183,168, 99,245,165,141, 63,125, 21, 61,126, 66, -188, 2, 0,116,156, 25,215, 85,249, 0, 88,180,241,139, 64,116,116, 55,132, 53,106,140, 50,181,198, 98, 43,160, 25,220, 85,233, -234,252,168,102, 45,250,163, 32,223, 58,205,147, 8, 49,162,187, 37, 6, 96,223, 69, 51,126,219,149,142,123,165,119, 16, 28, 96, -153, 73, 16, 32, 22,161, 91,100, 15, 40,182,215, 97,210,133, 16, 98,142, 1, 11, 1, 56, 66, 64,177, 28, 96,102,192,138,132, 0, -161, 96,235,147, 28, 15,203, 90, 1,117, 96,175,226, 38,121,126,160, 47,239, 37,230, 33, 20,217, 89, 24,204, 0,195, 3, 70, 26, - 96, 77, 44, 8, 33, 32, 98, 2,134, 5,116, 38,224,100,150,154,244,232,209,156,175,209,228,111,227,150, 20, 7, 98, 53,255, 91, -132, 2, 2,150,163, 64, 9,172, 51, 5, 0,240, 2, 30,224,157,179, 2,216, 51,255,154,174,143,237, 57, 22,225,108, 67,139,137, -137,233,156,158,158,254, 57,128, 30,233,233,233,251,210,211,211,143,198,196,196, 36,182,110,221,218, 76, 8, 9, 94,185,114,229, -254, 15, 63,252,112,194,178,101,203, 14,215, 33,124,218,180,127,225,236,217,179,231,207,158, 61, 27,251,246,237,131,238,222,253, -125, 57, 34, 36, 4, 55,111,222, 4, 0,133, 51, 11,249,212,182,232, 79, 98, 98, 98,212,154, 53,107, 20,171, 87,175, 70,100,251, -246,209,167, 46, 95,118,104, 42, 62,126,241, 98,230,128,255,207,222,151,199, 53,121,108,239, 63,147,141, 0, 42,130,187,104, 85, -172,168, 85,235,130, 21, 80, 43,137,162,181, 90,187,252,106,212,234,181,245,171, 45, 65,237,117,235,130,182,182,118,209,170,189, - 23,181,171,196, 46, 87,187, 88, 37, 88, 91,183,186,160, 9, 42, 34,136, 86,235, 10, 8, 42,130, 11, 74,194,150, 0,217,230,247, - 71,242,198, 16, 3,121, 19, 80,180,125,159,207, 39, 31,222, 45,135,201,204,188,243,156,115,230,204,153,190,125,159,186,112,236, - 88,103, 0, 62, 0, 62, 55,250,248, 64, 88, 93,141,110,237,218, 97,193,130, 5, 72, 77, 77, 93, 25, 26, 26,154,146,154,154,186, -191,160,160,192,141,114,119,119, 30,128,122,196, 0,212,208, 3, 83, 82, 82, 72, 92,156,236,216,209,163, 69,169,114,185, 92, 4, - 0,113,113,178,193, 43, 87, 42,211,192, 50, 9, 80,231,190,143,189, 83,121,253,198, 40,139,201,220, 67, 87, 90,138,210,219,183, - 64, 8, 15,148, 90, 80, 85, 85, 5, 74, 41, 40,165,184,116,238, 60,140,134,106,252,153,156,236,174, 14, 29,199,156,230, 0,120, - 99,164, 81,150, 49,210, 40, 56, 46, 11,180, 77, 17,176, 70,135,110,131, 36, 5, 57, 25, 42, 0,232,220,169, 19, 78,101, 88,245, -228,220, 63,183, 1, 0, 90, 61, 50, 64,122, 43,255, 68,163, 13,198, 3,255, 40, 66,230,211, 64,191,176,104, 20,205, 30,140,182, - 95, 31, 65,182, 70,135, 64, 17, 65,177, 70, 11, 1, 33,110, 61, 0,246,119, 51, 53,181,198,147, 93,187,118,165, 99,198, 62,141, - 29,219,118, 32, 49, 49, 17, 31,188,251, 30,246,170,247,131, 47,224, 35,184, 67,112, 84,105,105,221, 75,151,183,110,221,170,182, - 41, 2,146, 81,163, 70,213,136, 5,216,183,111, 31, 46, 94,188, 88,165, 80, 40,218, 57,123,147, 92,246,151,206,157,145,151,151, -135,199, 30,123,204, 52,111,222, 60,209,166, 77,155, 16, 16, 16,128, 11, 23, 46,220,229,121,205,203,203, 67,103,246,237,236,152, -120,110,234, 19, 79, 60,241,209, 75, 47,189, 20,144,153,153,217,180,170,170,234,255,124,125,125,159,177, 5, 6,254,206, 82,158, -227, 66,249,169,207,252,123,211,134,161, 35, 94, 32,159, 38, 3,164,253,179,248,100,205, 59, 84,147,115, 97, 58, 0, 37,254,198, -168,161, 0,204, 85,227,236,103,146,234,236,185,106,251,148,102,254,103,146,146, 63,202,171, 76,186,240, 71, 91,142, 9,242,227, - 63,193,175,174,242, 55, 81, 94,121,113,185,225,104,218,197, 27,123, 10, 53,250,148,185,106, 92,175, 77,201,152,242,175,197,234, -131, 71,210,164, 0, 84, 22, 62, 51,205,199,199,197,178,235,120,255,245,233,208,235,171, 81, 86,105,141, 1, 48,240,124,176,121, -107,221,105,118, 11,242,211,200, 11,207,254,219, 74,150,102,198,114, 54, 97,116, 31,130, 73,179, 86,193,207,207, 7,205,124,197, - 82, 0,170,156, 51, 39,164,235,191,216, 90,231,128, 36,160, 38, 24,136, 85, 9, 0, 33, 48, 83,106, 85, 4, 76,182,229,126,132, - 7,129,197, 2,147, 45, 56,208,157, 18, 80, 82,217, 28,149,213,197, 16, 9,120,246, 52,103, 38, 11, 96, 52, 82, 24, 77, 20, 21, -149, 22, 16, 62,129, 25, 4, 70,203, 29,215,189, 43,152, 45, 60,240,136, 25,196, 76, 64,121,212,238,254, 39,181, 24,207,140,164, -179, 23, 54, 17,119,185,161,207,167,157,175,111,223,177,187, 45,250,244,233,115, 61, 36, 36,228,133,203,151, 47,119, 75, 76, 76, -204, 0,240, 92, 82, 82,210,115,142, 15,175, 88,177, 66,189,112,225, 66,233,138, 21, 43,220, 17,132,189, 66, 98, 99, 99,107,125, -232,197, 87, 94,177,250, 0, 61, 75, 12, 68,157,220,254, 0,128, 65, 61,123, 74, 51, 88,144,191,125, 0, 62,117,202, 30,173, 58, -184, 79, 31, 75,124,124,252,151,227,198,141, 51,101,101,101, 9,174, 92,185,130,206, 45, 90,164,237,216,177,131, 85,128,226, 61, -202, 3,224, 72,238, 55, 83, 82, 82, 28, 99, 60, 78, 59,212,179, 91, 37, 64,185, 98,165, 78,182, 48,238,197, 11,251, 15,164, 53, -247,247,111, 86,166, 45,129,201,100, 2,181,189, 7,218,155, 69, 40,211,106, 65, 41, 69,255,232,104,233,159,201,110,243, 32,153, -112, 39,230,132,103, 91, 14,200, 11, 31,240, 56,198, 72,163,236,171, 0,114, 46, 95,102,173, 4, 68,143,125, 73,146,188,243, 23, -187,149,255,187,242, 59, 21, 0,180, 10, 25, 34,189,149,151,170, 6,128,198, 33,127,122,183, 18,128,111,208, 47,246,125,220,176, - 88,208,119,125, 6, 50, 70,183, 65,175, 29, 55, 33, 32, 64, 83,161,119,123,179,237,216,177,131, 76,124,105, 34, 29, 62,114, 4, -182,109,249, 13, 31,175, 92,129,184,210, 82, 80,139, 5,155, 55,111, 65, 97, 97,225, 51, 0,118,184,147,227, 74, 17, 0,128, 23, - 94,120,225, 36,128,114, 54,101, 89,191,126, 61, 25, 53,106, 20, 61,113,226,132,104,192,128, 1, 24, 49, 98, 4, 84, 42, 21, 30, -121,228, 17, 84, 87, 87, 35, 42, 42, 10,148, 82,203,137, 19, 39,120, 66,161,208,155,140,128,143, 5, 4, 4,172,158, 56,113,162, -240,220,185,115,205,170,171,171,107, 11, 12,100,139,254,193,253, 38,108,232, 55,108, 34,249, 46, 5, 40,171, 4, 12,151,118, 91, - 52, 57,170,105,168, 25, 24,248,208,128,201, 3,224,104,249,187,186,230,210,149,234, 64,254,204,249,249,207, 36, 21,249, 87,110, - 87,164, 1,104,103,123,121,171, 1, 20, 2,200,155,171,134, 91, 23,167,226,235,157,234,161, 67,251, 72,205,180,137,202,241,229, -168,208,149, 89,215,253,243,252,144, 91, 14,178,230,235,141,172,126,224,214,109, 95,144, 91,154, 60, 9,120,122,149, 35, 23, 54, -105, 18, 0,179, 81, 11, 80, 29, 70,247, 97, 55,161,107, 4, 31,160,212, 74,212,224, 67, 68,109,138,128,141,252,173, 57, 0, 1, -152,217,205, 77,164, 29,191, 74,194,122,183,163, 38,163, 6, 2,219,194, 94, 74, 41,204, 38,138, 42, 35, 80, 86,110,130, 17, 20, - 38,202,131, 64, 72,112,251,166,177,214,114, 30, 59,182,146, 0,192,224,200,183, 40, 49, 90,173,127, 10,128, 82, 2, 80,155,197, - 64,249, 32,124, 11, 44, 22, 1,178,115,182,176,250,205,175,126,252,170,244,114,238,229,186, 8, 88, 8,235, 82,141,186,216,201, - 94,243, 75,150, 44, 97,252,163,167,108, 86,241, 29,162,126,241, 69,201,150, 45, 91, 84, 54, 37, 64,229, 78, 9, 88,167, 84, 26, -255, 60,125, 90,214,185, 79, 31,243, 19, 61,122,232,108,125,180,218,230, 16,177, 67, 54,122,180,213,226,232,211,199,253,116,199, - 91,111, 73, 1, 96, 96,247,238,119,221,203,204,202, 82,103,156,247, 94, 25,234,211,179,231,215, 60, 30,207,124,225,216, 49,255, - 54,109,218,220, 78, 45, 40,216,224,206,234,191, 15,172,227,216, 15,116,182,128, 63,102,106,160,194,169,173,217, 40, 1,231,100, - 11,227,194,183,125,251,221,150,144, 46,157, 31,171,174,174,130,217,104,130,197, 98, 65,211,192, 64,148,106, 52, 12,249,179, 81, -162, 74, 62,124,227,223,173, 1, 24,114, 46, 95, 22, 49,243,255,233, 39,254,194, 24,105,148,101, 73,252, 23,238,146, 3,217, 49, -107, 78, 28,189,144,117, 65,234, 72,254, 0, 48,252,169,231,164, 7,246,252,174,190,149,151,234,125, 37,214, 18,224,231,250, 58, -123, 14, 27,248, 71, 17,240,199,235,246,243, 71,127,191, 97, 63, 46, 53,154,189, 46,239,230, 95, 54,147, 33, 67,134, 60, 61,106, -236,232, 93,175, 77,157,113,248,241,190,125,134,110,251,125, 59,210, 78, 30,199,241,227,199,119,214,229, 6,174, 67, 17,152,177, -117,235,214,111,183,110,221, 26,177,117,235, 86,214,133, 27, 53,106,212,240,189,123,247, 30,216,177, 99, 7, 66, 66, 66, 48,114, -228, 72, 4, 4, 4,100,151,150,150,134,158, 61,123, 22,121,121,121, 60,161, 80,136, 81,163, 70, 69,239,221,187,215,211,159,122, -174,180,180,116,229,246,237,219,235, 10, 12,244, 4,127, 22,158, 76, 92,254, 91,210,179,239, 84, 6, 79, 65,229,177,197,150,107, -135,150, 77,173,135,188, 7, 78, 17, 96,237, 1,168, 13,115,213,208, 1,248,203,246,241, 10,135, 15,159, 86,199,198, 46,148, 38, - 40, 62, 86, 5,119,234, 6,160, 26, 66, 31, 49, 10,174,151, 97,227,142, 84,226,185,188,157,234,105,175,206,199,250,239,127, 5, - 44, 87, 0, 8, 96,170,170, 68,112,187, 0,233,178,183,102,176,182,230, 96,182, 64,192,179,192, 72, 4, 16, 82,211, 29, 69, 0, - 38,128,154,193, 54, 48,204, 17,199,207, 92, 39, 0,208, 54,136, 71,133, 2,171,181,111,178, 88, 19, 24,149,148, 83,152, 77, 0, - 95, 96,129,217,196,110,228, 56,146,246, 31, 2, 0,225,131, 22, 80, 48, 57,225,121,128,133, 88,221,253, 89, 57,219, 61, 42,228, -183,239,125,171,110,128,254,197,202, 92, 97,200,223,193, 19,224,118, 57,214,177, 11, 23,146,142, 57,185, 12,235,120,214,237, 51, - 13,153, 58,248, 46,229,214,186,196, 47,193,106, 91,123,183,111, 72, 3,231, 1,112,174, 91,157,155,165, 86,172,250,142,114,197, -202, 11,178,133,113,189, 1,240, 47,164,164, 24,171,244,149,176,152,205,232, 25, 22, 38,109, 23,250, 24,142,253,177,157, 93, 29, - 83, 50,113,207, 31, 59,237,167,131, 31, 11,177, 31,239,249, 99,231, 93,231,117,133,198,127,253,185, 85, 65, 30,241,212,243,210, -115, 23,114,113,253,202,105, 21, 0, 28,216,243,187,170,205, 35,189,165, 55,243,207,120,220,238, 19, 38, 76,128,167,233,125,205, -196,167,206,251,249, 47,180,197, 31,215,170,238,249,128,159,154,154,250,135, 66,161,224,101,102,102, 90,246, 31, 77, 65,139,150, - 45,156, 87,122,120,132,173, 91,183,126,167, 80, 40,126,144,203,229, 70, 79,190,247,230,155,111,170, 0,144,105,211,166,209,220, -220, 92,100,100,100,160,188,188, 60,180,105,211,166,104,209,162,133,125, 47, 0, 47,200,159,193,127, 82, 82, 82,132,105,105,105, -125, 12, 6,195, 98,212,156,203,247, 6,239,158,217,252, 47, 97, 64,215, 31, 22,148,230,238,157,210, 0,242, 26, 21,204, 42, 0, - 87,215,189, 82, 0,220, 14,130, 10,133, 96,237,218,181,238, 93, 85,123,142,168, 59,116, 30, 65,110, 22,164,209,214,193, 29,161, - 41, 55, 97,227,182,195, 94,119,208,245,223,174,182,125,183, 13, 5,110, 34,176,169, 0,203, 22,189,230,209, 75,255,205,209,156, -123,182,129,205, 13,141,133, 0,128,216, 87, 72, 13,149, 70, 88, 0,248,249,249, 65,111,210, 19,179,201,115,121,233, 25,214, 61, - 3,194,159,152, 79, 45,148,143,203,151,118, 53,230,238,102,108,151, 14,114,187, 4,178,168, 31, 71,194,111,224,105, 1, 67, 92, -156,204, 7,128,121,229, 74,165,185, 62,130,148, 43, 86, 50, 27,249,216,219, 52,247,140,103,235,244,231, 44,255,194, 43,101,204, -121, 43, 96, 71,236,223,243,155,218,185,175,221,204,247, 46,127,128,187,141,125,156,117, 96, 19,241, 65, 37,175,238, 21,169,185, -229, 38,132, 54, 21,220,151, 87,197,182, 86,191,193,222, 57, 79,201,191,198,248,236,253,134, 63,108,240,137,193, 96,248, 13,112, -191, 41, 29, 75,188, 93,154,187,119, 35,106,198, 6, 60,212, 74, 0,171,193,199,219,125,132, 57,112,112, 68,183,110,221,144,147, -147,195, 85, 4, 7, 14, 28, 56, 60, 36,224,113, 85,192,161, 33,192,145, 63, 7, 14, 28, 56,112, 10, 0, 7, 14, 28, 56,112,224, -192,129, 83, 0, 56,112,224,192,129, 3, 7, 14,156, 2,192,129, 3, 7, 14, 28, 56,112,104,116,212, 8, 77, 61,121,242,164,215, - 81,155,174,130, 9, 57,121,156, 60, 78,222, 3, 35,175,206,232,112,174,254, 56,121,156,188,191,151, 60,143, 21, 0,135,129,194, - 83,184, 27,120, 26, 82, 30,135, 7, 19,148,107,183,135,178, 29, 88, 63,175, 80, 40,252, 1, 60,113,248,240,225,101,124, 62,127, -176,143,143, 15,244,122,253,145,161, 67,135,190, 11, 32, 67, 46,151,235, 31,132, 10,176,101,135, 84,253,147,199, 21, 74, 41, 61, -115,230, 12,250,244,233,195,189,147, 28, 60, 82, 0, 60, 90,135,204, 38, 81,142, 43,121,142,137, 79, 60,149,247, 15, 28,208, 89, -225,169,167,158,146,238,217,179, 71,205, 86,102,112,112,240, 93, 55, 10, 11, 11,157, 7, 83, 40,149, 74,194,178,140,247, 76, 9, -168, 45,159,127, 99,201, 91,181,106,213,136, 45, 91,182, 36,103,103,103, 3, 0, 66, 66, 66,158, 77, 79, 79,223,238,109,251, 58, -246,123, 74,169,253,253, 96,174, 51,239,138,237, 58,113,163, 60,179,109, 7, 79,200,255,177, 51,103,206,108, 41, 43, 43,235,209, -169, 83, 39,220,190,125, 27, 85, 85, 85, 0, 48,120,203,150, 45, 42,127,127,255, 11, 10,133,226,121,185, 92, 94,231, 86,146,103, -206,156,241,200, 32, 72, 77, 77,149,202,229,114,181, 39,223, 81, 42,149, 42,153, 76, 38,245, 38, 1, 20,245, 48, 9,195,132, 9, - 19, 60,121, 63, 0, 0,157, 58, 89,119,192, 45, 47, 47, 71,117,181, 53, 13,186, 78,167,243,228,125,171, 19,167, 79,159,166,131, - 7, 15, 70,207,158, 61,225,227,227, 83, 84, 93, 93,253, 8, 55,140,254,243,224,156, 12,232,158, 37, 2,226,172,216,123,139,223, - 19, 70,187,125,230,249,153,187, 61,146,169, 82,221, 49,144,178,179,179,225,239,239,111, 31,132, 24,176,217,252, 67, 38,147, 81, -165, 82,233,124, 78,106,121,198,171,186,141,138,186,179,157,171, 43,249,245, 1, 33,132, 14, 27, 54, 76,154,146,146,226, 17, 89, -108,217,178, 37,185,117,235,214,120,249,229,151,161,213,106, 45,241,241,241,219, 86,172, 88, 49,105,225,194,133,155, 61,252,255, -248,227,143, 63,236,231,163, 71,143,198,238,221,187,235, 60,103, 35,214,169, 47,211,176,176, 48, 0,160, 14,153,225, 60, 34,255, -210,210,210,180,174, 93,187, 54, 3, 0,177, 88, 12, 95, 95, 95, 20, 21, 21,161,164,164, 4, 1, 1, 1, 40, 42, 42,234,177,123, -247,238, 12,133, 66,209, 93, 46,151,223,168, 75, 94,239,222,189, 33,147,201, 16, 18,114, 39,235,223,202,149, 43,107, 60, 19, 23, - 23, 7, 0, 56,122,244,168,202,155,126, 83,159,236,143,107,214,172,169,237,150,125,175, 2,111,225,239,239,143,115,231,206, 65, - 40, 20,194, 96, 48, 96,247,238,221,200,201,201,193,162, 69,245,219,113, 54, 48, 48,144, 15, 32,250,224,193,131,187,163,162,162, -110, 62,255,252,243,109,146,147,147,193,231,243, 91, 53,111,222,156, 15, 14,255,104,242,103,174, 57, 43, 1,127,155, 32,192,240, -240,112,201,253,182,184, 27, 19,193, 3,151,218, 63,222, 66,171,213,218, 45,126,157, 78,135,117,235,214,217, 63, 30, 12,180, 46, -207,199,143, 31, 79,101, 50, 25, 5, 64,157,159,241, 20, 7, 15, 30, 84,189,245,214, 91,232,210,165, 75,131,213, 95,231,206,157, -201,219,111,191, 13, 74, 41, 82, 82, 82, 84,158,182,123,118,118, 54, 70,143, 30,109, 1, 0,145, 72,196, 11, 13, 13, 69,124,124, -252,166, 86,173, 90,209,240,240,240, 49, 30, 88,156,247,170,139,144,176,176, 48,202,252,174,227,199,143, 51,251, 1, 48,237,194, -218,237,175,213,106,183,136, 68,162,102, 0, 48,123,246,108, 76,153, 50, 5, 34,145, 8,190,190,190, 16,139,197, 32,132,128,207, -231,163,180,180,180, 25,128,120,133, 66, 81,167,236,184,184, 56,132,132,132, 32, 47, 47,207,254,137,139,139,171,241,169, 15,100, - 50,153,212,246, 59,189, 30, 19,230,207,159,111,255, 56,142,151, 78,215, 45,108,229,117,234,212, 9,254,254,254, 88,188,120, 49, -252,253,253,177,109,219, 54, 84, 86, 86, 54, 8,249,219,222,101,170,213,106,255,111,234,212,169,232,214,173, 91,155,221,187,119, -227,230,205,155,184,122,245, 42, 74, 74, 74, 12,247,115,108, 82, 40, 20,146,130,130, 2,170, 80, 40, 36,174,238,229,228,228,208, -139, 23, 47,114, 9,232,238, 3,249,199,196,173, 64, 76,220,138, 90, 21,131,251,162, 0, 16, 23,168,235,186, 55, 72, 79, 79, 87, - 53,132, 18, 48,101,202,148,135, 70, 9,168, 47,244,122,253, 93, 86,191, 55,205,203,144,201,248,241,227,237, 86,126, 82, 82, 18, -234, 75,252,142,214,191, 82,169, 36,195,134, 13,147, 42,149,202, 26, 30,129,250, 32, 49, 49,145, 0, 32, 81, 81, 81, 82,103, 79, - 3,203, 65,215,100,243, 6,160,117,235,214, 88,186,116,105,213, 27,111,188, 97,200,203,203,219,185, 98,197,138,145,141,221,190, - 14,123, 0, 16,199,118,242,176, 93,158,200,201,201,233, 1, 0, 51,102,204, 64,105,105, 41,174, 93,187, 6,161, 80, 8,129, 64, - 0,129, 64, 0,161, 80, 8, 95, 95, 95, 84, 86, 86, 34, 57, 57,121, 50,128, 64,119, 66,243,242,242,160, 84, 42,237, 31, 71, 79, -192,202,149, 43,145,156,156,236,245,239, 86, 42,149,106,219, 20,128,170,129,222,229,218, 18,119,179, 30, 63, 47, 95,190,140,157, - 59,119, 98,233,210,165,232,212,169, 19, 90,182,108,137,148,148, 20, 44, 90,180, 8,254,254,254, 0, 0, 62,191, 94,134,122,187, -233,211,167, 79,252,207,127,254,131,244,244,116, 92,187,118, 13, 38,147,233,229, 22, 45, 90, 4, 2, 48,222,239,190, 23, 28, 28, -140,152,152, 24, 85,110,110, 46,117, 36,255,152,152, 24,213,163,143, 62, 10,179,217, 12, 14,247, 22,142,196,239,120,220, 24, 30, - 0,234,226, 83,215,245, 70, 83, 2,198,140, 25,211, 16, 74, 0,245,224,195, 26, 47,190,190,167,193, 26, 36, 59, 59, 27, 58,157, -174, 86, 55,255,145, 35, 71, 26, 66, 49,168, 55, 14, 30, 60,168,178, 41, 22, 72, 73, 73, 81, 19, 66,208,186,117,107, 85, 67,118, - 78,198,253,111,243, 4,212,137, 85,171, 86,141, 25, 50,100, 8, 5,128,248,248,120,209,247,223,127,143,151, 95,126,153,113,205, -139,255,250,235, 47,145,237,222,222,240,240,240,231,216,252,255,209,163, 71,227,233,167,159,182,187,247,153, 99,230,156, 57,102, -233,254, 7, 0,216,172,127, 87,237, 64,156,238,215,137,221,187,119, 47,107,217,178, 37, 0,224,226,197,139,200,207,207,199,137, - 19, 39, 96, 48, 24, 64, 8,129, 64, 32, 0, 33, 4,102,179, 25,122,189, 30, 91,183,110, 5,128,190,158,120,142,100, 50,153, 75, -229, 37, 47, 47,175, 94, 74,128,195,111,175,151, 55, 0, 13, 48, 85,106, 52, 26, 49, 96,192, 0,168,213,106, 92,190,124, 25, 3, - 7, 14,180,223, 83,171,213, 8, 10, 10,178, 43, 2, 94,160,253,244,233,211, 11,190,251,238, 59, 68, 71, 91, 55, 50,106,223,190, - 61,204,102,243,143, 0, 74,238, 55,241,200,229,114, 53,163,124,134,132,132,224,216,177, 99,148, 33,127, 70,249,235,222,189, 59, -155,241, 97, 16,128, 31, 96,221,243,172, 46,140, 5, 16, 3,160, 21, 71,251,247,185, 99,179, 98,195,251, 24, 4,104, 83, 2,164, -233,233,233,106,111,101,116,238,220, 25, 83,166, 76,193,207, 63,255,236,109, 76, 0, 1, 64,127,254,249,103,151, 55,119,237,218, - 5,219, 61,143,101, 31,189,244, 24, 34,186,156, 67, 97,230,226,122,213,147,227,156,127,114,114, 50,162,163,163, 17, 19, 19, 99, - 39,255,142, 29, 59, 54,132,210, 87, 47, 69, 32, 42, 42, 74,114,240,224, 65,220,190,125, 91,202, 92,147, 72, 36, 82,165, 82,169, -138,138,138,146,120, 58,111,239,230,127, 73,217, 40, 0, 91,182,108,217,201,204,253,235,116, 58,172, 92,185, 18, 21, 21, 21, 16, - 10,133,240,241,241,193,165, 75,151,176,116,233, 82,104,181, 90,196,199,199,255,182, 98,197,138,225, 11, 23, 46, 84,185, 33,217, - 26,202,128,187,152, 0, 22,117, 14, 55, 59, 0,218,167, 3,220,253,222,160,160,160,193,213,213,213, 48,153, 76, 56,114,228, 8, -248,124, 62, 12, 6, 3, 42, 43, 43, 97,177, 88,236,239,177,209,104, 68,117,117, 53,243, 78,247,118, 39,183, 54, 55,127, 92, 92, -156, 61, 30, 32, 36, 36, 4, 69, 69, 69,245, 86, 68, 29, 86, 5,176,237,139, 26, 0, 65,174,110,172, 94,189,218,171, 66,196,199, -199,227,173,183,222, 66,255,254,253,237, 30, 16, 38,125,118,255,254,253,145,149,149,133,214,173, 91,123, 35,186,211,244,233,211, - 47,127,247,221,119,142,227,103,240,181,107,215,174, 53, 38,177, 12, 28, 56,144, 48,164, 63,112,224, 64, 12, 28, 56, 80, 5, 0, - 89, 89, 89,232,209,163, 7,219,118, 56, 9,192, 23,192, 38, 0,147,224,180, 37,184, 13,175, 3,248,194,118,252, 46,128, 30,128, -251, 45,234,255,206, 96,118, 3, 92,183,114,161,221,242, 95,183,114,161,253,222,125, 87, 0,238, 55, 30, 20, 37, 96,202,148, 41, -244,221,119,223,189,203, 21,232, 13,249, 55,164,245, 15,192,165,245,207, 88,253, 66,161, 16, 55,110,220,104, 84,242,119,180,254, - 29, 3,186, 84, 42,149,163, 23,224,190, 7,108,102,103,103,227,229,151, 95,214, 3,240,243,247,247,199,123,239,189, 7,161, 80, -104,191, 63,109,218, 52, 0, 64, 96, 96, 32,198,141, 27,135,195,135, 15, 31,184,143,229, 36,142, 30,128,186,148,128,176,176, 48, -231,173, 98, 93, 42, 3, 6,131, 1, 26,141, 6, 85, 85, 85, 8, 8, 8,128,143,143, 15, 76, 38, 19, 40,165, 48,155,205, 48, 24, - 12, 48, 26,141, 48,155,205,142, 10,253,237,186, 10,153,151,151, 87, 35, 0,144,153, 14,112,244, 8, 56,222,175, 47,188, 8, 8, - 20,215,118,195, 49, 38,192, 19,101, 96,233,210,165, 24, 59,118, 44, 58,119,238, 12, 63, 63, 63, 72, 36, 18,104, 52, 26,248,251, -251, 67,171,213, 98,253,250,245,224,241, 60,118,200,118,152, 62,125,250,229,121,243,230, 97,219,182,109,120,238,185,231, 0,160, - 45,128,155, 15,194, 56, 44,151,203,213, 1, 1, 1,210,137, 19, 39,170, 0, 96,243,230,205,210, 73,147, 38,121,210, 22, 6, 0, - 83, 0,252, 92,135, 18,224, 56,213,246, 8,128, 62, 0, 50, 56,219, 30, 53,136,191, 54,252, 45, 51, 1,214,151,252, 25,120,107, -165, 59, 14,200,203,150, 45,171, 55,249, 51, 24,208,191, 31,246, 31, 80, 97,227, 1, 63,187, 82,112,244,210, 99,245,250,141, 97, - 97, 97,200,203,203, 67, 82, 82, 18, 58,118,236,136, 13, 27, 54,120,108,117, 41, 20, 9, 18, 7, 15, 78,131,144, 63, 51, 31, 95, - 84, 84, 36,117,190, 55,108,216, 48,105, 82, 82, 82,131,197, 2, 0, 86,247, 63, 91,239,147, 86,171, 61, 15,235,188,176,101,243, -230,205, 88,191,126, 61, 0, 96,211,166, 77,208,106,181,204, 99,166,172,172, 44,180,106,213, 56, 94, 73,167,104,255,187,148, 51, -182,251,196,231,229,229, 29, 49,155,205,208,106,181,184,125,251, 54,180, 90, 45,244,122, 61,244,122, 61, 42, 42, 42, 80, 86, 86, -134,210,210, 82, 84, 86, 86,162,186,186,154,153,219, 77,171, 75,166, 51,185,187, 10, 36,117, 94, 21,192, 22, 54, 87, 63,117,113, -205, 19,248, 53,116,123,108,216,176, 1, 18,137, 4,126,126,126, 56,119,238, 28,212,106, 53,252,253,253,241,254,251,239,227,240, -225,195, 88,180,104,145,167, 10, 64,219,233,211,167, 95,157, 52,105, 18,126,253,245, 87,134,252,219, 63, 40,228,111, 29, 23, 20, - 18,134,252, 1, 96,226,196,137,170, 11, 23, 46,120, 58,181,202, 40, 1,176, 41, 1,206,211, 1, 23, 29,142,243, 1,156,230,104, -255, 14,156,131, 0, 27, 69, 1,184, 31, 65,128, 13, 77,254, 54,226,110, 8,203,141, 44, 91,182,172, 94,228,255,226,235,123, 48, -160,255, 29,215,205,150, 95,183,218, 61, 2,251, 15,168,188, 82, 2,228,114, 57,108, 75,195,160,215,235,177,111,223, 62, 44, 93, -106, 93, 81,112,250,244,105,152, 76, 38, 15,100,197,170, 1,107,224, 31,165,148, 9, 6,172, 23,249, 51,214,127, 93,110,254,134, -138, 5, 96, 20, 9,137, 68, 34,117,247,108, 72, 72,200,168,248,248,248,176,244,244,116,193, 15, 63,252,192,187,112,225, 2,166, - 77,155,102, 98,234, 49, 62, 62, 30,233,233,233,248,225,135, 31, 4, 87,174, 92, 65,120,120,184, 91,153,247, 34, 6,128,177,164, -157,148, 0,202, 40,125,108, 17, 26, 26,154,105, 50,153, 96, 48, 24,112,235,214, 45,220,184,113, 3, 55,111,222,196,205,155, 55, -113,235,214, 45,104, 52, 26,232,245,122, 84, 87, 87,163,180,180,148,249,159, 5,117,201,100, 2,253, 28,149,208, 58,202,238, 17, -249, 51, 57, 0,156,175,213,167,127,184, 88, 13, 96, 87,242,216,202,200,201,201, 65, 86, 86, 22,244,122, 61, 34, 35, 35,209,183, -111, 95,108,216,176, 1,239,188,243, 14, 68, 34, 17,248,124, 62, 4, 2,214, 14,217, 14,211,167, 79,191, 62,105,210, 36,100,100, -100,224,131, 15, 62, 96,172,223,235,120, 64,150, 49,103,102,102, 82,102,206,255,196,137, 19, 88,183,110,157, 20, 0,186,119,239, - 14,199,192,192,122, 42, 1,115, 97,157,255, 31, 15, 96, 22,128,112,252,195,221,255,192,157, 72,127, 87, 65,128,206,171, 0,238, -215, 20, 0,245,240,250,223,133,252,237, 74, 64, 61,166, 18,106,144,191,171,243,253, 7, 60, 31,223, 28, 7, 93, 63, 63, 63,244, -236,217,179,198,253,244,244,116,143,228,141, 31, 63, 30, 73, 73, 73, 96, 20, 1, 0,212,118,205,227,117,231, 27, 54,108, 80, 1, -192,238,221,187,165,174, 34,214, 83, 82, 82,212,151, 47, 95,118,105, 61,186, 66,109, 73,127, 24, 69, 35, 37, 37, 5, 81, 81, 81, - 82,149, 74,229,182,239,164,167,167,239, 91,190,124,249,136,212,212,212,253,161,161,161,200,206,206,134, 86,171, 21, 4, 6, 6, - 98,250,244,233,208,104, 52, 87, 82, 83, 83, 59,133,134,134, 34, 53, 53,149,196,198,198,186, 83,142,239,154,243,175, 71, 12, 64, -141,119,139,201,151, 96,203,157, 96,247,204, 56,204,255,187,109,143,136,136,136,119,212,106,245, 28,179,217,140,178,178, 50, 24, -141, 70,251,188,127, 85, 85, 21, 40,165,160,148, 34, 43, 43, 11, 6,131, 1,209,209,209, 47,201,229,114,147,171,164, 35,181, 33, - 58, 58, 26,209,209,209, 53,130,254, 60,157, 2,112, 36,122,155,203,159, 58,246, 15,219,170,128,134, 30,215, 88,143,159,204, 82, -191, 55,222,120, 3,106,181, 26, 82,169, 20, 57, 57, 57,104,210,164, 9,242,243,243,193,231,243,217,122, 0,200,244,233,211,175, - 78,157, 58, 21,135, 14, 29,194,251,239,191, 15, 0,193, 0,174,225, 78,254,135, 70,183,252,153,241, 37, 47, 47, 15, 97, 97, 97, - 76, 63,147,198,196,196,168, 66, 66, 66,144,149,149, 69, 89, 6, 2, 58, 42, 1,147,108, 10,192, 38, 0, 71, 0,200, 1, 72, 0, -220, 0,135,134,235,192, 13,157,141,207, 85,192,207,202,149, 43,107,189,222,152,228,111, 91, 1,112, 47,180,104,175,101, 94, 45, -112,223,191,125,125, 61,243, 90,186, 11, 18,243, 20,209,209,209,210,164,164, 36,245,132, 9, 19,104, 98, 98, 98, 13, 69,192, 73, -225, 99, 93, 15,177,177,177,110, 53, 27, 15, 19, 3, 81, 39, 69,194, 58, 42, 73,165,172,200,223, 97, 48,183,207,235,135,135,135, -255, 43, 62, 62,254,199,113,227,198, 33, 43, 43, 11, 87,174, 92,233,180,120,241, 98,105,108,108, 44, 43,121,247, 40, 15, 64,141, -122,174,133,248, 88,101, 12,148,203,229,186,132,132,132, 37,187,118,237,250,208,100, 50,161,164,164,196, 30, 3, 0, 0,183,110, -221, 66, 73, 73, 9, 40,165,140,213,238, 17,203, 50,243,255, 97, 97, 97,246, 8,118,230, 58, 91, 37,192,133,149,127,215, 52,212, - 61, 32,127,143,193, 40, 1, 11, 23, 46, 68, 74, 74, 10,198,141, 27,135,229,203,151,227,205, 55,223,132, 64, 32,128, 88, 44,118, - 59,134, 80, 74, 45, 51,102,204,192,143, 63,254,136,239,191,255, 30, 0, 58,218,200,191,193, 13,170,250,160,176,176, 16, 59,119, -238,172,145,197,209,118, 44, 29, 62,124,184,202,203, 37,143,102,155, 18,176,195,102,253, 71,112,228, 95, 59, 92, 5, 1,178, 82, - 0, 60, 73,196,225, 45, 97, 55, 52, 26,130,252,235, 75,212,247, 2,115,231,206,149, 94,184,112,161, 65,101,218, 92,164, 13,186, -148,142, 33, 60,219,218,122,198, 43, 64, 9, 33,176, 88, 44,216,178,101, 11,107, 37,224,173,183,222, 98,202,121, 87, 12, 0,143, -199,131,197, 98,193,219,111,191,173, 98, 75,158,117,201, 75, 73, 73, 81, 59,102, 69,244,162,223,253,180,124,249,242, 91,169,169, -169,187,217, 90,253,247,193,219, 70,156,189, 61,181, 40,124,172,148,128,216,216,216,143, 20, 10, 69,210,207, 63,255,124, 86, 36, - 18,129, 89, 21, 96,177, 88,208,188,121,115,104,181, 90,200,100, 50, 68, 71, 71,251,201,229,114,183, 11,188,153,241,197, 49,248, -239,248,241,227,136,142,142,174, 49,158,184, 27,135,226,226,226,104, 94, 94,158,212,217,197,239,109, 26, 96, 71,184, 8,240, 51, - 1, 48,173, 94,189, 90,108,179, 70,121, 14, 31,143,148, 0,199,196, 63,179,102,205,178, 31,151,149,149,185, 29,155, 8, 33,100, -250,244,233,244,135, 31,126,120, 30,192,239, 15, 34,241,216,136,158,120,122,143,141,210,238,132,235, 15,195, 24,126,191,193,172, - 2,112, 69,252,172, 86, 1, 52, 52,169,215, 38,239, 65, 81, 30, 30,228,142,243,217,103,159,169, 27, 90,166,211, 26,233,123, 6, - 39,247, 63,219,151,154,109, 46,116,226,193,239,189,167,191,117,209,162, 69,123,234, 83,159,163, 71,143,174,177, 44,246,233,167, -159,174,225, 25,240,112,238,159,120,232,237, 97, 85,110,185, 92,126, 78,161, 80, 52,217,187,119,239, 39,249,249,249,115, 42, 43, - 43, 97, 54,155,209,175, 95, 63, 12, 28, 56, 48, 62, 58, 58, 58,142, 13,249, 3,192,209,163, 71,237,199, 81, 81, 81, 53,174, 59, -159,187, 25, 87,136,163, 66,203, 40, 19,182, 56, 0,175,218,125,194,132, 9,181,221, 18, 56,140,151,162,123, 53,174,184,241, 84, - 88, 0,224,251,239,191,231, 54, 76,225,192, 90, 9,168,141,252,107, 83, 0, 26,186,115,113,157,149, 3,241, 80,179,255,199,213, -141, 35,225,223,131,105,129, 6,121, 7,229,114,185, 14, 86,215,235, 92,230,218,249,243,231,217, 16,151, 29,189,123,247,110,240, -241,192,149, 66,235,173,203,255, 94, 43,139, 28, 56,254,184,159, 74,128,219,202,245,118, 31, 97, 14, 28, 56,112,224,192,129,195, -195, 11, 30, 87, 5, 28, 56,112,224,192,129, 3,167, 0,112,224,192,129, 3, 7, 14, 28, 56, 5,128, 3, 7, 14, 28, 56, 60,132, - 48,193,131,237,138, 57,255,124,202,173, 0, 0, 32, 0, 73, 68, 65, 84,252, 51, 33,224,170,128, 3, 7, 14, 28,184,177,157,195, - 63,188,147,156, 60,121,210,235,136, 75, 87,193,132,110,228,213,185,254,216, 11,121, 13, 93, 62, 78, 30, 39,239, 31, 45,239,207, -119,174,120, 61,176,244,255,164, 19,238,181,188,227,139,188,151, 23,182,252,110,121, 76,253, 41, 20, 10,137,209,104,196,165, 75, -151, 84, 6,131, 1, 2,129, 0, 5, 5, 5,120, 41,160, 51,246,100,102,162,242,241,142,136,136,136,144,242,249,124,102, 93,123, -163,181,175, 66,161,120, 12, 64,235,179,103,207,238,108,223,190, 61, 79,163,209,136,219,183,111,191,212,215,215,119,173, 92, 46, -191, 6, 0, 9, 9, 9,188,132,132, 4,115,109,242, 18, 18, 18,154,218,188, 5,250,216,216, 88, 10, 0,139,255,253,228, 55,242, - 39,243,167,111,204, 12,189, 36,104, 61, 42,162, 73,211,102, 21, 0, 40,165, 84, 0, 32, 48, 33, 33,225, 42,247,190, 61,216,242, -238,181,150,200,118,211, 23, 79, 83,224,122,156, 50,119,101,228, 83, 18, 65, 80,128, 42, 55,251,162,244, 81,159, 38, 88,112,230, -160,250, 65,210,178,234,200, 71,206, 45,113,105,100,140, 29, 59, 86,178,107,215, 46, 85,252, 59,214,243,223, 14, 61,137,131, 7, - 15,178,106,151,127, 77,123, 69,194, 35, 68,149,117,225, 2,180, 90, 45, 58,117,234,132, 38, 77,155, 98,107,210, 22,214,237, 58, -126,252,248, 26, 47,110, 82, 82, 82,157,123, 41,216,178, 43,122,213,111,152,141,154, 40,165,245,235,119, 50, 77,205, 87, 85, 25, -228,189,172,176,213, 64,200, 43,214,227,188,245,192,241, 5,245,111,212,241,183,107,150, 47,169, 37,171,175, 41, 20, 10,170,211, -233,164, 91,183,110, 85,229,229,229, 65, 38,108,129,182, 29, 91,161, 74, 87, 9, 95,189, 9, 67,222,124, 13,195,198, 77,196,142, -239, 18,176,125,255,126,213,168, 81,163,164, 15, 64, 23,206, 54,155,205,237,242,242,242, 44,125,251,246, 21,133,134,134,226,196, -137, 19,239, 84, 85, 85,141, 85, 40, 20,209,114,185, 92, 19, 27, 27,107,169,107, 73, 88,108,108,108,185,227,249, 87, 95,125,197, -219,253, 83, 92,183, 14, 51,250,227,237, 65,189, 90, 29,221,251,223,196, 45,167, 37, 39,187,245, 30,190,156, 16,162,145,203,229, - 5,253,250,245,179,216,148, 6,206,211,240, 15,115, 19,121,170,105,176,202, 54,230, 13,249,127, 29,245,172, 36,178, 85, 7, 21, - 1, 69, 78, 69, 9,218,181,239,172, 50, 90,204, 88,212,103, 48,138, 58,181,146,126,183,227,119, 86,138, 64,204, 36,208, 30, 93, -153, 51, 62,182,238,181,224,208, 49,138,152, 73, 64,143,174,192,130,101,245, 35,110,102,131,146,250,102, 39,115,165, 76, 52,148, -220,250,128, 82, 74,177,132,128,124, 84,231, 51,192, 18,130, 9,231,101, 15,204, 90,235, 59,228, 79,109,228, 63, 12,135, 15, 31, -102,245,221,180,163, 47, 82,147,177, 7,148,202,235, 72, 79,179, 38,172,201,190,144, 5, 0,216,185,147,208,172,139,227,165, 11, -230,178,107,151,145, 35, 71, 90,246,237,219,199, 75, 74, 74,194,129, 3, 7,106, 36,195,113,134,151, 41, 84,237,205,228,162, 35, - 83,234,133, 66,193,164, 11,175,119,206,130,144, 87,236, 27,237,172, 94,189,186, 97, 20, 0,135,122,178,237, 78,200, 10,185,185, -185, 80, 39, 38,170, 62,138,158,128,126, 83,102, 65,212, 38, 16, 16,216,146,253, 89, 40, 96, 17,194, 82, 77, 49,230,149, 24,228, -127,190, 2, 71,142, 28, 81, 41, 20,138, 26,233,110, 27, 1,102, 30,143,215,186,101,203,150, 80,171,213,130,190,125,251, 98,208, -160, 65,188, 27, 55,110,244, 63,117,234,212, 25,133, 66, 49, 64, 46,151,223,176,145, 53,143,101,221, 53, 25, 49,124,100,200,242, - 85,219,120,113,211, 78, 55,139, 24, 61, 83, 26, 17,158,252,228,155, 95, 20, 60, 19,250,196,203, 97, 0,202, 97,141, 49,224,213, -198, 15,142,137,173,220,245,163,122, 43,164, 28,156, 61, 9,238,188, 5,246, 99, 79,130, 0, 41,211,184,253, 94,238, 3,133, 66, -193,243,128, 8,157, 55,169,160, 97, 97, 97, 8, 11, 11,243, 58, 79,188, 98,114,140,100,114,255, 72, 85,247,118,193,232,218, 46, - 24,143,183,106,143, 96,223, 38, 16, 91,128, 46, 62, 77, 16,144,115, 77, 53,253,153,231, 36,108,100,245,232, 10, 92,200,229,225, -252, 69, 63,156,201,109,134,231, 71,250, 99,213,187,124,244,232, 74, 26,204, 72,175, 47, 73, 51,219,156,134,132,132,168, 50, 51, - 51,145,153,153,137, 15,127, 58,133, 71,199,196,169, 0, 80, 15,183, 60,165,108, 63, 50,153,204,253, 91,188,196, 90, 71, 97, 97, - 97,144,201,100, 46, 63,204, 51,158, 98, 92,223, 15, 36,142,229, 25,219,103,137,164, 33,218, 99,236,216,177,146,157, 59,119,170, - 8, 33,120,227, 19,130,223, 14, 13,195,161, 67,135, 88,125, 55, 49,113,138, 36, 34, 60, 22, 67,135, 94,199,231,159,127, 94,227, -222,228,201,192,152, 49,192,252, 57, 73,170, 85,159,177,107, 19,134,252,213,106, 53,120, 60, 30, 38, 78,156, 8, 62,159, 95, 31, -178,191,203,242,119, 53, 32, 19,226, 29,249, 55, 24,194, 86, 1, 0,214,172, 89,131, 53,107,214, 88,175, 13,136,111,180,226, 28, - 56,112, 0, 95,189, 16,131,129,207,201, 32,104, 17, 4, 34,228,131, 39,228,131, 47, 22,129,231, 43, 6, 64, 65,205, 38, 80,131, - 1,175,189, 50, 11,101,251, 51,145,155,155,171, 82, 40, 20, 18, 52, 30, 72,102,102,102,100,199,142, 29, 69, 22,139, 5, 41, 41, - 41,216,182,109, 27, 2, 2, 2, 16, 25, 25,217,110,243,230,205, 31,219,158, 99, 21, 16,168, 80, 40,248,135,247,255,242,191, 71, -252, 10,218,232,202,249,152,188,164, 2, 95,254,247, 51,160,105,111,193,127,227, 90,119,201, 61,241,243,100, 7,238,224,213,162, - 24, 18, 7, 82, 39,214,203,196,126,236,120,253, 30,237,133,193,161,129, 61, 0,246, 86,218,184,251,231,146,174,143,118,109, 46, -255,232, 53,139,135,236, 72,194,194,194, 40,147,150,212, 33, 61, 41,245, 52,109,167,226,133, 87, 36, 79,117,124, 84, 37,170, 50, -193,247,191,111,193,164, 55, 64,252,198, 50, 4,136,196,168, 18, 86, 66, 87, 85, 9, 95, 16, 84, 95, 45, 82,125,250,233,167,210, -183,223,126,187, 78,242,189,144, 11,172,219,100, 1,160,183,125,128, 39,159,224,225,133, 81,164,198,123, 19, 51, 9, 88,183,201, - 43,242,150, 42,149, 74,234,173,181,206, 88,253,153,153,153,119,234,224,176, 17,149, 6, 29, 0, 96, 68,220, 62, 40, 87,142,244, -200,203,144,187, 34, 23, 66,146,115,167, 35,144, 66,144,150, 61, 28,206,139,208,234,255, 94, 96,215,176, 31,217,243,205,147,218, -210,206, 18,155,210,119,252, 56,187,118,150, 63,251,165,100,221,182,127,171,182,159,250, 0,203,231,253,134,112, 73, 40, 54,126, -125, 8,223,238,181,110, 16, 52,243, 95, 31, 72,215,254,244,129, 87, 74, 85,252, 59,160,192, 78, 40,127, 56, 11, 74, 41,154,182, -126, 28,135, 14, 29,130,109,223,130, 58,203,183,234, 51,153, 68, 38,107,161, 2,190, 2,240, 27,210,211,129,240,240, 59,247, 63, -254,248,206,241,252, 57, 73, 42, 95,191,197,210,153,175, 45,173,179,156, 12,249, 71, 69, 69,193, 98,177,224,203, 47,191,108, 80, - 7, 13, 0, 88, 44,150,187,201,159,214,253,254,242, 38,104,107,188,252,204, 16,110,145,185,120,206,238,231,179, 30,244,237,123, -247, 28, 59,111,162,182,134,154,111,177, 76,195,188,121,243,236,247,231,205,155,135, 53,107,214,128,215,109,198,157,255,106,123, -222,149, 60,193, 68,215,229,115,222,201, 90, 48,145, 93,249,170,170,170,208,182, 83,103,192, 98, 0,207, 7, 32, 2, 62, 76,229, -165,168,202,187,132, 91, 5,133,232, 48, 88, 2, 34,106, 14, 98, 52, 0,124, 30, 86,206,124, 19, 35,215,125,128, 5, 11, 22, 52, -244,184,204,138, 21, 21, 10, 5,161,148, 54,175,172,172, 28, 28, 20, 20,132,172,172, 44, 88, 44, 22, 92,186,116, 9,235,215,175, - 71,207,158, 61, 17, 28, 28,252, 50,128,215,156,200,186, 86,111, 0,165,180,101, 39, 94,186,164,221, 35,163, 69, 37, 41,167, 81, -170,245,193,143, 59, 76,216,117,244, 39,204,145,249, 10, 4,122, 75,152, 45,166,192,165, 2,192, 17,122,227,163,182,233, 30, 87, -158, 1, 30,139,142,200,204, 27, 66,178,104, 24,214,165, 40,154,231, 94,204,197,201, 31, 78, 67,161, 80,120,100, 61, 48,228,160, -215,255, 12,189,126, 35, 52,154,104,198, 58,246,232, 7, 14,242,105,166,106, 93,101,134,120,201, 44,152,111,107, 96,186,120, 25, - 2,145, 16,126,132, 15,127,194,135, 63, 95,128, 32,161, 24,180, 92,135,235, 7,142,184,221,233,197, 21,169, 31, 58,102,177,191, -135,171,222, 37,136, 95, 76,108, 30, 1,239,172,127, 27, 57,171,224, 69, 10, 92,103,242,135,128,143,188,235, 21,184, 94,108, 64, -250, 57,235, 6, 34,221,166,109,135, 39,251,158, 11, 73, 14, 4,164, 16, 62,188, 83,214,191,173, 9, 2, 39, 95, 67,192,164, 51, -240,121,126, 9, 16,236,239,153, 39,151,197,206,109,158,108,241,170,216,246,186, 42, 34,232, 93, 28, 63,120, 9,255,111,252, 56, - 4,183,236,142, 89,255,126, 21, 95, 44,222,139,136,192,197, 88,251,211,135, 94,239,224, 67, 8, 16,187,224,140,221, 98, 25, 58, -116,168,141,144, 44,110, 27,120,202, 36,161, 10, 56, 0,224, 55,148,220,108,130,110,143, 52,193, 55,223, 88, 45,255, 37, 75,128, -144, 16,171,136,146,155, 77, 80,114,179, 9,250,245, 57,175,114, 71,254, 7, 14, 28,128,197, 98,177,147,244,230,205,155, 97, 54, -155, 61,114, 95,215,225,225,185,139,252,173,239,179,123,229,157, 2,100,173, 66, 33,101, 44, 53, 11,165,176, 88,238,238,190,204, -117, 11,165, 88,155,144, 32, 77,176,126,199,229,255,164, 0,161, 20, 36, 33, 65, 33,165,148,226,179,207, 62,179,223,103,142, 19, - 18, 18,164,148, 90,159,163, 0,169, 77, 94,130, 66, 1,219, 61, 98, 54,155, 97, 50,155, 97, 50,221, 93,103,204,117,147,217,140, -175,215,174,149,174, 77, 72,168,165,124, 20,130,166, 77, 1, 33, 31,102,125, 5,206,110, 73,194,251,175,202,209,225,117, 57,250, -175,248, 8,151,254, 60, 1,190,175, 24,198,226,155, 56,125, 84,141,237,135,246,160,244,198, 13,156, 57,115,166,193, 54,214,138, -140,140,100,229, 77, 80, 40, 20, 1,148,210, 65,153,153,153,191,191,247,222,123,189,206,158, 61, 43, 50, 24, 12,224,243,249,104, -218,180, 41, 76, 38, 19, 50, 50, 50, 64, 8, 17,185, 27,235, 19, 18, 18,252, 21, 10,133,111, 66, 66, 66,112, 73, 65,234,159, 31, -254, 47, 63,232,175, 67, 59,160,209,241, 32, 18,240,208, 33, 80,140,210,219, 34,200, 63, 53,225,244,237,254,254,238,120,195, 22, -107, 66, 29,251,162, 77, 49,184,235, 58, 71,215,247, 7, 12,249, 59, 43, 7, 60,119, 90, 40,179,223,119, 13, 55,231,232, 41,158, -123,251,108,238,126,189,126, 35, 0,130,170,170,239, 33, 62,118, 25,250, 61,143,214,184,239, 14,111, 15,136,146, 4,104,202, 97, - 17, 9, 96, 56,126, 22,213,231,243, 80,181,247, 16, 80, 89, 13, 17,165,240, 3, 31, 2, 16, 84, 91, 76,208, 84, 87,225,235,125, - 59,220,202, 92,245,174,213,186,119,132,245,156, 49, 87, 40,178, 46, 82, 44, 88,230,125,127,117,202, 87,206,218,101, 47,147,201, -236,123,107, 51,120,105, 77, 1,246, 31,215, 34,255,102, 21, 0, 32,255,102, 21,114, 10, 42,129,232, 68,102, 99, 20,247,174, 31, - 82,104, 85, 4,202, 79,195,223,255, 34,124,196,229,176, 88, 52, 48, 26,143,131,207, 15,129, 65, 87,220,104,157,117,194,232,127, - 75, 0,130, 47,127,155,129, 38,188, 71, 0, 0,215,179, 40, 6,140,227,227,223, 75, 71, 98,232,200, 94, 0,168,237, 57,207, 16, - 21, 21, 69,223,248,132,160, 73,171, 62,160, 0, 70,191, 48,147,245,188,255,218,111, 22,211,214,173,255, 2,112, 6, 37, 55,155, -160,188,216,186, 5,115,223,190, 64,183,110,192,203, 47,223, 33,255,242, 98, 95,148, 23,251, 34,200,239,122,157, 50,199,143, 31, - 15,169, 84,138,225,195,135,215,112,253, 59,126,188,153, 18,112,245,222,122,131, 88,135,249,109, 66,136,253, 83,219,181, 88,185, - 92, 45,143,113, 63, 39, 30, 19, 19,163,114,101, 57,207,155, 55, 15, 49, 49, 49, 53, 8,181, 54,121,191, 41, 20, 56,115,230,140, -221, 5,239, 88,103, 12,156,175,205,140,141, 85,199,202, 93,111,213, 44,162, 20, 60, 63, 31, 24,111, 92,129, 98,241, 98,172,215, -149, 64, 27, 21, 97,191,255,221, 79,235,241,193,155,175, 34,116,193, 75,248,232,244, 1, 36,106, 47, 97,228,179,207, 34, 36, 36, -196,227, 96, 64, 27,209,211,240,240,240, 26,125,248,232,209,163,170,186,182, 99, 87, 40, 20, 66,133, 66, 49,240,244,233,211,249, - 41, 41, 41,234, 55,222,120, 35,226,203, 47,191, 20, 87, 84, 84,216,183,105,174,170,170, 66,147, 38, 77,114, 38, 76,152,208,125, -200,144, 33,143,184, 81, 36,120,132,144, 78,167,211,182, 20,101,239, 89,112,121,193,162,248,118,219,151,180,199,249, 66, 1, 74, - 43,248,176, 16,160,184,194, 0,218,162,107,213,252,119,150,245,122,230,249,127,189, 6, 55,241, 4, 54,247,127, 13, 87,191,155, - 99, 14,141, 64,254,181, 77, 1, 80,182,174, 28,185, 92,238,238, 33,234,108,253, 91, 93,109,223,215,230, 29,112,251, 79,123,181, -108,163,210, 80, 35, 68,197, 26,136,127, 59, 0, 34,224, 1, 85, 6,208,114, 29,136,201, 4, 33, 0, 51,181,160,202,108, 66,185, -201, 0, 88,220, 91, 81, 76,144,223,170,119,107,213,105, 97, 13, 18,108, 16,133,149, 56, 4,242,185,125, 1,238,178,254, 1,252, -242,122,187, 26,231, 3, 23,230, 65, 72,111,195, 72, 90, 66,169, 84, 30, 96,251, 98,137, 43, 84, 8,250,232, 39,220,122, 35, 22, -183, 53,190,104,111, 60, 11,179, 57, 15, 0,112,229,100,219, 70,235,176,137,187,191, 80,189, 58, 74, 81,131,252, 25, 68, 4, 46, -198,224, 94,227, 17, 25,116, 22,137,187,151,170, 60, 25, 68,134, 13, 27, 70, 83, 82, 82, 80, 92, 60, 2, 45, 90,236, 71,147,150, -189, 65, 41, 5,143,199, 99, 21,136,148,159, 15,228,229,157,177,157, 85, 0,226, 10,104,116,192,160, 65,214, 43, 57, 57,192, 87, - 95, 1,229,101,128,174, 2,168,208, 1,254,129,101,172,202, 86,155,181,159,155,155, 11, 0,248,228,147, 79, 0, 0,161,161,161, -247,194,205,204,170, 14,231,206,157, 91,195, 98,119, 38,110,214,222, 29, 27, 97,219,231,253, 29,240,217,103,159, 97,205,154, 53, - 80, 40, 20, 18,119,193,117, 51,130, 67,145,125,246, 28, 10, 3, 3, 85, 60, 30, 15,115,230,204,185, 43, 38,195,147,242, 61, 89, -221, 28,212, 82,129, 87, 63,121, 23,125,198,143,135,226,147, 79,192,227,221,225, 57, 69,206,153, 59, 30,194, 67,135,176,111,223, - 62, 92,186,116, 73, 42,151,203,213,108, 54, 94,113, 36,255,180,180, 52, 21, 0,100,100,100,168, 34, 35, 35,165,105,105,105,234, -240,240,112, 73,122,122, 58, 34, 35, 35,165,149,149,149,170, 90,198, 92,227,180,105,211,250, 76,153, 50,165, 89,151, 46, 93,176, -107,215, 46,125,105,105,169,160,178,178,210,234,237,176,205,127,108,221,186, 53,116,244,232,209,190,114,185,188,210,133, 24,158, - 3, 89,243,242,178, 78,174,249,224,237,233, 77, 90,116, 83,226, 79,229, 43,248,235, 42, 65,254, 77, 1, 64,121,168, 54, 24,161, -161, 45, 10,103,207,152, 21, 65, 8, 41,100,198,124, 79,126,175, 11, 15, 1, 55, 85,240,128,160, 86, 45, 46, 37, 37,229,174, 79, - 73,161, 22, 37,133, 90,143,218,154,249,220,177, 98,173, 13, 47, 62,118, 25, 62,103, 10, 33, 40,208, 50, 30,128, 26,207,215, 38, -240, 92, 65, 62,142,221,190,134,179,151,242,112,243,210,101,148, 93, 46, 64,249,213, 66,152,244,149, 48, 26, 77, 40, 55, 27,160, - 55,155, 80, 77,205, 48,131,130, 18,246, 74,166, 99,180,255,133, 92,235,249,130,101,140,229,207, 67,252,187, 13,179,226,197,211, - 56,128, 56,165, 22,113, 74,109, 13,194,103, 62,145,113, 25, 16,210,219, 16, 80, 45,126,153, 97, 54,177,158, 2,184,121, 12,102, - 93, 19, 0,192,127, 5, 1,168,190,121, 5,153,159,182, 67,246,207, 99,113,236,211,126,200,201,186,214,168, 29,179,239,160, 16, -232,180,128, 78, 11,232,125,207, 1, 0,126,253,208,136,183,231, 45, 1, 0, 12,137,238,229,177,229,255,194,176,131,208,104,162, - 17,120,116, 63, 86,191,107, 85,114,135, 13, 27,198,202,245, 15, 0,203, 63, 94, 74,186,118, 5, 28, 63, 23, 46, 88,221,255, 0, -208,173, 27,197,154, 53, 64,167,238, 21,120, 44,226, 22, 6,141,184,133,231, 95, 50,178, 46,163,163,197,207,156,135,134,134, 34, - 52, 52, 20,115,230,204,105,232, 42,118,251,174, 57, 98,221,186,117, 82, 87,132,109,247,162,173, 90,133,117,235,214,177,178,132, - 95,123,237, 53, 21, 19,249,239, 10,243,231,207,191,203, 11,224, 10, 7,207,229, 99,250,140,217, 56,190,113, 35, 22, 45, 90, 84, -171,114,194,148,111,255,254,253,168, 43, 96,111,216, 99,143,224,251,239,190, 66,216,228,201, 88,190,124, 57,234, 42,227,188,121, -243, 48, 98,196, 8,120,179, 2, 32, 45, 45, 77,229, 16, 44,135,163, 71,143,170, 0, 32, 61, 61, 93, 69, 8, 65, 90, 90, 90,157, - 50,245,122,125,243, 29, 59,118,224,220,185,115,200,201,201,241,211,233,116, 48, 26,173,253,204, 96, 48, 96,247,238,221,196,166, - 44, 84,178, 40,142,165,186,186, 90,116,124,203,100, 84,101,127,129, 61, 41,185,184,116,157,143, 50, 29, 15,102, 10, 20,234,124, - 49,123,193,187,145,177,177,177, 5, 44, 12, 62,187, 94,193, 44, 57,101, 57, 29,192,161, 17,172,255,218, 20, 0, 2,128, 72, 36, - 18, 72, 36, 18,156, 58,117,202,254,201, 59,118, 5,165,149,165,104, 49,200,243,117,191,199,143, 31, 39, 0,224,231, 55, 5,226, - 99,151, 33,188, 82, 12, 74, 8, 68, 51,138,107,220,119, 75, 92, 34, 62,204, 20, 40,208,149, 32,191, 84,131, 91,101, 90,148, 86, - 85, 65,107,168,196,173,234, 74, 92,175,210,163,176,170, 2, 26, 99, 53,180, 22, 35, 12, 22,247,193,175, 79, 62,225, 98,192,115, -136, 11,120,117, 98, 19, 80,136, 64, 61,222, 6,252, 78,244,190,139,107,172,145,127,179, 10,251,143,107, 49,112, 97, 94,205,186, -160,183,225, 99,185, 2, 31,203, 21,124,240,148, 0,249,249,249, 6,182, 50,183, 92,178,160, 85,124,130,253,252,146,206,140,130, -220, 66,100,165,158,197,141,203, 37,141,222,113, 55,126,157, 2, 0, 40, 43,162,240,171,124, 12,146, 25, 2,252,191, 37, 66,251, - 39, 62,113, 50, 8,123,227,159, 62, 55, 52, 5,175, 44,176,146, 63, 33, 4,191,167, 90,155,128,237,154,127, 6,161, 61,186,215, - 44,231, 70,224,203, 47,129,139, 23,173,158,128, 15, 63,164,118,247, 59,165, 20,129,129,129,238, 71, 96, 91, 31,101,230,253, 63, -249,228, 19,228,230,230, 34, 59, 59, 27,217,217,217, 72, 78, 78,198,155,111,190,137,252,252,252, 70,107, 15,134,232, 92, 89,210, -115,231,206, 5, 33,132, 53, 25, 18, 66, 80,151, 50, 81,215, 61, 71, 28,242, 41, 1,225, 53,193,183,239, 44, 67,147, 29,201,136, -137,137,193,100, 70, 27, 3, 32,239,214, 27,115,195, 6,195,207,207, 15,195,134, 13,195,123,239,189,135,228,228,100,213,242,229, -203, 93,190,127,223, 21,102,227,122,175,199, 16, 28, 28, 44,181, 88, 44,117, 42, 20,117,221, 99, 65,142,118,143, 83,100,100,164, -212,129, 40, 17, 17, 17, 33,117,227, 61, 25, 62,108,216,176,102,249,249,249, 56,116,232, 16, 30,125,244, 81, 8, 4, 2,251, 20, - 71,112,112, 48,219,233, 8,139,237,255,146,174, 61,250,199,173,219,219, 28,127,237, 90,130, 39, 35,123,194, 95,204,131,191,159, - 25,190, 62,213,120,250,185, 9, 22, 0, 26,199, 47, 38, 36, 36,184,155,139,178,175, 2, 96, 57, 29,192,225, 65,243, 0, 0, 32, - 10,133,162,233,220,185,115, 49,119,238, 92, 0, 48,124, 28,251, 49,140, 69, 38,248,250,138,225, 77,227,201,100,214,240, 97,191, -167, 46,130,242,121,120,239, 87,189,163,245,207, 10,126,193,193, 82, 83, 19, 63,104,169, 25,231,116, 90,156, 41, 45,198,217,178, -219, 56, 91,166,193, 57,157, 6, 23,245, 90, 20, 87, 87,161,194,100,194, 53,189,206,254, 63,235,194, 11,163, 8, 86,189,203,199, -170,119,249,160,224,131, 18, 30, 98, 38, 17,188, 54, 73,132, 25, 19, 91,161,107,215, 54,176, 64,232,241, 79,102, 92,253,142,243, -242,117, 36, 5,170, 77,134, 52,167,192,170,200,103,174,176, 6,209,237,121, 43, 0, 0, 32,160, 90,240,169, 14,213, 60,107, 68, -179, 70,163,241,147,201,100,209,158,148, 49, 44, 44, 12,201,201,201,216, 88,161, 67,165,129,135, 87, 54,125,139, 34,177, 47, 42, - 13,141,183, 77,196,184,190, 31, 72,211, 52,203,176,241,199, 68,251,181, 95, 63, 52, 34, 34,112,177,253, 60,230,153,175,164, 20, -172,214, 15,211,213,139,129,105, 11, 70,160,249,209,100, 72, 63,141, 2,111, 44,160, 86,171,189,234,195,157, 58,213,140, 30, 31, - 62, 28,104,222, 28, 8, 9, 1,194,251, 54,133, 88,196, 7,159,119, 71,172,216,215,215,237,128,204,227,241,236,150,127,110,110, -174,221,234,103, 62, 31,125,244, 17, 62,250,232, 35, 92,187,198,222, 43,227,106,190,190,230,125,207,173,175,117,235,214, 73, 87, -175, 94,237,146,176,217, 90,255, 14,174,231,187,226, 20,152,115,139,133, 93, 10,123, 3, 33,176,232,171, 33,108,219, 9,242,165, - 75, 49,205,191, 57,154,171,211,236,247,103,252,107, 26, 62,248,239,183,200, 89,245, 11,222,239, 51, 28, 19, 2,187, 96,223,182, -109,200,203,203,115,249,254, 61, 31, 43, 71,175,222,189,165, 22, 91,153, 24,133,204,113,122,198,213,181,218, 48,115,230, 76, 74, - 8,161, 76, 96, 31, 51,223,239, 72,242,105,105,105,234,136,136, 8, 41,165, 20,204, 84,128,155,122, 75, 17, 10,133,143, 62,255, -252,243,185,165,165,165,208,106,181,240,245,245, 69,171, 86,173,208,188,121,115, 52,111,222,220, 93,229, 89,156, 20, 59,179,143, -143,143,254,197,216,207,165,235,143, 13,196,229,171,101,104, 19,192, 71,100,119,130,199,187, 80,248, 55,107, 86, 2,192, 92, 7, -111,112,251, 13, 60,164,214, 63,224,102, 25,160, 92, 46,175, 80, 40, 20, 62, 0,252,229,114,185, 93, 11,236, 16,213,222, 43,205, -151, 89,234, 39,147,201,168,104,134, 61,242,159, 56,204,255,187, 29,144,223,217,153,168,254, 36,250, 57,232, 77,213, 40,211,233, -145,107, 52, 66,104,177,126,185,212, 88, 5, 11,165,160, 0,118,221,188, 4,157,201, 8, 0, 44, 6, 38,130, 5,203,106,246,113, -107, 60,128, 5,102, 84,227,252,197,114,124,191,185,204,163, 31,235, 72,244, 54,151, 63,181, 29,219,137,157,205,234, 7,235,119, -149, 16,142,248, 26, 64, 8,138,139,239, 4,231,137, 44,215, 97,224,181,195,236, 62,217,184,126,221,110, 57,237,103, 83,190,216, - 95,215,213, 80,188,148, 74, 37,152,210,108, 58,125, 4,209,209,209,141,214,113,183,159,178, 46,239, 75, 77, 62, 11, 0, 24,220, -203,154, 25,239,237,121, 75,112,228,108, 47,252, 55,113, 50, 20, 59,102,177,158,255,127,101, 65, 52,130,130,146,109,103,106,155, -178, 20, 13, 74,173,214, 24, 64, 17, 20,148,204, 74,214,190, 61,123,237, 57, 45, 38, 79, 6,164, 82,130,219, 87, 3,160,211,138, - 81, 89, 38,194,166, 13, 4,115,231, 82, 92, 41, 42, 71,120,100, 4, 82, 14,168, 88, 89,197,102,179,217, 62,223,159,156,108, 45, -171, 35,225, 23, 21, 21,161,168,168,136, 53,255, 59, 16, 6,229,241,120,119,145, 42,165, 32,158, 38, 1,146,203,229,234,215, 94, -123,173, 70, 44, 0,227, 17,240,196, 21, 78, 28,180, 18,139,211,178, 2, 66,216,207,217, 17, 66, 96, 42, 47,135,176,101, 16,248, -126, 77,208,235,197,241,248,104,212, 72,188,195, 44,219,235, 63, 0,230,202, 42, 8, 91,180, 65,159, 8, 9, 58,119,232,130,207, -207,167,161,119,239,222,210, 99,199,142,221,165, 4,196,202,229, 0,136, 10, 0,102,197,198,218,151, 14,154,156,200, 94, 32,224, - 3,244,206, 66,197,218, 10,188,118,237, 90, 2,128,218, 92,252, 36, 35, 35,195,165,139, 63, 45, 45, 77,205,134,252, 19, 18, 18, - 8, 33,100,113,243,230,205,123, 69, 68, 68,116,189,112,225, 2, 78,156, 56, 1,179,217, 12,127,127,127,232,245,250,162,160,160, -160,203,158, 24,125, 10,133,130,215,166, 77,155,125,207, 61,247, 92,155,163,135, 51,176, 70,185, 15,205,136, 8,221,219, 84,227, -226,109,127, 12,237,110,188, 4,192,121, 30,203, 92, 87,155, 56,102,156, 34,132, 56,158, 58,231,125,225,208,200, 16,176,120,233, - 13, 0, 12, 14,131, 10, 45, 72,241,120,126,184, 6,185,215, 66,124,172, 51, 6,150,105,180, 82,163,159, 88, 85,202,179,224, 70, - 85, 5, 96, 52,194,108, 91,215,116,190,162, 4,133,250, 50, 80, 74, 97,203, 47,160,102, 83,188,152, 73, 4,235, 54,221,233,147, - 23,114,129, 30, 93, 77,224, 67, 87, 47,242,119,234,236,238,234,160, 86, 47,128, 82, 57, 75, 5,100, 66,163,209, 24,242,243,243, - 5, 43, 71,130, 23,183,111, 24,230,245, 62, 98,183,194,216, 42, 21,174,188, 46,206,231, 12, 9,177,181,230,176,132, 96,160,109, - 37,135,171,229,126,137,137,137,214, 76,128, 50, 25,101,147,243, 33,118,220,215, 82,197,246,217,170,180, 68,138,200,160,179, 24, - 18,221, 11,135,247,157,197, 81,237, 82, 16, 16,200,199,125, 37, 77,216, 62,155, 85,249,130,130,146, 65, 8,193, 11, 47,188,128, -111,190, 41, 3, 67, 49,214,191,148, 81, 8,104, 77,203,254,118,173,242,162,134, 75,165, 41, 7, 84,170,225,195, 1,195,141,142, -184, 90,226, 3,139,109,182,181,157,174, 13,222,138, 41,199,190,163,221,209,180, 67,119, 41,147, 37,176, 46, 48,196, 95, 80, 80, - 0, 0,184,113,227,134,221, 51,112,243,230, 77,251,192,234, 37,136,131,219,217,249,165, 36,108,242, 1, 56,226,155,111,190,145, -174, 89,179, 70,197, 40, 0,171, 87,175,246,216,250,119, 38, 12,111, 33, 22,139,113,227,202,101,116,233,218, 13, 22, 83, 53,136, -201, 12, 65,211,102,104, 58, 96, 32,154,244,127, 2, 22,157, 9,102,125, 53,168,201, 12,152, 45,136, 91,251, 95, 76,156, 60, 17, - 98,177,216,165, 60,211,166, 64, 86,255,215,213,115, 97,203, 93, 63, 27, 25, 25, 41,181, 41, 0,148, 82,138, 33, 67,134, 72, 83, - 83, 83,239,122,206, 29,249,219,234,202, 2, 96,119,247,238,221,251,127,241,197, 23,134, 91,183,110, 85,141, 28, 57,242,185,204, -204,204,247,245,122,125,113,203,150, 45,229,159,127,254,185,134,109,253, 41, 20, 10, 33,128, 71, 34,194,195, 91,197,206,136,197, -165,130, 75,154,169, 51, 98,159, 76,223,183, 33,254,122,185,102,240,192,168,145,150, 54, 29, 66,255,159,179,149, 95, 87,106, 97, - 91, 31, 35, 14,250, 39,113,193, 1,206,199, 28, 30, 84, 5,160, 46,235,194, 27,242,103,200,166,150,132, 49,172,148,128, 21, 39, - 14,170, 1,144, 73, 3, 34, 41,124,197,208, 82, 19, 12, 38, 19, 44,212,130, 22, 1, 1, 40,208,149,194,147,228, 66,174,150,247, -221,137, 1,240,108, 45,182, 43, 23,127,125,211,245,218,242, 8,140, 27, 56,112,224,246,184,184, 56, 81, 80, 80,144,229,250,245, -235,152,215,251,186, 51,249,179,254, 31,181, 37,236,241, 10,182, 44,127, 46,146, 60,221,245, 12, 91, 36,108,159,165, 6, 64,198, -246, 89, 34,217,121,250, 67, 85, 90, 34, 64, 64, 48,174,239, 7,210,237,167, 62, 80,179, 37,127,166, 47, 21, 23,143,160, 64, 25, - 99,253,194, 21,239,172,143,223,207,244, 7, 82,215,230, 26, 54,171,158, 20,107,123, 75,204,229,229, 42,194, 7,244, 85,190, 32, -229, 38, 8,120, 2,232,121, 98,233,168, 9,175, 98,118, 76,172,219,246, 72, 74, 74, 34, 73, 73, 73,244, 30,190,127,160,148, 18, - 66, 8,117,140,104,119,244, 4,120, 34, 75, 46,151,171, 99, 98, 98, 48,111,222, 60,187, 66,209, 88,169,112,135, 15, 31,142,217, -137,235,240, 81,121, 9,250, 69, 13, 5,175, 77,160,181, 76, 70,106, 77,221, 11, 33, 8, 95, 0, 34,226,227,155,132, 85,104, 54, - 98, 32,186,118,237,234,113,212,126,125,224, 96,221,171,194,195,195,165,169,169,169,245,170,171,220,220,220,232,253,251,247, 95, -225,243,249,219,158,124,242,201,143,103,205,154,117,107,237,218,181, 41,128,117,202,193, 3, 81, 60, 0,201, 39, 78,156, 24,244, -195,250, 13, 60, 17,223,231,234,248,151,198,247,157, 61,123,182,246,235,175,191, 30, 11, 32,192, 70,252,229,204, 6, 65,108, 60, - 10, 28, 30, 12,176,113,255,123,171, 0,212, 91, 97,112, 67, 62,172, 7,164, 77, 39,210,136,108,188, 76, 98,201,202, 81,233,170, - 13, 48,153,205,232, 58,104, 0, 66, 77,225,158, 18,110,131, 5,163, 48, 73,127, 0,168, 24,107,220, 22, 7, 80,175, 28,248, 74, -165,114,135, 66,161, 16, 36, 39, 39, 47, 88,185,114,229,167, 14,202,197,112,199,255,197,214,163, 0,160,193,146,151, 76, 56,207, -196, 89,212,254,251, 38,156,151,121,165,233,239, 60,253,161,154,105, 31, 10,138,237,167, 62,240,170,140, 86,114, 39,120,101,193, -240, 59,102, 47,185,115,111,193, 50,207,243,145,199,189,117, 70, 29, 7,144,181,223, 44,150, 84,234,173,251, 0,220,201,255, 31, -235,241, 59, 98,179,200,204,114,185,188,193,231, 85, 25, 37,160, 33,100,217, 98, 1, 84,204,113, 3,148,205,171,239,117,237,218, - 21,109,231,204,145,174,217,187, 87,149,247,241,111,144, 9, 91,160,185,109,243,158, 74,189, 9,115,223, 92, 4,190, 95, 16,118, -109, 80,224, 84, 75,130, 81,131, 7,123,157,183,223,108, 54,121, 61, 76,176,117,241,179, 80,190,200,243,207, 63,127,139, 82, 26, -223,163, 71,143,255, 21, 23, 23,235,188, 32,126,199,122, 31,150,145,145, 1,139,137, 96,240,144,190, 31,204,158, 61, 91, 11, 0, -179,102,205,178, 0,208,214,167, 73, 29, 60, 78, 53,142, 93,120, 69, 57, 60,100, 30,128,123,162, 20,120, 77,140, 73, 53, 18,236, - 32, 35, 55,171,209, 43,213, 41,233, 15,115,173,222,114,229,114,185, 25,192,127,108, 31,175,229,186, 42, 95, 61,127, 47,105,136, -103,238, 37,172, 4, 79,177, 96, 89,114,131,203,118,151,234,215,131,246, 53,222,203, 58,104,168, 77, 87,228,114,185, 90, 46,151, - 55,136, 44, 82,143, 57, 0,166, 12, 10,133, 2,182,237,123,145,239,176,125,111,234,254,125,246,237,123, 71, 68,140,128, 77,233, -173,245,255,241, 39,106,137,121,115,224,221,196,196,114, 55, 65,119, 74, 64, 67,212,215, 19, 79, 60, 81,109, 50,153, 82, 0,232, -222,123,239,189,122,145,104,108,108, 44,121,239,189,247,168,193, 96, 0,128,189,181, 61,183, 98,197, 10,178,112,225, 66,251,255, -178,165, 2,174,115,108,119, 14,238,228,112,127,193,214,195, 69,188,221, 71,152, 3, 7, 14, 28, 56, 52, 10, 76, 0,170, 0,136, - 27,216,136,115,183, 99, 32,235, 29, 5, 57, 60, 28,224, 26,147, 3, 7, 14, 28, 30, 46, 8, 0, 52, 97, 65,254,122, 88, 3,184, - 27,138, 15, 44,224,150,253,253,237, 58, 18, 7, 14, 28, 56,112,248,251,193,143,227, 11, 14,156, 7,128, 3, 7, 14, 28, 56,112, -224,192, 41, 0, 28, 56,112,224,192,129,195, 63, 29, 53, 92, 58, 39, 79,158,244, 58, 34,215, 85, 48,225,131, 46, 47,100,128, 15, -124,125,110, 64, 40, 42,129,197, 98, 93, 22,198,231,243,192, 35,124,235, 95, 30, 1, 33, 60, 80, 34, 0, 33, 4, 60,152,176,125, -167, 16,148, 82, 4,241, 90,192,147,242,217, 50, 42,182,132, 53,128,167, 28,214, 4, 3, 70,102,201,215,195, 88,127,156, 60, 78, - 30, 39,143,147,199,201,123, 48,229,113, 30, 0, 55, 56,120,248, 34,180,165, 90, 24,141, 20,183,110, 19,236, 73,246,197,222,125, -254,224, 17, 33,246,169,218, 98,239,129,118,216,171,106,135, 67,199, 90, 65, 0, 1,120, 16, 99,104, 36, 15, 62, 34, 31,214,255, - 99,210, 43, 83,233,164, 87,166,210,195,169,170, 42, 35,143,164,158, 61,147,121, 80,117,228,176, 46, 57, 57,185, 10, 64, 83, 78, - 7,125,248, 49,242,169,161,146, 89,179,166, 82, 79, 55,121,122, 88,161, 80, 40, 36,212,134,186,118,215, 99, 11,234, 4,174, 71, -113,224,208, 8, 30, 0, 6,131,135, 12, 98,253, 18, 30, 73,205,112,171,181, 52,180,188,134, 68, 70,166, 16,163, 71,154,113,234, - 47, 95,136,132, 2, 8,248, 2, 8,133, 20, 62,124, 35, 32,104, 10, 1, 42, 49,168,151, 9, 98,145, 15, 40,128,118,109,128,103, -199, 88,176,127, 27, 59,242,191,120, 62, 27,143, 62,214, 21,237,131,155,163,224,202,133, 78, 1,109,187,160,101,123, 51,254,248, -253,119, 36, 39, 39,151,160,145,119,196,146,201,100, 99,148, 74,229, 78,135,243,103, 28,207, 57,212,142,217,179,100,212, 84,117, - 86, 58, 40, 44, 80,101,177, 20,163,180,125,165,170, 67,219, 17,168,168,110,135,111,214,253,244,183,221,233, 44, 38, 38, 70, 53, -111,222, 60, 16, 66,176,122,245,106, 85, 67,228, 4, 96,210, 1,112,252,127,255,225,145,210, 69, 41, 8,143, 87, 87,123, 83,199, -246,100,218,244, 78,242,173,154,237,236,184, 51, 34,135,134, 5,147, 13,208,193, 75,192, 78, 1,104, 44,240,238, 51, 23,142, 25, -101, 4, 5, 31, 2,190, 16,131,195, 9, 90,183,226, 65, 32,224,193, 71,200, 71,143, 80, 30,174, 92, 53, 97, 80, 24, 15, 45,130, -196,248,227, 64, 51, 0, 0,159, 86,130, 82, 11,220,165, 8,158,244,202, 84,250, 87,102, 38, 58,183,239,128,191,210,142, 34,221, - 96,132,246,182, 22, 34,159,166,232,217,127, 8,250, 14, 25, 5,213,118, 37,100, 44,115,227,223, 3,226, 31,174, 84, 42,247,135, -132,132, 32, 51, 51,147,233, 48, 37, 0,230, 40,149,202, 29, 50,153, 44, 90,169, 84,238,255,187,189, 20, 51, 99,101,212, 71,160, -129,128,103, 64, 85,149, 25,165, 58, 95,252,248,243,126,143,234,127,196,200, 33,146,102,190, 26, 12, 31, 34, 66,231, 78,207,170, -154, 53, 11,128,209,100,194,173, 91,183,209, 38,255, 42,114,114,243,240,202,203, 99,232,134, 31,118,121,213,174, 97,182, 61, 21, - 0,246,219,100,223, 79,235, 31,184,179, 29,238,234,213,171,161, 80, 40, 36,141,149, 14,248, 62,190, 47,116,203,150, 45,119,239, -167,208, 72,228,165, 80, 36, 72, 8, 8, 98, 26,160,222,105,254,175, 32,233,175, 58,114,188, 45, 75,166,125,223, 43, 59, 94, 77, -208,185, 85,228,254,248,227, 15,251,249,232,209,163,177,123,247,238, 58,207, 57,220,123,242,119,188,230,168, 8,212,169, 0,164, - 30, 78,199,144,161,225,247,173,208, 22,207,178, 67, 58, 62,236,213, 75,200, 19,240,161,213, 8,208,182,181, 16,109, 91,139, 80, - 81, 33,132, 88, 40,128, 89,224,131, 1,125, 8,250, 61,206, 7,143, 8, 65, 8,129,143, 80, 4, 33,175, 26, 68, 44,130, 73, 15, -152,160,171,147,252, 15, 31,216,143, 46,237, 90,225,204,169, 51,200, 47,186,126,167,124,229, 21, 16,159, 61, 70,121,124,130, 1, - 97, 3,240,199,110,207, 56,118,237,218,181,146,204,204, 76,213,197,139, 23,225,235,235, 11, 95, 95, 95,233,214,173, 91,213, 30, - 14,102, 82,165, 82,185,159, 33,126,135,206,209, 28,192,168,111,191,253,246,246,171,175,190,154, 44,147,201, 70, 42,149,202,228, - 7,177,131,135,135,135, 75,210,211,211, 89,255,110,201,240,193,146,222,161, 77, 85, 29,218, 21, 33,160,153, 15,120, 60, 63, 84, - 86,154, 80,172,169,196,100, 89, 79, 42,110, 54, 0,223,127,247, 51,171,126, 36,196, 13,188,240,204,227,170, 94,189,122,226,250, - 13, 45,142,255,121, 2, 21, 21, 58, 4, 4, 52, 69, 72, 72, 39,240,248, 66,152,205,249,136,157, 57,149, 38,172,253,241,111,101, -221,196,196,196,168,230,207,159,111, 63,159, 55,111, 94,131,121, 1, 30,100, 15,128, 82,169, 36, 50,153,140, 38, 37, 37,193,213, -198, 74,247,219,104,151,203, 99, 65, 8,193,186,117, 10,105, 76, 76,253,148, 0, 94,167, 23,237,228,157,177,188,137,203,193,180, -109,115, 30,130,131,120, 15,109,251,253, 83,225, 72,246,174,148, 2,183, 30,128,212,195,233, 0, 80,111, 69,224,240,156,156, 58, -239, 15,253,188,155,215,131,133, 67,142,115,143, 6,161,100,117,107, 8, 5, 66,116,108, 95,129,242,114, 33,142,159,233, 8, 62, -159, 15, 62,225, 67, 36, 52,161, 87, 55, 61,186,119,227,131,128, 7,145,208, 7, 34, 62, 65,216,227, 6, 4, 5, 90,176,241,127, -117,203,238,217,165, 13,174,228, 22,213, 36,127, 27,242,175, 93, 33,132, 39,160,237, 34, 31, 71, 96,243,166, 40,209,222,102, 85, -222, 53,107,214, 72, 86,172, 88,161,186,114,229,138,227,101,213,152, 49, 99,176,107, 23,123,107, 83,169, 84, 30,112, 36,127, 23, -104, 25, 31, 31, 95,242,198, 27,111,236, 67, 35, 79, 81,212, 65,254, 42, 79,202, 22, 26, 18,164, 10,110, 83,134,150, 45,252,209, - 33,184, 45,252,252,253,112,229, 74, 33,204,102, 11,130,219, 55,197,217,243,105,136, 28, 58, 72,146,118, 56,163,206,193,244,245, -215,167,210,199, 67,181,120,228,145, 14, 56,119,254, 10,142, 31, 63,143, 91,183,203, 65, 41, 16, 24,232, 11,189,190, 2,253,251, -247, 66, 73, 73, 41, 10,143,255,137, 33, 79,134, 75, 82, 15,177, 87, 84,107,134, 60,189, 0, 0, 32, 0, 73, 68, 65, 84, 30,100, - 48,214,191,109,219,105, 48,158,128, 53,107,214,120,236, 5, 96,166,251,157, 51, 1,187,216, 78,182,222,253,175, 67,135, 14,180, - 99,199,142,245,206,197,175, 84, 42,201,132, 9, 19,104, 98, 98, 34,152,141,149,234, 34, 60,219, 86,184,119,149, 63, 50, 50, 82, -194,108, 14, 84,139, 18, 75,221,200,180,255,111,185, 60, 86, 85,159,119,212, 89,222,160, 69, 21, 56,182,188, 73, 13,226,231,240, -112, 90,255,206, 46,255,122, 77, 1,212, 87, 17, 24,250,121,183, 90,149, 0,111,200,159, 65, 74, 74, 10, 10, 11, 11, 1, 0,193, -193,193,212,147,151,129, 79, 43, 33, 32,102,136,132, 66,252,121,166, 21,248, 2, 1,154, 10,117,214, 56,128, 38, 60, 20, 22, 54, -197,227,189, 44, 32,132, 64,246,172, 9,212,194, 3,136, 15, 8, 40,172,129,252,174,161, 47,185,138, 27,154, 10,100, 23, 22,214, - 90,150,146, 82, 13,180,183,110,216,100,177, 30,128,156,201, 31, 0,176,107,215, 46, 60,245,212, 83,146, 61,123,246,184, 29,224, -100, 50,217,240,188,188, 60,151, 29,166,180,180,212,241,114,243, 37, 75,150,224,220,185,115, 35, 30,164,169, 0, 7,242,103, 13, -201,240,193, 18,177,224, 58,124,125,155, 67,236, 35, 66,151, 46,157,209,177,115,103,148,149,169,161,209, 84, 64, 36,226, 35, 40, - 80, 12,129,111,115,183,131,169,128, 22,162,105,147, 22,208, 87,154,112,230, 76, 14,174,221, 40,197,245, 27, 21,168,172, 22,227, -145, 96, 19,196, 62,124,228,100,231,225,209,174, 93,113,237,122, 25, 42, 77,205, 88, 13,208,142,110,255,218,174,123, 58, 29, 80, -155, 76,111,100, 49,214,255,188,121,243,238,186, 62,127,254,124,175,188, 0,174,118, 39,116,158, 59,110, 40,175, 66, 90, 90,154, -170,190, 27,242, 76,152, 48,129, 42,149, 74,200,100, 50,184,154, 14, 96,227,169, 98,200, 31, 0, 50, 50, 50,238, 42,147,237,190, - 91,163,135,217, 97,176,161, 60, 46,137,243,253, 49, 97,181,206, 37,241, 7, 7,241,108,163, 20,187,230, 29, 61,122,116, 13, 47, -201,211, 79, 63, 93,163,174, 56,183,255,131, 3,143, 99, 0, 26,202, 35,208,144,200,201,177, 42, 22,133,133,133, 30, 41, 1, 2, -129, 0, 66,190, 16, 66, 33,193,176, 33,128, 94, 87,141, 75,185, 34, 8, 5, 66, 8,204, 2, 68,132, 83,136,132, 66,240,249, 60, -128, 18,104,180,192,177, 19, 2, 88, 44, 22, 0,183,106,149,123,226,207, 92, 84, 84,212,158,129,179, 75,219,182, 84,103, 34,168, -172, 44,133,217, 98, 98,253, 59, 79,156, 56, 81,187,210,161,215,179, 34, 26,103,215,191, 43,205,112,251,246,237,142,207, 39, 55, -134, 23,192,149,139,223,145,252,109, 3, 32, 59, 11, 48,184,141,138,199,187, 10,147,217, 2,131,209,132, 91,183, 53, 16,138,196, -168,174, 54,194,104, 50,195,100,178,192,100,166,172, 60, 49, 34,161, 14, 98,223, 14, 40, 46, 46, 69, 89,185, 30, 26,109, 37,154, -181,232,139,193,143, 63,142,140,212,221,104,111, 48,161,180,172, 20,221,187,119,133,143, 72, 0, 93,185,230,111, 49, 80,216, 34, -255,237,115,255, 78,158, 41,175, 98, 1,230,205,155, 87,195,155,224,124,143,173, 2,160,209, 68,219, 31,140,141, 13, 66, 98, 98, - 98,141,254,202, 24, 8,249,249,249, 94,239,202, 41,147,201,104, 98, 98,162,125,155,241,218, 98, 2,156,201,213,217, 83,149,150, -150,166, 98, 2,223, 40,165,244,232,209,163, 53,238, 31, 61,122, 84,229,206,233,193, 40, 13,140, 18,224,104,197,215,102,232,187, -249,109, 24, 31,153,140,205, 0, 38,174,214,225,137, 69, 21,245, 82,190,156,231,248,221,197, 4,112,184,247,222,128,218, 60, 0, -247,213,191,227,202,210,175,143,245,239,100,177, 34, 39, 39,135, 25, 80, 88,245, 94, 62, 95,128,136, 65, 22,240,121, 2, 28,203, - 20, 35, 43, 71,140,177, 79, 1,207, 60, 13,140, 27, 77,208,174,141, 8, 98,145, 15,196, 34, 31,248,138,125, 16,220,206, 7, 98, -145, 24, 98, 55,203, 0, 11,242,175,146, 18,205, 77, 82,219, 64,210,181, 75, 39, 4, 52,247,135,216, 98, 64,133,222,120,223, 59, -197,225,195,135,247, 31, 62,124,184, 6,225, 59,126, 0,160,184,184, 24,227,198,141,107, 52, 43,223,102, 29, 73,156,175,217,142, - 61,178,228,204,102, 64,167, 55, 66,167, 51,160,172,172, 26, 55,111,106,113,237,218,109,148,151, 87,163,162,194,136,138, 10, 3, -116, 58, 35, 74, 75, 74,221,202,170,174, 54,161,170,202, 12,163,209,128,166, 77, 69,232, 24,220, 12,126,254,254, 0,128,144,174, -157,209,161,125, 51, 4, 52, 19,131, 82, 51,140, 38, 11,170,171,117,127,139,129, 36, 38, 38, 70,181, 96,193,130, 58,201, 60, 38, - 38,134,181, 69,106,219, 82,184,214,251,171, 87,175,198, 55,223,124,227,241, 86,195, 14,219,206,218, 63, 12,161, 22, 22, 22, 50, -187,103,122,196,110, 19, 38, 76,160, 73, 73, 73,112, 84, 30,148, 74, 37, 25, 63,126,124,157,223,155, 57,115, 38, 8, 33, 96,250, -113,120,120,184, 4, 0, 34, 34, 34,164, 12,145, 51, 86, 63,115,159, 82,106,191,207,226,215,214,176,226, 93, 41, 14,108,102, 80, - 90,182,108, 9,226,160, 37,212, 87, 30,135, 7,143,252, 93,157,123,229, 1,120,144, 44,255, 59, 3,188, 25,124, 62,223,227,239, - 13, 25,100, 65,235, 86, 62, 40, 43, 19,192, 71, 96,130,143,136, 15,117,186, 8, 99,165, 66,136,132, 66,148,149, 9,145,154,233, -143,102, 98, 2, 30,143,135,209,209, 6, 60, 55,150,130,199,163, 88,122,210,243,114,202,100, 50,202,247, 19, 67, 35,108, 9, 63, - 99, 1, 46, 22, 82, 12,151, 12, 99,189,165,111,255,254,253,113,228,200, 17,151,247,252,252,252, 88, 15,150, 90,173,118, 4, 0, -172, 95,191, 30,211,166, 77,179, 95, 47, 46, 46,182, 31, 79,155, 54, 13, 69, 69, 69,141,210,158,233,233,233,106, 66, 8,152,121, - 82, 30,143, 7,198,221, 89,199,188,105,173,200,191,122, 77,218,170,153, 94,229, 35,226,195, 96,180,160,170,186, 0, 87, 11,138, -161,209,150, 65,163,209,163, 88, 83,137, 98, 77, 37,154, 7,117, 6,144, 91,167,172,155,183, 41,110,220,188,141,158, 61,187,162, - 68,171,133, 80,192, 67, 89,121, 1,116, 37, 22, 60,246,168, 14,109, 90,181,130,159,159, 31,124,124,124,113,253, 70, 57, 8, 63, -144, 85, 25, 29, 93,242, 13,181, 10,160,161, 87, 16,212,102,173, 3,119, 98, 1,216, 66, 46,151,171, 99, 98, 98, 48,119,238,220, -187,188, 10,204, 52,131,183, 43, 11, 38, 76,152, 80,195,130,101,222, 47, 66, 8, 94,124,241, 69, 36, 37, 37, 17,182, 74,128,179, -229,239,120,207,217,211,224,140,181,107,215, 18, 0,118, 43, 63, 35, 35, 67,101,235,215,106,155, 55,128,249,171, 2, 64,210,211, -211,237,247,235,218,206, 53, 45, 45, 77, 53,100,200, 96,233,145, 35,214,119, 98,230,204,153, 56,121,242, 79, 41, 67,225, 71,143, - 30, 85, 49,191, 63, 34, 34,194,173,167,108,237,218,181,248, 74, 26,136,137,107,244,214,223, 53,223,191,198,253,137,107,244,246, -250,156, 46, 21,226,187, 3, 6,112,120, 8,148,246,184, 21, 53,149,238,149, 11,113,242,228, 73,246,171, 0,238, 5,241, 59,198, - 2,212,199,250,175,105,201,215, 36,127,155,155,201,237, 84, 64,203,150,124,240, 8, 31,173, 90,242,209,173, 43,197,181,107, 2, -240,248, 4, 66,129, 0, 66,129, 16,127,157,246, 71,144,191, 16,124, 62, 31, 67,194,205,240,245,245,129,197, 66, 1,106,246,138, -252,155,180,233,136,155, 21, 20,186,139,106, 8, 8, 31, 23,175,229,147,139, 44,201,223, 54,176, 73,175, 94,189,170,186,122,245, -170,171,223,171,102, 89,142,145,197,197,197,251, 24,146, 7,128,113,227,198, 97,253,250,245,246,103,202,202,202, 80, 84, 84,132, - 29, 59,118, 48,203, 5,239,123,231,181, 13, 92,170,140,140, 12, 21, 19, 44,102,187,230, 49, 41,164, 30, 74, 87, 75, 37, 97,160, -133,101,208, 87, 26,161,245,169, 2,133, 22, 85, 85, 38,148,149, 85,163,232,182, 30,215,174, 87,224, 73,105, 39, 0,169,117,202, -170, 52,180, 68,222,165, 91, 8,233,242, 8,186,116,233,128,226,226,219, 8,108,110, 70,183,110, 1,104,221, 42, 4, 98, 95, 95, -148,148, 84,224,248,137, 11, 40, 40, 44, 67,219, 14,189, 30,218, 1, 36, 65,161,160,132, 64,202,112,169, 35,169,214,181,110, 63, - 65,161,144, 36,172, 93,203,202, 11,176,102,205, 26,149,179, 2,176,106,213, 42,172, 91,183, 78,234, 78, 94, 66, 66, 2,141,141, -141, 37,114,121,160, 67,153,168, 43, 98,166, 0, 48,126,252,120, 86,238,127,199, 41,133, 22, 45,146,224,237,180, 1, 99,229,219, - 20, 0, 74, 41,197,144, 33, 67,164,169,169,169,181,222,119, 71,216,204,220,122,106,234, 17, 21, 33, 4,132, 16,244,235,215, 87, -186,118,237, 90,245,221,207,222, 81, 50,220,201,227, 77,208,130,145, 39, 27,222,185,134,126, 52, 97,245, 57,187, 60, 54,224, 98, - 0, 30, 30,184, 85, 0, 30, 68,139,159,193,164, 73,147,234,245,125, 30,143, 7, 62,223,250,233, 25,202, 67,255, 62,102,248,136, -196, 86, 5, 64, 40,196,224,112,192,199, 7, 16,242,125,208,178,165, 24,124,190, 14,102,179, 5, 22,139,231,110,123,189,230, 6, -196, 29,122,224, 82,242, 79,104, 37,224,225,112,254, 21,143, 7,148,121,243,230,169,215,174, 93, 43,173,207, 50, 64,102, 89,223, -235,175,191,110,191,198, 88,250,101,101,101,208,235,245,152, 62,125, 58, 0,224,235,175,191, 6, 0, 85, 99,180,109, 90, 90,154, -218,102,237,171, 0, 96,208,160, 65,245, 10,224,234,208,169, 59, 50,143,238, 65,235,150,126,240,243,179,118,251,234,106, 51,202, -202, 13,208,104, 43,209,177, 75, 47,252,184, 97,163,219, 54,249,253,247,189,228,197,231, 35,232,209,140,179,120,114, 72, 95,116, -234,212, 9, 70, 67, 21,250,247,123, 28,254, 1, 1,184,146,151,143,194,107, 37, 72, 77, 59, 15,109,121, 0,118,175,223,248,208, -250, 76,103,198,202,109,237, 79, 48, 83, 46,183, 47, 11,183, 56,145, 62,143, 71, 0,106,167, 12, 58, 83, 46, 71, 95, 23, 22, 44, - 33,160,112, 80,203, 99, 99, 99,225,236, 5,152, 59,119, 46, 8, 33,136,141,149,171,108,124,142,153,177,114,244,237,123,183,188, -216,216, 88,187, 59,222, 29,201,177, 37,127,103,140, 31, 63, 30, 35, 70,140,144,122,171, 4, 59,206,213,135,135,135, 75, 83, 83, - 83,213,181,221,103, 19,164,104, 91, 85, 64, 25,229, 43, 50, 50, 82, 42,151,199,170,157,149, 14, 7,249,240, 68, 94,226,252, 38, -214, 83,113,155, 59,158,142,249,249,118,133, 96,207,169,186,199, 62, 87,121, 0,184, 24,128,135, 84, 1, 24, 60,100,208, 61,153, -243,105, 40,203,223,177, 35,121, 3,141,150,160, 93, 27, 30, 8,225,129,240,120,216,187,223, 58,191,239,227, 35,134,143,200, 7, -227,158, 38, 16,251,136,224, 43, 38,208, 20,243,145,113,188, 41,204, 22, 51, 58,118,240,108, 94, 87, 38,147,209,107, 5,151,160, -205,220,133,110, 29,133, 56, 83,232,253,188,240,204,153, 51,213,168,103, 80,158, 76, 38,147,126,249,229,151, 42,198,205, 95, 92, - 92, 60, 49, 60, 60,188, 98,223,190,125, 59,159,123,238,185, 81,197,197,197,100,234,212,169,123,108,249, 2, 26,173,115,166,167, -167,171,195,195,195,165,204,113,125,100,253,184, 97, 35,153,250,202,100,154,125,225, 28,174,229, 93, 1,143, 71, 96, 54, 83,136, -125,131, 16,218,179, 55,118,255,145,204,186, 78,175,221,178, 72, 53,197,215, 84, 85, 85, 38,244,233, 29,130,224,246, 45,145,127, -245, 38,180,167,115,145,149,157,143,253, 7,254,194,149, 66,138, 99,153,103,188,106,167, 7, 37,249,143,101,115,160,215,207,245, -255,132,165,188,220,255, 97,205,154, 53,118, 5, 96,205,154, 53, 64,222,250,187,158,117, 37,143, 45, 40,165,164, 62,253, 56, 54, - 54,182, 94,125,207,129,228,213,222,220,119,229, 85,112,252,174, 43,121, 30,181,243,149, 45, 72, 90,243,178,117,108, 24,254, 72, - 13,242, 7, 0,217,152, 39,172, 7,218,147,110, 21, 0, 46, 15,192,131,131,117, 43, 23,222, 53, 13,224,145, 2,240,128, 7,124, -212,187,112,153, 39,124, 32, 22,137, 48,110, 12, 1,143, 16, 12, 26,104,194,233, 51,190,224, 17,235,156,127, 73, 9, 15,237,219, -242,193, 35, 34,156, 58, 45,130,216, 7, 48, 24, 13,184,146,239,235, 17,249,231,102,255,137,240, 17,207, 64,208, 50, 28,185,217, - 25, 16,220, 72, 66, 64,179, 32, 90, 90,166,105,148, 10, 86, 42,149,106,153, 76, 38, 29, 56,112,160, 42, 46, 46, 14,189,123,247, - 46,210,106,181, 24, 56,112,160, 84,171,213, 98,206,156, 57, 42, 27,249,171, 27,187,145,235, 75,252,206, 74, 0, 0, 68, 14, 29, - 36,105,215,182,157,202,223,223, 31, 63,110,216, 72,206,156,205,245,108, 64, 79,205, 80, 3, 32,102,180,164,231,178,210,209,174, - 77, 19,136,197, 66, 84, 84, 24, 80,120,189, 12, 68,208, 17,199, 50, 83,185,104, 41, 54, 56,241, 6,208,245,255, 80, 99,121,225, -241, 5,141, 90,164,216,216, 32,135,180,181, 13, 67,104,238, 72,217, 19,210,174,111, 62, 3, 87,227,188, 44,210,199,250, 91, 43, -175, 91, 63, 28, 30, 90,244,235,215,207, 30,240,183,110,229,194,187,238,185, 85, 0, 26, 58, 31,255,253,206,239,239,153, 22, 65, -160,213, 18,248,181, 37,104, 17, 68, 48,112,128, 17, 98, 17, 31, 62, 34, 35, 90, 4,137,109,131, 0, 65,196, 64, 51, 50, 78, 8, -173,222, 2,150,138,145, 76, 38,163,189,186, 55,195, 27,115, 63, 66,165,168, 3,126, 77, 46, 68,215,208, 65, 0,128, 38,199,118, - 32, 59, 31,180,162,188,241,148, 0, 0, 36, 47, 47, 79,178,114,229, 74,149,163,119, 0, 0,105, 76,203,255, 94,195,150,236,167, -222,245,126,240,208, 9, 50,245,149,201,244, 86,241, 45, 84,222,208, 67, 44,110,129, 14, 93, 30,103, 53,149,240,176,195,154, 14, -187,129,126,102,222,122,216, 87, 4,228,109,104,244,223,230, 46,184,239,239,134, 81,207, 76,108, 80,203,157,139, 1,120,176,148, -128,218,200,223,173, 7,224,159, 0, 10,107, 84, 63,225, 81, 80, 80, 4, 53,167, 72, 57, 44,128, 88, 36,132,143, 72,128,103,199, - 80, 80,106, 65, 96, 11, 19, 76,102, 2,139,197,108, 27,252,220,227,241,206, 21, 24,251,162, 12, 21,130,110,104,221,196, 31,147, - 95, 8,194,198,173,167,237, 74,128,209,252, 43, 78, 95,104,220,117,226,140, 34,224,112,206,189, 61, 94,120, 21,254,142, 32, 19, -180,132, 38, 6,222,205, 12,202, 32,175,228,173,211,174, 64, 76,224,194,187,111, 28, 95,208,232, 86,255, 63, 25,251,254, 50, 54, -100, 31, 38, 86, 5,145, 58, 40,139,220,180, 64, 99, 41, 1,110, 27,203,219,125,132, 57,112,224,192,129, 3, 7, 14, 15, 47,184, - 68,207, 28, 56,112,224,192,129, 3,167, 0,112,224,192,129, 3, 7, 14, 28, 56, 5,128, 3, 7, 14, 28, 56,112,224,192, 41, 0, - 28, 56,112,224,192,129, 3,135,191, 7,106,172, 2, 56,121,242,164,215,209,160,174,130, 9, 27, 90,222,148,233,177,110,191,167, -211,220,176, 31,251, 7,181,181, 31,255,252,125,194, 93,207,182,146,190,234, 86,222,190,213,119, 50,230,141,156,255,165,253,248, -150,234, 91,120, 83,190,218,224,109,249,106,131,171,242, 61, 63, 85,238,246,123,153,170,157,232,220,185, 51, 46, 95,190,140,129, -210,177,246,235,191,253,168,184,231,245,231,174,191,196, 7, 7, 75,222, 40, 44,116,204, 76, 72,238,103,255,115,150, 55,118,236, - 88,201,174, 93,187,106,100, 74, 28, 51,102,140,116,231,206,157,234,198,120, 63, 30,100,121,245,145,245,119,174,191,168,168,168, -151,250,244,233,179,241,244,233,211, 47,166,164,164,252,218, 0,229,163, 15,202,251,193,201,107, 92,121, 30, 43, 0,206,248,234, -171,175, 36, 85, 85, 85, 32,124, 33, 8, 33, 48,155,140, 16, 9, 5,152, 51,103,142,186,190,154,199, 87, 95,125, 37, 1,128,217, -179,103,215, 75,150, 78,115, 3,254, 65,109,237,196,223,182, 99,103, 0,192,141,171,151,189,146,183,111,245,235, 24, 57,255, 75, - 59,113,125,181, 45, 3, 0, 48,251,217, 65,127, 75, 13, 48, 83,181, 19, 3,165, 99,145,169,218,105, 37,181,241, 83, 0, 0,151, - 47, 55,126,253,133, 2,146,108, 64, 21, 10, 72,179, 1,213, 27,133,133,200,136,123, 27, 0, 48,104,229,167,141, 90,111, 47,189, -244, 18,221,180,105, 19,170,170,170,106, 92, 23,139,197,170,151, 94,122, 9,191,252,242,203,131,186, 60,112,104,247, 46,193, 27, -168,217,172,207,206,191,177, 8,192, 14,206, 14,170, 29,159,127,254,249,240, 63,255,252,179,217,181,107,215,218, 6, 5, 5, 53, - 15, 11, 11, 43,124,243,205, 55,127,244, 86, 94, 84, 84,212,136,201,147, 39,167,108,220,184,241, 85, 0, 1,147,254, 47,118, 58, - 0,203,233,211,167, 95, 86, 40, 20,191,201,229,114,139,135, 34,153,228,202,180, 1,198, 43,103, 18,105,168, 62, 76,239,129, 76, - 14, 13,237, 1,112,196,127,254, 27, 47, 9,232,216, 71, 21,213,167, 7,252,124,132,160,148,194,108,166, 56,147,115, 5,241,171, - 63,147,250,250, 8, 49,107,214, 44,175,200,251,231, 13,139, 36,189,186, 29, 84,157,201, 14,145,122, 91,112,134,240,125, 3, 90, - 64,167,185, 97, 39,254,186, 60, 2,108, 44,213, 65, 83, 22, 98,223,234,215,237, 47, 82,109,207,213,181,198,210,249,127,138, 68, - 34,235, 91, 64, 41, 44, 22,235,251,109, 54,155,237,229,231,241,133,172,173,104, 0,104,215,218,154,170,211, 80, 86,130,106,147, - 9, 0, 80, 97,178,202,235, 50,106, 6, 30,237,213,159, 21,241, 3, 64,223,193, 35,144,169,218,105, 39,254,218,158,187,159,245, -199, 12, 26,217, 0,158,242,247,199, 30,157, 78,197, 16, 63, 0,100,237,221, 87,215,160, 85, 39, 62,253,105,153,228,248,237, 99, - 40,204, 63,133,110,157, 34,240,191,185,191,120,220,135,199,142, 29,251,220,230,205,155, 25,242, 55, 1,168, 2,224, 7,192, 82, - 85, 85, 37,240,245,245,197,216,177, 99, 37,174, 60, 1,141,140, 54, 79,244,235,243,199,158, 95, 18,154,232, 10,207, 99,168,108, -230,198, 43, 90,227,203, 0,126,123,208, 6, 38,153, 76, 70,189,221,128,199,137, 24,189,194,151, 95,126, 41,201,200,200, 80,109, -216,112, 39, 49,209,237,219,183,145,157,157,141,103,158,121,230, 7,137, 68, 34,125,243,205, 55, 89,181,175, 66,161,224,109,220, -184,241, 67, 0,255,159,189, 47,143,111,162,234,222,127, 38, 73,211,116,223,217,247,150,202, 78,161, 8,200,154, 0,165, 66, 1, -101, 41, 90,208, 87, 68,104, 64, 69, 1, 81,180,175,223,159,190, 46, 8,138, 20,101, 13,139,226,171,101, 43,136, 82, 40, 20, 10, - 41,101,211, 74, 41,101,183,180,165,116,163,116, 79,151,236,153,249,253,145, 76, 76, 67,210, 76,210,176,190,243,124, 62,243,105, -231,206,228,100,114,231,222,251,156,115,238,185,231, 62, 55, 34,242, 69,183,157, 59,119,182,126,249,245, 5, 94, 0,116, 0,218, - 26,110,123, 6, 0,103,244,232,209,163,128,251,183, 58,183, 70,170,131,103,127,136,140,132,149,148,181,254,102, 71,255,160,210, -207,103,128,203,229, 65,167,211, 66, 86,223,128, 89,211, 95,160,234,235,235, 91, 74,216,148, 51,223, 11, 11,219,176,180,237,175, -137,167,192,182, 2,176,102,237, 58,161,112,226, 12,105,199, 86, 62,112, 23,240, 64,146, 36,116, 36,192,227, 18,240,247,233,129, -222,221, 59, 73, 83, 83, 14,139, 54,110,220, 40,180, 87, 9, 88,183,110,157,176,103,240, 89,105,255, 30,183,193,229,232,164,235, -214,175, 23, 45,122,251,109,187,100, 52, 86,151,193,205, 39, 0, 62,222, 94, 0, 96,252,107,233,190, 54, 29,187,216,244, 6, 28, -143,127, 27,131,103,127,136,215, 94,154, 6, 0,198,191,150,238,219,112, 48,195, 46,237,154,203,229,162, 67,135, 14,224,114,185, - 80,171,213,104,108,108,132, 78,167, 67, 77, 77,141, 67, 47,215,147,199,197, 15,107, 15,192,213, 7,184, 87, 0,252,213, 80,130, -138,178, 92,252, 28,255,145, 93, 86,127,255, 97, 99,209,161,157,126,138,164,131, 5,242,239,210,165,139,113, 58, 0, 0,138,139, -139,157, 82,127, 12,147,171, 82,145, 30, 30,248,252,237,183, 0, 0,159,155, 16,255, 47, 57, 57, 77, 7, 19, 59,178,181,206,250, -104,164,176,102,112,170,244,195, 78,175, 64, 69,142,131, 43, 73, 33,226, 5, 29,126,252,102,175,232,248, 6, 48, 29,204,121, 11, - 22, 44,248, 77,161, 80, 96,199,142, 29,202, 57,115,230, 8, 0,120, 2, 32,119,236,216,161,158, 51,103, 14, 79,161, 80, 64, 32, - 16, 72, 91, 58,208, 69, 70, 70, 10,143, 29, 59, 38, 53,108,216,210, 98,120,242, 57,255,111,221,231, 31,184,249, 94,223, 5,183, -191, 79,226,211, 49,126, 94,239, 36, 85,124, 86,175,166, 30, 43, 5,128,222,130,183,166, 38,130,242,247, 79,181,251,183, 15, 25, - 50, 68,248,231,159,127, 58, 76, 54,107,214,172, 17,238,219,183, 79, 90, 95, 95,111,241,250,221,187,119,177,111,223, 62,233,235, -175,191, 46,250,241,199, 31,211,108,180, 23, 98,231,206,157, 63,143,136,124,113,102, 78,214, 57, 94,135,118,109,180, 47,191,190, -160,201,184,123,242,240,175,232,219,183,111,143,157, 59,119, 78,232,219,183,239, 65, 0, 56,115,230, 76,179,253,131, 73,127,211, -247, 15, 2,176,145,136,103,192,128, 1,212,145,148,227,200,186,122,221, 88,166, 84,170,240,245,186, 45, 13, 11,231,196,176,132, -253, 20,227,190, 32,192,213,171, 87, 11, 71,140,159, 42,237,209, 41, 0,174, 46, 28,144, 36,137,178,178, 50, 92,201,206,130, 90, - 75,130, 36, 41, 4,248,184, 99,252,132, 73, 82,133, 74,107,247, 23,186,186,148, 35,184, 83, 25,192, 37,208,171,123, 17, 92,121, -247,236,182,252, 77,201,223, 28,178,186,122,148, 21, 21,192,205, 39,192,170, 87,160, 57,242, 50,199, 79,123,126,197, 91, 83, 6, - 99,240,236, 15,209,140,150,125, 31,248,124, 62,184, 92, 46,188,189,189,145,159,159,143,154,154, 26,189, 34,229, 32,249,183,109, -213, 26,158, 60, 46,166, 46,250, 2, 19,102, 13,195,161,171, 37, 40, 83,160,197,228,111,142,226,210, 50, 92,187,112, 22, 65,126, -222,122,242,231,113,157, 82,127,207, 79,127, 13, 0,224,199,115,177,139,252, 1,224,255,214,111,192,255,173,223, 96, 36,255,148, -198, 70,188, 63,126,146,254, 98, 16,159,209,239, 30, 22,215, 85, 56,255,189,231,164,175,119,126, 19, 46, 28, 79,120,192, 29, 28, -112,209,190,245,112,188,253,249, 82,233,242,164, 30,140,212,136,180,180, 52, 13, 0,252,244,211, 79,114, 0, 2,122, 27,229, 29, - 59,118,144, 0,220, 77,183, 85,142,137,137,113,104, 94, 46, 62, 62, 94,104, 79, 57, 3,140, 24, 52,160,191, 60,241,215, 3,226, - 1,125, 66,185,141,215, 79,160,160,188, 30,119,107,229, 32, 41,202,161, 64, 96,138,162,168,234,234,113,212,168, 81,163,156,154, - 72,204,132,252,225,239,159,234,144,140,140,140, 12, 41, 0,130, 32, 8, 12, 25, 50,196,238, 58, 75, 77, 77,189,143,252, 47, 92, -184,128, 89,179,102, 25,207, 53, 26, 13,110,222,188, 41,141,143,143,111,214,139,185,115,231,206,183, 71, 68,190, 56,233,203,184, - 37,188,196,196, 68,108, 91,183,154,103,240, 24, 25,201, 63, 49, 49, 17,235,215,175, 71,223,190,125, 15,218,234,111,230,228,111, -173,191, 77, 24,110,240, 2,122,121,216,148,247,237,186, 77, 70,242, 47,175,172, 66,121,101, 21,100,245, 13,112,113,225,121,110, -218,177, 75, 9,103,109,136,192,226,161, 34, 44, 44,236,190,163, 89, 5, 96,227,198,141, 84, 64,151,126,232,210,198, 23, 74,141, - 14, 4, 1,164,164, 28,197,127,127,218,129,203,217,217,120,127,233, 98,112,185, 28,144, 58, 18,222,238,174,232,210,111,132,116, -237,218,181,140, 59,216,250,245,235,133,189,187,223,145,122,123,202,241,195, 79,229,224, 16, 20, 6,247,253, 91,186,126,253,122, -187, 58,169, 37,242,167,137, 95, 33,171,106,162, 32,200,234,234,109,202,179,212,153,232,142,148,145,176,178, 9,193,253,180,231, - 87, 70,207, 24, 28, 28,140,128,128, 0,212,213,213,129,207,231,131,195,225, 64,161, 80,160,166,166, 6, 92,174,190,147,219,179, -217,210,254,223, 14, 96,241,218, 99, 56,176,238, 99,180,109,213, 26,238, 30,254, 40,210,149,224,231,248,143,224,105, 24, 52,184, - 12,229, 89, 34,127,154,248,101,165,121,232,209,161, 21,234,229, 74,184,186,187, 2, 58,157,205,120, 0, 91,245,247,209,214, 67, -184,118,241, 60,250,116,235, 5,153,206,182,210, 72,147,255,223,199,142,227,255,214,111, 48,150,167, 52, 54, 34,165,177, 17,249, -226,255,224,216,245,203,232, 61,184, 27, 80,101,123,107,230,209,203,186, 9, 23,190, 51, 86, 26,228,209, 19, 10,170, 30, 80,149, -131,175,170,134, 74, 87, 15, 37,169, 0,201,247, 68,251,145,131, 16,177,176, 51,101,203,154,163,231,253,197, 98,177,187, 88, 44, - 6,244, 83, 0, 16,139,197, 48,156, 27, 44, 40, 37,118,239,222,109,119,167, 93,178,100,137,112,233,210,165,210, 94,189,122, 81, - 4, 65, 72, 1,224,149, 87, 94,161, 58,119,238, 76,125,252,241,199, 14,109,205,236,229,202,217,177,225,195,215,221, 34,219,171, -184,231,110,150,225, 80, 1, 7, 31, 30,185,167,250, 79, 90,131,172, 81,131,215, 28,145, 89, 83, 19,241, 32, 45,127,248,251,167, - 98,246,236,217,118, 79, 17,154, 18, 62, 69, 81, 4,189,157, 52, 83,188,246,218,107,194,123,247,152, 25, 37,106,181, 26, 87,174, - 92, 57,217, 92,123, 1, 32,236,208,174, 13, 63, 58, 58, 26, 0,144,153,153,137,147,135,127, 21, 20,151,150,145, 52,249, 27,126, -187,177,191, 93,185,114, 37,190, 37,253,237,235, 57,147,112, 53,175, 8,109,186,181, 5, 26,229,140,127,123,121,101, 21, 52, 26, -173, 65,193,209, 66,163,209,162,232, 78,129,160,133,175,149,176,113,206,226, 17,162,137, 43, 74,165, 82, 97, 64,143, 30, 82,119, - 55, 23,144, 36, 5, 29, 9,156, 61,125, 6,255,249,252, 11,144, 20,112, 43, 55, 23,151,179, 47,161, 79,159,254,224,114, 9, 60, -211,173, 3,242, 47, 50,247, 2,240,121,229, 8,237, 82, 10,240, 8, 20,221,213, 0, 60, 2,253,122,220, 65,198,149,114,135,127, -128,169,123,223,146,103, 64, 33,171,106,178, 26,192, 22, 76,221,251,150, 52,237,140,132,149,136, 88,178,222, 98, 20,187, 41,180, - 90, 45,220,221,221,193,225,112,224,231,231, 7,185, 92,142,198, 70,253, 54,192, 65, 65, 65,168,170,170,178, 43, 71,182,178, 6, - 24,236,230,134,247,215,157, 70, 68,127,224, 78, 22,240,151,225,218,251,235, 78,227,251, 37, 34,232, 72,157,221,245,119,237,194, - 89,227,255, 99,195,123,128,231,197, 65, 74,218,117, 12,232,209, 17,222,158,174,248,105, 95, 42, 6,137,162, 80,108, 97, 21,128, -173,250, 59,120,157, 2,238, 2, 83,198, 18,216,122, 40, 31, 1,126, 93, 49,109, 56,193,168,254,104,119,127, 74,227, 63, 91, 39, - 83,159,198, 3,237,101, 32,230,127, 2,234, 63,159, 3, 28, 5,136,140, 21,244,160, 98,181, 50,131,167,123, 74, 59,251,134,163, - 78,215, 0, 85, 77, 46,126, 46,220,137, 51, 83,106,208,107,158, 8,227, 23,121,194,205,239, 25, 8,120,126,224, 77,145, 97,158, -118, 30,181,109,235, 54,139,131,148, 88, 44,166,104,165,141,195,225,128,162, 40,181, 65,137, 86,114, 56, 28, 57, 69, 81,254, 0, - 72,180, 96,121,109,124,124,124, 90,100,100,164,168,170,170, 74,154,146,146,162, 87,124, 82, 82,208,179,103, 79,244,232,209, 67, - 68,151,217,131,122, 21,249,206,220,255,251, 62,233,155,168, 54, 28, 74, 41,195,252,132, 28,141, 86,163, 89,175,210, 97, 5, 0, -135, 54,163,120,241, 69,245, 3, 39,255,132,132,132, 52, 71,172,127,211, 41, 19,130, 32, 48,120,240, 96, 33,211, 93, 37,117, 58, -157, 93, 10,195,237,219,183, 33,145, 72,136, 77,155, 54, 89,186, 44, 0,208, 11, 0,111, 76,212,180,218,252,252,124,223,204,204, - 76, 36, 38, 38, 34, 60, 63,159,147,153,153, 9, 0, 8, 15, 15,199,243,163, 7,193,219,211, 21,235,127, 60, 80, 62,107,214,172, -184, 77,155, 54, 45,177,183,191,221,253,109, 37,188,122, 11,224,217,125, 49,246,174,156,135,254,125,218,224,153, 73, 95,216,236, - 31,178,186,122, 8, 4,174, 0, 0, 23, 23, 30,228,114,165,179,121,134, 37,253, 71, 0, 38,155, 1, 53, 25,168, 72,146,132,187, - 43, 31,106, 45, 5,146, 2, 56, 4,240,201,103, 95, 64, 71, 2, 13, 13, 13, 40, 43,187,139,214,173,219,128,162, 72,104,181, 58, - 8, 92,120,224,186, 48,115,193,110,216,176, 65,216,189, 75,177, 52,208,175, 78,223, 28, 12, 7, 65, 80, 24,216,251,150,148, 94, - 21, 96, 15,104,235,158,118,247,155,147, 63, 19,235,223, 92,139,166,137,127,195,193,140,251,200,159,169,245, 15,232, 3,134, 92, - 93, 93,225,227,227, 99,116, 25,210,129,127, 62, 62, 62,104,211,166, 13,180, 90,230,202,211,143,169,167,224,211, 5, 16,134,234, -207,115,180,122,247, 63,160, 47,251,248, 11, 41,106,213,246, 77,201, 20,151,234,131, 21, 59,181,242,135,151,143, 7,120,222, 92, - 40, 43, 21, 0,135,131,182,157, 59,224,108,118,129, 67,245,247,218,123, 95, 98,212,208, 49,224,149, 1, 13,173, 1,119, 14, 7, - 67,187,116,133,120, 74,107, 70,114,204,231,250,127,121,105, 30,166,190, 56, 18, 8, 81, 2,151,121,128, 39, 15,152, 28,142, 14, -155,183, 50,243,198,180,247,135, 90, 93, 13, 66, 85,133,159, 11,119,226,252, 28, 31,140,154, 58, 7, 35, 90, 61, 47,186,122, 76, - 11, 45,217, 8, 23,117, 35,180, 61, 72, 84,220, 99, 22, 52,106, 80,222,148,115,230,204,225, 0,168,161, 12, 59, 68, 25,206, 91, -132,148,148,148,180,158, 61,123,138,220,221,221, 17, 24, 24, 8,119,119,119,164,167,167, 19, 41, 41, 41,105, 14,136,107, 51,105, -210,164,173, 27,182,252,192,249, 36,173,129,220,119, 46, 23, 42,181,166, 81,169,195, 50,123,200,223,220,229,159,158,158, 78,208, -199,227, 66,254,150,220,253,246,122, 1, 26, 26, 26,140,255, 95,184,112,193,120, 0,192,210,165, 75,155,156,155,220,239,106, 69, - 92, 59, 0, 93, 12, 74,161,251,243,211, 95, 81,154,122, 2,104,203,255,185,225,195, 77,251,219, 33,177, 88,172,180,167,191,197, - 78, 30,133,126,225, 61,224,213,223, 11, 37, 39, 10, 1,129, 43,166, 47,250, 23, 6,191,250, 61,163,223,172,213,234, 80,114,247, -158,150,182,252,105, 20,221, 41,104,233,171,165,172, 28, 44, 30, 3,133, 0,150, 44, 21,202, 48,184,145, 20,160, 35,245, 74, 0, - 65, 0,191,238,223,135,169,211,102, 32, 48,168,149,113, 0,164,236,120,151, 92, 78, 57,122,135, 20, 25,207,251,245,113, 55,234, -134, 3,123,229,131,203,177,223, 11, 96,238,238,183,116,221, 30,235,223,220,221,111,233,186,233, 90,246,230, 80, 87, 87,135,250, -250,122,168, 84, 42,144, 36,137,138,138, 10,163,251, 95, 46,151,163,161,161,193,174, 41,128, 3,235, 62, 70,218, 85, 64, 86, 0, -104, 20,192,247,203, 69, 70,247,255,197, 44,224,210,221,179,224,218, 89,127,178,210, 60,248,251,120, 32,192,223, 3,207,132,246, - 68,254,237, 10,228,148, 84,161, 83,128, 15, 84,247,202,145,123, 43,183, 73, 46, 0, 38,245, 55, 76,248, 2, 70,136, 98,112, 32, -105, 47,164,233,123,177,115,205,123,152,254,222, 10, 92,214, 0, 21, 85,229,140,234,207,116,174,255,245, 97, 67, 48,187, 87,103, -236, 61,112, 18,151, 47, 23, 96,205,149, 76,236,142,248, 23,176,253, 28, 74, 74, 42, 24, 89, 23, 29,148,174,208,169, 43,161, 86, -235, 35,171, 91,183,239,136, 30, 61,123,138,234,220,244,177, 24, 10, 82, 14,142,170, 17,110,141, 92,220,187,219,188, 2, 64,191, - 51,165, 82, 9,165, 82, 41, 0,160, 6,224,165, 84, 42,189,205,151, 4,182,192, 11, 32, 76, 79, 79,151,246,236,217, 19,175,188, -242,138,168,178,178, 18,211,166, 77,179,103,224, 28,193,231,243, 27, 60, 61, 61,181, 17, 17, 17,119,151, 47, 95,222, 46, 46, 46, - 46,255,175,172,203, 19,119, 95, 83,221,212,144,176,123, 63,214, 7,225,242,119, 38,249,155, 91,255,180,194, 66,191, 51,166,177, - 0, 46, 46,255,196,168,172, 89,179,198,120, 88, 58, 7,140, 43,124,172,189, 27,190,225,224, 0,224,201, 74,243, 44,186,211,233, -254,150,117, 49,235,246,172, 89,179, 98,237,233,111, 35,159,125, 6,227,134,135,226,203,207, 86,227,219,181,201,248,127,191,156, -196,130, 49,131, 80,246,123, 50,100, 53,117, 76,250, 7, 17, 61,229,121,104, 52,218, 44,141, 70,171, 53, 85, 0, 0, 96,197, 39, - 31,181,196,130,103, 45,255, 71, 8, 75,115,255,230, 74, 64, 19, 5,128,195,225, 64,214, 32, 7,151, 67, 64,171,213,129,164, 40, -104, 73,125, 16,105,246,165, 44,140, 25, 27,169,119,147, 81, 20,184, 28, 46,234,229,106,104,213, 42,219,214,255,198,141,194,174, -237,239, 74,131,252,101, 70, 45, 99,216, 96, 79, 67,140, 46, 1,130,160, 48,160,103,174,116,195,198,141,140,189, 0,180,117,223, - 92, 48,160, 67,214,107, 51,193, 53,246,192,207,207, 15, 21, 21, 21,112,117,117, 69,125,125, 61,130,130,130,140, 65,129, 74,165, - 18,181,181,181,118, 41, 0,177, 95,238,198,247,203, 69,240,233, 2,164, 93, 5,222, 89, 37,133, 39,143,139,105,239,126,133, 98, -178, 12, 9,107, 62, 0,151,195, 92, 30,109,253,135,135,135, 34,168, 91, 23,180, 10, 10, 4,159, 67, 64, 75, 80,168,104, 84,160, -166, 94,233, 80,253,125,187,242, 55,188,216,179, 43,188,189, 3,224, 30,212, 14,154,234, 26,100, 29,218,133,218,234, 66,135, 26, -241, 15, 43,223, 6,150,140, 3, 79,171, 70,151, 70,160,156, 91,135,239,239,254, 5,240,189, 25,203,184,152,244,135,168,146,163, - 64, 33, 95,142, 65, 33, 34,244,250,151, 39,242,253,210,164, 65, 65, 89,210,142, 67,243, 33,227,212, 67, 69, 41, 32,255,133,132, -192,211,139,137,229,111, 58,192,211,171, 0,248,206,234,184, 71,143, 30, 5, 0,204,158, 61, 91, 20, 31, 31,159, 54,117,234, 84, -163,197,200,132,252,131,130,130,142,108,221,186,213, 67, 34,145,112,151, 44, 89,130,197,139, 23, 83,231,206,157, 27, 10, 32, 69, -161, 69, 79, 0,127,218,251, 76, 98,177,159, 85,183,191,163, 1,129,206, 36,127,115,130, 55, 85, 88, 40,138, 34, 12,129,129,182, -251, 69,113,241, 57,250,255,157, 59,119, 26, 15,243, 50, 26,254,254,254, 16,139,197,214, 6,193, 98, 0,181, 0, 56,197,165,101, - 56,127,254,188,113,206, 63, 60, 60, 28,128,126,251,237, 61, 7,147, 81, 83,175,148, 3, 88, 33, 22,139,117,246,244,183,223, 15, -124,138,200,229,139, 48,113,226, 88, 4,186,114, 81, 79, 80, 72,201, 41,194,249,171, 37,118, 17,245,194, 57, 49,207,230,231,230, -242,138,238, 20,128, 62, 12,228, 15,214,106,127, 50,137,223,188,204, 18,154,196, 0,184,186,186,226,214,245,203,162, 46,237,252, -165,110, 46, 60,232,116, 36, 8,130, 0, 65, 0,177,226,183, 64, 81, 36,116,134,124, 0,114,165, 18, 55,114,242,193,231,219,140, -234,134, 86, 83,141, 1,189,110,155,142, 24,120,115,201,109,236,255,165,187,177,105, 13,234,147,135, 63,178,123,218,109,253, 91, - 34,126,133,172, 10, 0, 28,178,254, 45,117,180,140,132,149, 0,192,216,250, 7,244,235,252,219,180,105, 3,149, 74,133,123,247, -238, 65,167,211, 33, 48, 48, 16, 85, 85, 85, 8, 12, 12, 52,212, 43,115,194,174, 40,203,197,199, 95, 72, 33, 43, 0,190,121,111, - 36, 26,180, 58, 44, 93,149,136,239,150, 71,227,189, 53,135,192, 35, 8,216,193,255,144,149,230,161,109,160, 47, 92,224, 2, 29, - 8,220,189,125, 13,119,202,101, 8, 14,242,199,239, 23,207,225,198,117,216,109,253, 79,159,187, 20, 46,254, 0,135, 11,236, 72, -190,141,253, 27,223,199,220,149, 18, 44,157,220, 31,111,141,237,108, 87,253,165, 52, 54,226,219, 41, 51,129, 90, 1, 64,184, 0, -223,174,198,140,191, 78,227,216,216,133, 32,190, 90, 4,226,143, 15, 24, 91, 24,151,238, 6, 96,136, 66,134, 6, 55, 46,228, 2, - 1,130,167,187, 64, 69, 41, 32,227,184, 64,139, 80, 80, 58, 57, 52,149,119,113,118,157, 12,179,103, 5, 35, 77, 42,125,232,157, - 54, 54, 54,150, 2,128, 45, 91,182,208,174,126, 98,201, 18,253, 52,240, 47,191,252,194,244,205, 14,111,215,174,221,209,175,190, -250,202,227,214,173, 91,112,113,113,129,183,183, 55, 46, 95,190,172, 1, 80,209,146,231,107,110, 77,190, 35,222, 1,103,146,191, -185,245,175, 39,230,251,151, 15, 26,150, 7,166,217,120,174, 91,123,246,236, 25,198,116,122, 78, 32, 16,204,181,174, 52,137,235, - 71,143, 30,125, 27, 64,120, 78,214, 57,152,206,249,191, 57,119, 38,142,118,235,134,196,196, 68,100,102,102,226, 72,183,110,238, -179,102,205,250,241,212,169, 83,140,251,219, 75,227,134,192,135,244,131, 28, 46,216, 31,191, 8, 27, 15, 93,194,251,207,143,192, -156, 53, 59, 49, 99,197,207,246, 90,224,196,138, 79, 62,178,148, 8,136, 50, 81, 2, 88,139,254, 41, 67, 19, 15,192,155,111,190, - 73,212,222,205, 69, 94, 81, 21,120, 46, 92,104,117, 36, 52, 90, 29, 46, 94,204,196,127,255,251, 35,212, 58, 10, 26, 29, 74,253, -203,119, 0, 0, 32, 0, 73, 68, 65, 84, 9, 62,143,131,242,154, 6,148,220, 56, 47, 90,188,120,113,179, 29,106,227,198,141,194, -158,193,119,254,177,254, 13,237,106,255, 47,161,250,246,196,161, 0, 14, 5, 14,135,196,208,254, 55,164, 27, 25,120, 1, 44, 89, -255,166,171, 0, 60,252,219,216, 69,254,150,172,127,211,168,218,136, 37,235,237, 34, 47,253,160, 88,131,134,134, 6,184,184,184, - 24,173,127,146, 36,141,127,237, 85, 0,126,142,255, 8, 23, 75, 78,193,179,141, 62,232,207,139,199, 69, 69, 89, 46,188, 93, 93, - 80, 91, 93, 12, 46,135, 0,143,195,108,250,153,182,254, 59,250,123,225,122,254,109,104,213,106,184,242,248,104,104, 80,226,119, -233, 57, 12, 18, 69,217, 69,254,116,253,189,240,246,231, 72,248,254, 59,200, 73,160, 99,112, 7, 92,189,246, 7,150, 78,238,239, - 80,253, 1,192,210,224, 65, 72,186,117, 18,144,105, 1, 65, 32,142,103, 92, 7,241,213, 34,122, 96, 98, 92,121,167, 86,231,167, -157, 61,158, 1,168,235,209, 64,212,163,134,211, 0, 25, 79, 3,141,174, 14,174, 74, 57, 4,165,183,177, 59,238, 22,186,132,133, -194, 90, 0,160, 57,220,220,220, 76, 73, 0, 2,129,192,226, 53,166,216,186,117, 43,182,110,221,218,162,206,236,229,229,245, 78, -110,110,174,135,183,183, 55,220,220,220,224,239,239,143,138,138, 10, 16, 4, 33,119,230,160, 65, 91,252,209,209,209, 20,160, 15, - 8,180, 39, 40,208,217,228, 63,100,200, 16,161,173,128, 90,166,177, 0, 30, 30, 30,177, 60, 30, 47,207,188,124,205,154, 53, 77, - 44,127, 0,232,220,185, 51,198,141, 27,183,195,150,253, 83, 92, 90,214, 36,218,255,227,255, 91, 2, 87, 30, 31,173, 91,183, 6, - 29, 19, 96,184,238, 97, 79,127,155, 39,236,135,197,171,191, 67,253,189,114, 4,121,183,194,181,235,133,152,179,102,167,221,253, -195,140,240, 9,179,207,155,202, 97, 61, 1, 79, 0, 46, 93,186,212,108, 50, 32,171, 30, 0, 0, 88,182,108, 89,218, 55,171, 9, - 17, 69, 77,145,118,105, 23, 0, 47,119, 87,244,234, 19,134, 94,189,251,131,199, 1, 26, 20, 58, 20,222,173, 70, 70,218, 97,145, -167,135,187,205, 47,104,148,203, 17,218,249, 46,148, 42,129, 33,107,139,190, 25,185, 9,148,160, 40,160,186,214, 21, 32, 0, 47, - 15, 45,250,134, 22,224,244, 5,219, 89,236, 76,173,127, 83,139,223,205, 39, 0, 46,148, 6,208,254, 51,222,233,120,182,159,209, -212,250, 55,181,248,233,178,220,107, 89,198,123,153,100,217, 51, 85, 2, 0,160, 77, 27,189, 50, 82, 93, 93, 13,111,111,111,163, -251,223, 30, 5,128, 86, 2,128,175,176, 48,122, 52,240,253,105,108,252,119, 20,102,188,247, 29,118,174,124, 11, 60,130, 0,223, -149,217,138, 29,218,250,191, 94, 88,142,144,142,129,216,190,109, 55,186,116,233, 2,159,118,193,232,223, 46, 24, 26,213, 63,238, -127, 23, 6, 50,105,235,255,139,185, 99,241,206, 39, 59,208,177, 27,209,162,250,163,173,255,241, 7,126,192,177,217, 49, 32, 58, - 12, 5,160,207, 10, 8, 0,183, 27, 27,141, 74, 98, 14,152, 37,240,217, 48, 39,143, 24,189,140, 18, 6, 79,171,151,118,233,222, - 7,117,110,192,109,220, 65,125, 65, 5, 42, 86,232,208, 80,211, 1, 55,207,230, 48,126, 33, 36, 73, 18,110,110,110,148, 66,161, -128,137,229, 73,185,185,185,129, 36, 73,226, 81, 12,150,245,245,245,223,188,245,214, 91, 83,182,110,221, 42,240,241,241,129, 84, - 42,197,218,181,107,235,212,106,245,243,206,252, 30,218,226,167,151,203,217, 27, 8,152,152,152, 72, 24,146,252,180,152,252, 1, -192,132,216,109,214,185,173, 12,131, 98,177, 88, 45,145, 72,134,238,221,187,247,114, 99, 99, 99, 91,141, 70,191,204,212,156,252, -123,245,234,133,161, 67,135, 78, 18,139,197,182,190,147, 39, 43,205,195,151,159,126,140, 95,147,142, 32,114,196, 64,156, 72,253, - 67,111,192,180, 11,134, 79,187, 96,132,231,231,227,249,233,175, 84, 22, 86,201,199, 3,216,199,212,250, 95,188, 37, 9,113,111, -140, 71,187, 54, 66,163,114, 97, 94, 15, 45,204,166,200,122, 2,158, 34,165,128,145, 2, 0, 0,239, 47,123, 47,237,155,111, 72, -209,237, 14,207,160, 91,247,158, 82,111, 15, 55,144, 20,160, 80,169,145,159,159,143,138,252, 75, 34, 47, 79, 15, 44, 92,184,208, -102,199,117, 19, 8,176,247,232,104, 17, 29, 1,223,172, 59,130,195,129,135, 7,115,235,137, 94, 2,232,225,223, 6,164, 78,163, - 39,127, 3, 52,132,139,205, 20,187,230,160,151,212, 68, 44, 89,223,132,180, 28, 33,127, 83, 37,192, 52,241, 79,117,117,181,237, - 23, 96, 67, 9,248,217,100,149,240,214, 21,111,254,115,162,105,128, 39, 67, 57, 29,253,189,176,247,194, 37, 92,189,249, 55, 6, -137,162,154,144,190, 61,228, 79,227,133,183, 63,199,254,129, 30,120,123,106, 15,167,212,223,210,224, 65,120,239,224, 94, 16, 95, -126,130, 35,173,135, 96,109,195,213, 38,215,167,249,248, 98,165,172,214, 46,226, 56,181, 58, 63,205,143, 23,129,226,154, 60, 84, - 84,221,197,189, 28, 79,112,117,222, 24,222,111, 36,118,159,221,253, 72, 7, 53, 39,101,251,187,240,227,143, 63, 70, 16, 4,113, -252,187,239,190, 19,188,248,226,139,117,114,185,124, 60, 28,152,243,111, 14,206, 88, 2, 40, 22,251, 57,133,252, 45, 88,169,182, -148, 15, 6,207, 38,174,148, 72, 36,193,245,245,245, 95,102,102,102, 46, 41, 41, 41, 65, 99, 99, 35,248,124, 62,218,182,109,139, -160,160,160, 23, 37, 18,201,239, 63,255,204,104, 75,128, 27, 0,194, 59,250,123,225,185,231,158,195,165, 91, 37, 8,236,218,187, - 73,127,123,126,250, 43,114, 0,235,190,140, 91,178,143,233,239,152, 39,236,135,136,212, 63, 49,251,147,255, 98,212,168, 81,104, -221,186,181, 69, 69,203,137,175,157,112,128,252,169,102,202, 89, 37,226, 17,144, 62,163, 84,192, 0,240,254,251,239,167,109,216, -176, 65,120, 49, 45, 71, 4,232, 35,105, 41,138,130,171,171, 43, 62,120,127, 25,227, 78,251,182,157,105,126,153,130,118,245,115, -181,114, 64, 43, 55, 70,192,211,196,111,239, 90, 44,218,213,159,123, 45, 11,185,215,178, 16, 20, 20,132,138,138, 10,135,136,223, - 39,168, 29,212, 12,130, 35,153, 98,246,231, 63,227,220,105,231, 85, 99, 65, 65,129,113,183, 63,141, 74,121, 31,249,219, 67,252, - 52,254, 53,208,195,105,245, 7, 0, 68,252, 7, 70,226,167,201,255,118, 99,163,104,154,143, 47, 82,128,180,149,178, 90,135,126, -251,111, 43,143,155, 12, 60, 10, 0,192,238,107,204, 19,246, 80, 20, 69,184,186,186, 26,189, 0,244,255, 0,224,234,234, 74, 88, -250,255, 33,227,204, 15, 63,252, 48,106,223,190,125, 75,235,234,234,226, 1,100, 56,251, 11,156,177,244,207,201,228,228,116,136, -197, 98, 5,128,165,134,163, 69,239,227,202,149, 43,195, 1,116, 13,236,218, 91,174, 81, 41,221, 13,253,173, 14,128, 12,192,141, - 78, 1,238, 47,137,197, 98,187, 26,116,196,199, 91, 31, 22,241, 59,164,104, 57,120, 63, 11, 39, 32, 44, 44,140, 17,249,219, 52, - 64, 91,186, 83,223,131, 0, 61,183, 79, 19, 63, 90, 72,252,244,220,180,172,188, 24,178,242, 98, 4, 5, 5,181,200,226, 7, 0, -173,142,180,219,251,208, 28,202,171,101, 14, 63,139, 57,232,185,125,103, 17,255, 3,168, 63, 2, 0, 34, 61, 60, 40, 83,171,127, - 0,207,165, 69,196,255, 63,134,191,234,234,234, 98,216,106,120,244, 56,117,234,148, 68, 34,145,252,183,176, 74, 46,215,168,148, -166,243,145,222,157, 2,220,253, 28,216,253,143, 0,244, 83, 25, 79,154, 82,197,226,225, 42, 1,140, 26,147,163,251, 8,179, 96, -193,130, 5, 11, 22, 44,158, 92,112,216, 42, 96,193,130, 5, 11, 22, 44, 88, 5,128, 5, 11, 22, 44, 88,176, 96,193, 42, 0, 44, - 88,176, 96,193,130, 5, 11, 86, 1, 96,193,130, 5, 11, 22, 44, 88, 60, 21,104,178, 10,224,210,165, 75, 14, 71,145, 90, 10, 38, -100,229,177,242,156, 37,207,176,183, 58, 7, 0,105, 41,249, 10, 91,127,214,229,133,133,133,209,117, 71,175,229,166, 46, 93,186, - 68,178,245,199,202, 99,229, 61,189,242,236, 86, 0,158, 18,180, 40,201, 68,116,116,180, 16,128,105,202, 80, 81, 98, 98, 98, 26, -171, 43, 62, 26,124,253,245,215,175, 94,185,114,165,255,249,243,231,223,115,117,117,133, 92, 46,255, 64, 34,145,172,102,144,129, -141,197, 63, 3, 11, 5, 64,199,214,196,227,141,168,168, 40,225,225,195,135,211, 28,252,172, 40, 57, 57,249,164,147, 18, 74, 33, - 42, 42,234,165,228,228,228,221,155, 55,111,246, 7, 80, 15, 64,199,246,185,167, 15, 79,213, 20,128,129,188, 91,244,249,189,123, -247,154,231, 11,151,182, 68,110,116,116,180,208,176,102,151,138,142,142,166,236,149, 69,217, 9, 75,235,131, 91, 40, 79,248, 40, -222,165, 68, 34, 33, 22, 45, 90,180,250,218,181,107,223,119,238,220,249, 61,129, 64, 0,149, 74, 5, 0, 95,239,223,191,159,156, - 58,117,170,232, 17,117, 25,202,254,227, 97,202,179,186, 7,187,233, 94,236, 14,237,207, 30, 29, 29, 45,164, 40,138,162,254,159, -101,217,244, 53, 91,109,208, 18, 10, 10, 10,168,130,130, 2,167, 17, 76,117,245,184, 38,251, 21, 56,155,168, 9,130,176, 75, 46, - 73, 82,148, 78, 71, 81, 36,105,249,136,138,138, 18, 38, 39, 39, 59,180, 11,213,150, 45, 91,198, 28, 57,114,228,228,232,209,163, - 65, 16, 4,181,107,215,174,113,246, 62,155,249,113,228,200,145,221, 47, 15,227, 67,188, 64, 92,157,231,153,191,111,254,252, 88, -146,190,102, 75, 94, 99, 99, 35,213,216,216,216,108, 59,164,239,121, 16,239,135,133, 85, 67,224,190, 4, 65, 60, 27, 29,222, 98, -222,108, 91,249,180, 31, 33, 90,180,141,219,222,189,123,165, 51,103,206, 4,160, 79,170, 97,210, 56,165,142,120, 21,104,133,130, -206,249,111, 72, 67, 42,141,142,142,182,207,171,144,232,111,199,183,218,238,251,141,147,223,100, 46,206,254,125,109,172,117,104, -198,245, 39,145, 72, 8,153, 76,182,167, 79,159, 62,211, 1,112, 40,138,130,155,155, 27,202,203,203, 81, 91, 91, 11, 31, 31, 31, -148,151,151,159,156, 58,117,170,232,192,129, 3,105,118,190, 19,138, 78, 7, 75, 16, 4,166, 79,159,142,113,227,198,137, 22, 44, - 88,192, 88,206,193,131,191, 25,255,159, 50,229, 69,155,231,182,160, 56,247,246, 63,213, 61,108,125,147,115,243, 50,183, 97,182, - 55, 85,162,183, 19, 54, 69,122,122, 58, 86,172, 88,113,223,187, 24, 57,114, 36,117,250,244,105, 70,109, 57, 49, 49, 81,138, 79, - 8,250,252,254,196, 51,159, 16, 45, 30,204, 31,227,177,165,137,165, 45,145, 72, 68,177,177,177, 24, 53,106, 20,117,230,204, 25, - 70,159, 61,103, 37, 39,227,129,196,247,144,156,156, 44,165, 55, 9, 27, 53,106, 20, 85, 87, 87,215, 28,225, 11, 99, 99, 99,141, -237,245,247,223,127,119, 39, 8, 2, 49, 49, 49,247, 0,180,158, 53,107,214,113,137, 68,194,177,199, 98, 95,125,124,181,241,255, -178,148,187, 32, 8, 2, 59,223,117, 7, 64,224,155, 87,190,126, 33, 48, 48, 16, 0,176,235,167,157,140,235, 42, 60, 60, 28,221, -186,117, 99,153,247, 49, 33,127,123, 61, 0, 84, 98, 98, 34,194,195,195, 41, 43, 3, 40,229, 64,231,118,170, 53,105, 46, 47, 49, - 49,209,116, 67, 12,187, 65, 16, 4,145,152,152, 72,208, 3,144,225,175,195,150, 38, 77,254,134,103, 34, 76,158,205,110, 69,133, -152, 89, 99, 60,152,148,219,130,231,161, 77,198,131, 73,185, 61,228, 79, 81, 20,232,221,217, 40,202,190,102, 34,145, 72, 56, 53, - 53, 53,255,245,241,241,153, 14,128, 51,119,238, 92,204,158, 61, 27,124, 62, 31,110,110,110, 16, 8, 4, 32, 8, 2, 92, 46, 23, - 50,153,140,113, 61, 70, 68, 68, 8, 1, 80,251,246,237, 3,253, 78, 40,138,194,254,253,251,177, 96,193, 2,169,225,250, 99, 7, - 75, 10,193,163,240,172, 37, 38, 38, 74, 1, 16, 47,221,156,137,153, 55, 44,246, 49,106,230,141,104, 17,241,153, 67,253,142,122, -255,253,247,209,181,107, 87,167, 60, 47, 65, 16,148, 88,236,135,128,128, 19, 78,173,135, 9, 19, 38,140, 77, 77, 77, 61, 73, 81, - 20, 17, 27, 27,155,102, 15,249, 91,195,129,196,247, 16, 31, 31, 15,146, 36,241,222,123,239, 49, 82, 40, 76,201, 31, 0,142, 28, - 57,146, 52,106,212, 40, 0,240,139,137,137,209,142, 30, 61, 26, 98,177,152, 52,196,205, 48,241, 50, 54, 57, 95,187,118, 45, 94, -122, 78,111, 27,238,124,215, 13, 47, 15,227,227,131,200,247, 25,255, 38, 15, 15, 15,140, 26, 53, 10,153,153,153,198,241,212,252, -160,239, 97,179, 23, 62, 58,242,111, 86, 1,160,201, 42, 51, 51,211,152,118,210,212,122,178,151,104, 77, 6, 17,103, 15, 74,230, -202,128, 83, 93,195, 22,166, 4,236,134,169, 66, 97,176,254,159,198,118, 70,153, 14, 38, 37, 37, 37,198, 11,197,197,197,140, 21, - 70,153, 76,246,149, 92, 46,127,133,195,225,112,102,205,154, 5,153, 76,134,210,210, 82,184,184,184,128,199,227,129,199,227,193, -197,197, 5,110,110,110, 80, 40, 20, 96,226, 66,220,188,121,179,240,248,241,227, 82,130, 32, 48, 99,198, 12, 80, 20, 69, 43,121, -196,140, 25, 51, 0, 0,169,169,169, 82,118,168,104,158,252, 13,239, 87,100,170, 36,211,239,222,212,171,229,200,160,158,152,152, - 72, 24,222, 11, 54,111,222,236, 20,101,236,163,143, 62,162,141,130, 22,123, 38, 34, 35, 35, 35, 46, 92,184,144,218,165, 75, 23, -132,132,132, 80,195,135, 15, 55,122, 78, 12,187, 63, 58, 68,254,107,214,172, 1, 65, 16,224,112, 56,184,112,225, 2,152,120, 99, -204, 60, 18, 47, 16, 4,129,151, 95,126, 89,107, 40, 82,199,196,196,212, 9,133, 66, 44, 88,176,128,156, 56,113,162,205,223,110, -186, 43,105, 89,202, 93,128, 0, 18,222,249, 39,107,241,206,119,221, 17, 51,220, 21,203,159,255,128,241,115, 49,177,252, 89,239, -192,195, 35,255,216,229, 43, 45, 94,231, 53,215, 33,195,195,195,169,204,204, 76,208,158, 0,154,184,194,195,195,237,234,228, 15, -154,252, 77,173,234,199, 61, 96,207,116, 74,224,169,211, 0, 40, 10, 37, 37, 37, 40, 43, 43, 51,150,153,159,219,176,254,185, 71, -143, 30,157, 24, 26, 26, 10, 46,151,139,220,220, 92, 80, 20,133,191,255,254, 27,106,181, 26, 4, 65,128,199,227,129, 32, 8,232, -116, 58,200,229,114, 28, 56,112,192,166,220, 19, 39, 78, 72, 1, 96,198,140, 25,247,181, 91,122,170,135, 38, 10, 38,237,218,220, -173,111,235,156,137,149, 79,195,218,116, 0, 19,215,191, 57,210,211,211, 97,176, 12, 91,166, 0,127, 66,128,248, 76,175,192,153, - 42,175, 20, 69, 1,159, 16,152,121, 35,218,225, 64, 89,130, 32, 40,195,123, 49,146,145,225,125, 17, 45,145,215,189,123,247,251, -200,205, 81,184,186,186, 82,215,174, 93, 67, 69, 69, 5, 81, 81, 81,129,176,176, 48,170,160,160, 0, 92, 46, 23, 90,173,214,161, - 47, 24, 61,156, 75, 43, 15, 88,182,108, 25,214,174, 93,139,211,167, 79,131, 32, 8, 76,158, 50, 31,119, 10,152,109,224,120,228, -200,145,223, 12,239, 88, 9,128, 52, 28,136,137,137,169, 5,224,155,156,156,140,168,168, 40,161,169, 66,222, 28,244,214,255,253, -251,152,232,167, 3,128, 93, 59,179,236,146,199,226,241, 37,255,102, 61, 0, 6,235,159, 48,245, 4,208,150,127,102,102,102, 75, -200,223, 86,128,146, 67,242, 76, 60, 19, 66, 56, 16,224,244, 0, 44, 39,202,100,240, 49, 62, 15, 93,230,172,224, 23,106,175,159, -241,112, 6, 26, 38, 45, 52, 30,118, 88,254, 20, 61,216,118,232,208, 1,131, 6, 13,194,160, 65,131, 0,192,120,110,126,175, 21, -248,250,251,251,247, 81,169, 84,168,174,174,198,185,115,231,144,145,145,129,138,138, 10, 40, 20, 10,208,115,164, 20, 69, 65,163, -209, 64,165, 82, 49,154, 98,160,219,134, 53,114, 79, 76, 76, 36, 8,130, 0, 83,207,204,193,131,191, 25, 15, 38,231,182,160, 56, -247,118, 19,162,167, 15,211,115,211,123,152, 98,212,168, 81, 72, 79, 79,111, 89,131, 48,153,243,135,126, 26, 75,100, 32,103,130, -190,134, 22,198,222,152,190, 23,218, 11,224, 44, 56,195, 11,208,190,125,123, 20, 23, 23, 19,230,202,174,163,228,127, 32,241, 61, - 99, 27,166, 49, 98,196, 8, 0,192,169,179,204, 23,107, 68, 69, 69, 69, 26,230,254,175, 3,144, 27,198,115,250, 48,106,221, 76, -131, 11,155,206,253, 91, 80,174,236,148,199,226,241, 7,143, 73,231,164, 61, 1,246, 90,254,203,151, 47,167, 86,173, 90,229,180, -135,181, 37,207, 48, 72, 57,173,113, 50,157, 67,107,142,116, 76,100, 53,136,197, 98, 79,107,215, 29,133,233,220,191, 51,148, 0, -211,185,127,166, 74,192,236,217,179,225,225,225, 1, 79, 79, 79,120,121,121,193,199,199,135,244,243,243,227, 36, 39, 39,227,213, - 87, 95, 53,222, 39, 16, 8, 48,126,252,120, 52,163, 4, 4,168,213,106, 84, 87, 87, 67,169, 84,194,199,199, 7,174,174,174,208, -106,181,160, 40, 10, 58,157, 14,106,181, 26, 26,141, 6, 58,157,206,174,248, 2, 67,208,154,213,235,166, 86,232,163,132,173,128, - 64,123,209, 82, 37,128,248,204,250,116,223,204, 27,209, 6,114,117, 80,182,153,245,111, 82,142, 25, 51,102,216, 29, 12,104,110, -253,155,202,115, 20,225,225,225,148, 78,167, 67, 88, 88, 24,117,233,210, 37, 34, 44, 44,140,210,104, 52,144,201,100, 14,203,164, -141, 41, 30,143,135, 37, 75,150,224,194,133, 11,248,103,222,159,121,155, 62,122,244,232,209,145, 35, 71, 2,128,151,129,244,229, - 0,176,123,247,238, 86,167, 78,157,242, 54,244, 15,194,240,215,166,224,181,223,173,197,203, 67,239,183,254,103,127, 47,199,238, -115, 26, 80, 20,133, 1,179, 6, 32,107,103, 22,241, 40,141, 43, 22,206,177,254,109,122, 0,104, 75,149,110,176,166,241, 0, 76, -176,106,213, 42,218, 98,112, 10, 24,200,115,120,126,221,176, 68,175,201,145,154,154, 74,210,171, 2, 90,106,177,199,198,198,122, - 62,205, 13,110,203,150, 45, 88,179,102, 77,147,118, 69,147,255,148, 41, 83, 48,101,202, 20,189,133,115,234, 84,115, 98,252,243, -243,243,149, 58,157, 14, 53, 53, 53,168,172,172, 68, 77, 77, 13,228,114, 57,228,114, 57, 26, 26, 26, 80, 87, 87, 7,153, 76, 6, -133, 66, 1,149, 74, 5,157,206,182,197, 68, 16, 4,246,237,219,103,151,194,246, 36, 35, 61, 61,189,201, 97,138, 37, 75,150, 8, - 77,207,153,204, 57, 91,152,243,111, 98,185,183, 36,144,203,210,103, 41,138, 34,246,237,219,231,212, 88,128,125,251,246,217,221, -135, 7, 14, 28, 72,233,116, 58, 99,130,150,176,176, 48,138, 36, 73,220,187,119, 15,141,141,141, 14,253,230,127, 47, 31,141, 83, -167, 78,129,220,227, 11,138,162, 16, 31, 31,111,124, 71,233,231, 72, 48,157,249,136,138,138,122, 17, 0, 98, 98, 98, 74, 12, 10, -128,106,215,174,132, 86, 11, 23, 46,108,117,234,212, 41, 76,152, 48, 33,194,158,156, 0,101, 41,119, 65,128, 64,130,137,245, 63, -235, 59, 57,184, 47,203,176,235,156, 26,139, 23, 47,198,170,163, 95,179,204,250, 20,145,191, 77, 15,128,249,188,191,105, 60, 0, -211,105,128,196,196,196, 52, 67,128,144,212,204,147,228,232,128,113,159, 60,122, 90,192, 48, 15,233,148, 9,246,113,227,198, 93, - 77, 77, 77,237,243, 56,190, 96,218,234,119,150,219,159,182,250,237,112,251, 55, 65, 66, 66,130,241,255,255,252,231, 63,248,241, -199, 31, 1, 64, 13,128, 79, 19, 63, 0,140, 31, 63,222,150, 2,160, 8, 13, 13,133, 92, 46,135, 90,173, 70, 69, 69, 5, 92, 93, - 93,193,227,241,140, 30,128,198,198, 70,200,229,114,168, 84, 42,200,100, 50, 76,159, 62, 93,180,127,255,254,102,159,143,182, 50, -109, 44,107,197,140, 25, 51,108, 42, 10,122,133,230,193,197, 0, 56,114,221, 28, 38,203,253,238, 67,124,124,188,116,201,146, 37, -162,248,248,248,180, 71,218,134,173, 88,255,166,176, 39, 22,192,154,245,239, 40, 6, 14, 28, 72, 93,188,120,145, 8, 11, 11,251, -148,110,218, 58,157,238, 19, 15, 15, 15, 84, 86, 86, 58, 52,198,124,252,225,104,164,165,165,129,216, 23, 0, 0, 56,246,177, 23, -198,127, 81,143, 81,163, 70,225,203, 85,167, 64, 81, 20, 99,111,197,145, 35, 71, 14,140, 30, 61, 26, 0, 42,118,239,222,217,254, -212,169,211,190, 20, 65, 97,226,132,137, 83, 14, 31, 62,156,116,248,240, 97, 70,114,104, 47,231,218,181,107,241,242, 48,151,166, - 22, 63, 40, 44, 89,188, 4,173,199,183,193,211, 26,183,244, 84, 27,101,171, 62,180,170, 32,132,133,133, 53,175, 0,152, 70,252, - 27,200,223, 24, 44, 69,123, 2,152,106,254, 22, 72,187, 69,176, 32,207,233,115, 82,177,177,177,125, 82, 83, 83,157, 57,224, 61, -173,237,140,128, 62, 10,220,104, 73,191,254,250,235, 0,192, 55,105, 75,198,107,134, 65,203, 26,174, 13, 29, 58,244,213,180,180, -180, 68,157, 78,135,186,186, 58,104, 52, 26,227,188,191, 82,169, 52, 46, 49,164, 3, 3,247,239,223,159,198,160,189, 16, 48, 44, - 1, 52,111,183,209,209,209, 20, 77,250,227,198,141, 19, 49, 81, 0, 30, 84, 30, 0,211,185,127, 83,242, 55,159, 22, 96,240, 62, -154, 3, 21, 31, 31, 47,125,233,165,151,176,103,207, 30, 71,189,101, 66, 83,207, 9,125, 78, 7, 12,206,188, 17, 77,221,186,117, -203,234,231,233,132, 63, 71,143, 30,181,234,177,187,125,251, 54, 99,207, 76,117,245, 56, 10, 0, 34, 34,242,145,159,159,111, 49, -186,188,170,106, 44,128, 26, 0,182,199,173, 94,189,122, 81, 23, 47, 94, 36, 12,131,229,167, 0,192,225,112, 62,185,115,231, 14, -106,106,106, 28,234,200, 28, 14,161, 87,216,105,242,191,172,197,143, 82, 53, 0,224,203, 85,167,236, 30, 35,232, 62,177,112,225, -194, 48,138,162, 16, 53, 41,106,250,161,164, 67,191, 50, 37,126, 83, 81, 47, 78,125,225, 58, 65, 16,189, 40, 10,224,190, 44, 3, - 69, 81, 88,178,116, 9,218,140,111,219,194,188,170,250,101,189,116,187, 99, 51, 9, 62,126,104,110, 21,128,113,240, 54, 91,198, - 70, 37, 38, 38,218,237, 50, 53, 33,109,167, 60,184,169, 60,122,253,255, 83,186,188,238,137,128, 89,221, 55, 89, 34,102,229,218, -125,131,129, 88, 44,214, 74, 36,146,253,163, 71,143, 94,148,156,156,188, 78,171,213,162,182,182,214, 24, 3, 0, 0, 21, 21, 21, -168,173,173, 5, 69, 81,176,167, 61, 69, 68, 68,136,142, 31, 63, 46, 77, 76, 76,108, 98,125,210,159,143,136,136,176, 43, 25,208, -131,128,226,220,219,142, 16,254,125, 4,111, 99,200, 38, 8,130,160, 28, 33,127,131,167, 45,205, 82, 95, 4, 0,147,160, 64, 70, - 88,176, 96,129,148,193,119, 50, 54, 52, 76,167, 42,239, 39, 34,102,201,241,186,118,237, 74, 93,191,126,157,118,249,127, 10,224, - 19,149, 74,133,188,188, 60,200,100, 50, 71,169,144, 34,247,248,225,216,101,253, 74,189, 29, 82, 53,118,159, 83,131,162, 40,156, - 62,239, 56, 39,166,167,167, 99,194,132, 9,162,195,135, 15,167, 29, 74, 58,228,168, 24, 14, 73,146, 46, 0,176,231,188, 6,139, - 23, 47, 70,155,200,182,204,213, 73, 11,104,108,108, 4, 0,228,231,231, 83, 91,182,108, 49, 42,100,166,177, 36, 59,118,236, 48, - 29, 31, 88,247,130, 19, 65, 91,247,150, 44,127,243,235,205, 77, 1, 16,134, 41,128,251,150, 77,217, 51, 5, 96,113,160,112, 30, -233,152,202,115,234,250,127,122,238,223, 81,216, 82, 72,236, 85, 88,172,185,251, 29,157, 6,176,230,238,119,112, 26,192, 52, 40, -136,176,227, 26, 44, 40, 1, 20,128,245, 18,137,100,115, 66, 66,130,134,207,231, 67,165, 82, 65,171,213,130, 36, 73,248,250,250, -162,166,166, 6,246,102, 83, 60,126,252,120, 26,244,235,254,169,125,251,246,193,160, 8, 24,151, 6, 30, 63,126,252,127, 98,112, -120,233,165,151,168,198,198, 70, 28, 58,116,200,222,246, 44,180, 81,223,212,204, 27,209, 34, 38,222,184,247,223,127,255, 62,227, -194, 28, 31,124,240, 1,197, 52,200, 83, 44,246,179, 41, 79, 44,246, 99, 36,204,205,205,141, 30, 36, 41,138,162, 32,151,203, 81, - 90, 90,234,240,156,191, 41, 34,191,168,111,114,222, 18,242,215,233,116, 4, 0, 56, 96,241,155,131, 60,248,123, 82,119,211, 76, -128,206, 66,115, 10,153,137, 2,192,226,113,244, 0, 24, 94, 28, 97, 79,249, 35,182, 64,211, 30,179,231, 33,236,176,152,109, 40, - 34,227,156,246, 92, 51,103,206, 20, 57,144,222,183, 89, 11,205,130, 5,218,156,117,202, 40,104, 76, 44, 22,107, 1, 16,211,167, - 79, 23, 22, 22, 22, 74, 21, 10, 5,116, 58, 29,122,245,234, 37, 26, 52,104,144,195,239,123,223,190,125,166, 75,206, 28,242, 26, - 61,232, 24, 0, 91,231, 76,244, 69, 67,116,120, 83,194, 57,125,218,110,183,191, 97,173, 63, 53,243,198,253, 10, 28, 69, 81, 20, -157, 35,192, 68, 33, 51, 6,204, 57,218, 55, 0, 96,239,222,189,132,179,250, 26,211,123, 0,160,186,186, 26, 93,187,118,165,234, -234,234,208,185,115,103,100,103,103, 59,101,172,227,188, 84, 3,130, 32, 48,229,133, 88,218, 13,131,213,171, 22, 24,255,183, 55, - 99,166,179, 32, 22,139,201,205,167, 54, 59, 85,230,156, 57,115, 12, 94, 23,137, 39, 0,173,225,160,196, 98, 49,105,114, 15, 59, - 29,240,184, 43, 0, 79, 16, 90,220, 73, 31, 87, 55,148,179,159,235, 1,120, 97, 30,104,189, 25,230,248,141,223,113,227,198,141, - 71,252, 70, 72,226,241,150,167,175, 43,123, 51,202, 89,197, 39, 77,246,177,160, 44, 93, 51, 88,222,105, 79,195, 64, 82, 86, 86, -102,124, 31,249,249,249, 78,123, 39, 18,201,102, 74, 44, 94, 64,252,254,155,132,209, 7, 28,221,222,213, 17, 24,150,245, 57,125, - 76,104, 78,185,102,221,254, 15, 31,150,166, 6,136,135,217,208, 88,176, 96,193,130, 5, 11, 22,143, 7, 56,108, 21,176, 96,193, -130, 5, 11, 22,172, 2,192,130, 5, 11, 22, 44, 88,176, 96, 21, 0, 22, 44, 88,176, 96,193,130, 5,171, 0,176, 96,193,130, 5, - 11, 22, 44,158, 10, 52, 89, 5, 64,231,188,118, 4,150,130, 9, 89,121,172, 60, 86,222,195,147, 23, 23, 23,215, 84,187,231,112, -140,217,229, 76,151,154,209,217, 20, 77,151,158, 89, 74, 31,236,233,233, 9,129, 64, 96,252, 60,135,195, 1,151,203,189, 79, 30, -189, 49, 19, 73,234, 87,121, 89,219, 44,135,125,191,214, 33,145,108, 17,114,121,174,160, 72, 45,230,207,127, 35,205, 17,121,155, - 55,111, 22,101,103,103,243,194,194,194, 82,205,179,238, 57, 40, 79,152,157,157,141, 77,155, 54,165,177,253,237,201,147,103,183, - 2,240,191,136,192,192, 55,154, 84, 92,101,229,118,226,177,146,247, 70, 32, 5, 0,149,219, 43, 9,211,255, 91, 32,178,133,201, - 61, 31,184,188,255, 89,108, 93,183, 70, 88,113,245, 28, 70,249, 85, 72,219,107,139,144, 67,117,197,133, 70,127,145,119,232, 16, - 44, 90,186, 44,205,214,231,207,156, 57,131, 17, 35, 70, 24,137,159, 38,108,130, 32,238, 35,108,146, 36,141,199,157, 59,119, 44, -202,187,120,241, 34,194,195,195,225,230,230, 6, 30,143, 7, 46,151,219, 68, 38, 77,250, 58,157,206,120,168, 84, 42,100,102,102, - 34, 36, 36,228,169,123, 63, 18,137,132, 16,139,197,212,230,205,155,133,127,255,253, 55,110,221,186, 37,245,245,245,197, 47,191, -252,210,162,246,191,101,203, 86,161,171,192, 31,190,126,207, 72, 27, 27, 74, 68, 91,182,108, 19,110,220,104, 95,238,135, 77,155, - 54, 9, 19, 19, 19, 79,230,228,228,224,208,161, 67, 8, 13, 13,197,123,239,189,199, 53, 93,123,239,128, 60,105,126, 94, 46, 66, -130,187,129,239,234,138,197,139,151,140,137,141,141,101,183, 2,126, 90, 61, 0, 79, 18, 34, 34, 34,108,106, 60,199,143, 31,183, -217, 49,105,130, 54, 39,110, 71,225,108,121, 15, 0,132,157,164,109, 51,181,172,147,229, 49,249,188,249,247, 63,217,196,178,121, -179,240,250,153, 99, 40,220,253,141, 84, 46, 87, 65, 51,132, 3,183, 14, 4,186, 23, 94,198,179, 94,148,180,166,226, 47,180,219, -252,255, 68,211, 23,124,214,172, 18,112,253,250,117,112,185, 92,140, 28, 57, 18, 60, 30,207,120,208, 10, 1,109,245,107,181, 90, -232,116, 58,104, 52, 26,220,185,115, 7, 39, 79,158,180, 40, 79, 46,151, 35, 43, 43, 11, 67,135, 14, 5,159,207,135,139,139, 75, - 19,153, 36, 73, 66,171,213, 66,171,213, 66,163,209, 64,161, 80, 32, 43, 43, 11, 13, 13, 13,143, 3, 89,115, 12,109,131, 3, 64, -219,146, 60,244, 18,137,132,136,139,139, 35,227,226,226, 16, 16, 16,128,127,255,251,223,152, 49, 99, 6,234,235,235, 17, 16, 16, -224, 80, 6,210,128,128, 0,227,243,124,244,209,135,248,121,103, 38,220,220, 90,129,203,229, 75, 27,234,139,236,150,153,145,145, -129,134,134, 6, 12, 29, 58,244,206,184,113,227,218, 86, 85, 85,225,216,177, 99,186,249,243,231, 99,235,214,173,205,246, 17, 85, - 65,238,125,117,115,229,230, 77,164,121,185, 99,105,252,103, 69, 3, 6,246,233,120,183,184, 28,199,146,211, 78,238,218,181,123, - 92, 76,204,203, 39, 88,234,124,252, 65,167,254, 53,243, 20, 48, 82, 0,204, 83,183,218, 58,127,232,228,255,230,155,111, 54,123, - 79, 77, 77, 13, 0, 80, 76,148, 0,154,172, 91,106,173, 63, 8,121,166,150,191, 19,172,127,123, 73,155, 41, 89, 59, 91,158,233, -189,166,127, 1, 0,213,213,250,204,136,254,254,169, 79, 69, 71, 45,248, 51, 21, 33, 69, 82,105,145,156,196,180, 16, 46,158, 9, -210,130,244,167,224,226,207, 69,125, 21, 31,110,245, 10,244,204, 94, 47,253, 57, 62, 78,244,234,146, 21, 86,149, 0,130, 32,112, -227,198, 13,240,249,124,140, 25, 51,198, 72,218, 46, 46, 46,224,112, 56,160, 40, 10, 26,141, 6, 90,173, 22, 42,149, 10, 69, 69, - 69,144, 74,165, 86,183, 84,230,112, 56,208,104, 52,200,206,206,198,200,145, 35,225,230,230, 6, 87, 87, 87,163, 60, 90, 1, 80, -169, 84,104,104,104,192,149, 43, 87,160, 84, 42,141,211, 4, 76, 16, 19, 19, 35,228,114,185,210,250,250,122,240,249,124,148,151, -151,191, 61,109,218,180,122,129, 64,240,179, 35,164, 29, 19, 19, 51,147,203,229,238, 73, 78, 78,166,229,229, 76,155, 54,237,111, -137, 68, 50, 67, 44, 22,171, 29,177,132,227,226,226,164, 43, 86,172, 40, 7,208, 10,208, 79,181, 92,191,126, 29,173, 90,181, 66, - 88, 88, 24,126,250,233, 39,187,201,255,135,185,115, 49,113,192, 0, 0, 64,155, 69,139,224,230,222, 26, 13,117,133,168,147,229, -137, 98, 99,231,165, 89,203,231,110, 13,253,250,245, 67,121,121, 57,206,156, 57,211,153,195,225,224,202,149, 43,240,247,247, 71, -122,122, 58, 94,123,237, 53, 42, 59, 59,187,217,207, 87,125,181,180,201,185,167, 90,131,118, 90, 37, 22,191,255, 73,199,248,213, -255,193, 55,171, 55,162, 61, 71,135,141,171,215,164,190,246,218,107,176, 37,143,197,227, 71,254,116, 57,211,189, 0,238,203,255, -109,235,252, 97,194,153, 59,245, 61, 9, 48, 85, 2, 30,146, 39,192, 94, 75,157,176, 97,157, 59, 34,207,210,223,167, 42,113,213, -119,171,190, 20,134,102,255, 32, 45,231,234, 16,226, 3,116,238, 68,129,219,143, 15, 94,183,110,224,171,148, 80,157, 45,130, 74, -198, 3,151,116,129, 50,245,103,233,214, 13,171, 69,243,223,178, 60, 29, 64,187,231,115,115,115,225,231,231, 7,145, 72, 4,129, - 64, 0, 62,159, 15, 30,143,103,180,250,149, 74, 37, 74, 75, 75,113,234,212, 41,112, 56, 28,112, 56, 28, 52, 39, 79,167,211,225, -218,181,107, 24, 49, 98, 4,188,189,189, 33, 16, 8,192,229,114,161,213,106,161, 86,171, 81, 87, 87,135,191,254,250, 11, 42,149, - 10, 60, 30,207, 24, 11, 96, 11, 35, 71,142, 20,222,188,121, 83,122,251,246,109,212,213,213,129,207,231,163, 77,155, 54,235, 79, -159, 62,141, 97,195,134,241, 36, 18,201,143,246, 40, 1, 35, 71,142,156,122,243,230,205, 61,102,242, 66, 79,159, 62, 29, 58,108, -216,176, 93, 6, 37,128,145,188, 77,155, 54, 9,213,106, 53,202,202,202,104,151,183,177,146, 86,172, 88, 81, 18, 23, 23,215,126, -198,140, 25, 99,222,125,247, 93,187,198,191,173,219,126, 20,126,184,124, 89,147,178,178,117,235,208,230,197, 14,248,230,155,239, - 68,115,231,190,226,208,120,122,230,204, 25,233,159,127,254,137, 15, 63,252,176,142,203,229,122, 11, 4, 2, 12, 27, 54, 12, 82, -169, 20,201,201,201,104,223,190,189, 29, 61,143,192, 47,185,119,177,255, 86, 9, 14,254,254, 19,184, 92, 2, 75, 23,189, 74,246, -111, 19,200,217,178,248, 19,108,181, 87, 30,139, 71, 66,254,230, 74,164, 37,165,192,225, 85, 0,143,122,123,219,110,221,186,137, -108, 29, 15,219, 90,127, 16,242,156,104,245, 51, 37,109, 71,200, 26,166,214, 57,109,161, 27,228, 80, 14,202,179, 58, 80,251,251, -167, 58,100,253,111,216,176, 65, 56,111,222, 60,202, 90,153,249, 53,107, 48,189,127,195,134, 13, 66,243,107,230,101,205,214,215, -181,139,210,210,146, 58,180,242,226,161,155, 23, 5, 94, 32, 9,222,115,207,195,163,255,207,112, 27,248, 45, 92,125,220,192,111, - 80, 64, 46,215,161, 19, 87,142,244, 4,235,169,100, 57, 28, 14,120, 60, 30, 92, 92, 92,112,235,214, 45, 92,185,114, 5,222,222, -222, 8, 8, 8, 64, 64, 64, 0, 2, 3, 3,225,235,235, 11,153, 76,134,244,244,116,112,185, 92,227,220,190, 37,208,215,249,124, - 62,116, 58, 29,114,114,114,224,238,238,142,192,192, 64,180,106,213, 10, 65, 65, 65,240,244,244, 68, 78, 78, 14, 52, 26,141,113, -138,192,154, 66, 97,110,249,223,187,119, 79,154,151,151,135,174, 93,187, 34, 50, 50, 18,131, 7, 15,134, 92, 46,199,201,147, 39, -145,157,157,189, 93,169, 84,190, 98,135,229, 47,186, 87, 94,241,107,254, 93, 25,188, 66,134, 34, 52,242, 13,180, 31, 60, 5, 53, - 42, 14,142,167,158, 64,118,118,246, 52,165, 82, 57,159, 41,249,215,213,213,225,242,229,203,210, 51,103,206,160, 95,191,126,136, -139,139, 11, 4, 64, 26, 60, 0,237, 1, 64, 32, 16, 48, 38,235,173,219,126, 20,254,146,144, 36,244, 15,232, 35, 77,216,125, 25, -115,127,248, 1,201, 89, 89, 72,206,202, 66,155, 69,139, 0, 0, 26, 77,227, 41, 71,250,220, 11, 47,188, 64, 29, 60,120, 16,211, -167, 79,191,227,229,229,197,113,119,119,207,204,200,200,192,153, 51,103, 80, 89, 89,137,208,208, 80,251,148,210,172, 91, 88,253, -199, 85,108, 93,253,209,101, 30, 87, 1,142,174, 30, 95,175,253,129,179, 39, 61, 19,165, 28, 30,158,121,230, 25,150,101,159, 18, -240, 28, 37,248, 71,181,121,197, 3,179,176,255,183, 21,129, 7, 50,175,222, 66, 87, 61, 97,163,220, 46,165, 98,245,234,213,194, - 19, 39, 78, 72,115,115,115,173,150,101,100,100, 48,146, 69,223,151,145,145,129,234,234,106,233,234,213,171, 69,203,150,233,173, -114, 75,101,205,193, 91, 89,133,228, 66, 37,218,215,112, 49,192,155, 64, 80, 5, 16,194,243, 1,135, 8, 0,165,188,135,198,123, - 4,174, 21,146, 40,107, 84,130,199,225,160,175,191,171,212,218,239, 54, 85, 0, 92, 93, 93,145,151,151,135,246,237,219, 35, 34, - 34, 2, 92, 46, 23, 36, 73,162,170,170, 10,103,206,156,129,139,139, 11,248,124, 62,212,106,181, 85, 5,128,246, 14,208, 74, 0, - 69, 81,200,207,207, 71, 72, 72, 8,124,124,124,208,208,208,128,172,172, 44,232,116, 58,184,186,186, 66,165, 82, 65,165, 82, 89, - 29, 59,232, 32, 58, 0,168,168,168,144, 22, 23, 23,163,127,255,254, 16, 10,133,232,208,161,131,168,177,177, 17, 65, 65, 65,210, -212,212, 84,156, 63,127, 30,190,190,190, 67, 37, 18,201, 78,177, 88,172,179, 85,143, 21, 21, 21, 39,239, 85,203,224, 31, 58, 20, -221, 70,190, 4,223, 14,161, 80, 53,214,162,240,207,195,184,117,226, 39, 90, 30,163,247,107,136,125,144,150,150,150,162,117,235, -214, 16, 8, 4,162,203,151, 47, 75,227,226,226, 56, 6, 15, 0, 0,220,140,139,139, 35,153,180,193,109,219,127, 18,250,250, 61, - 35,245,245,127, 6, 28,142, 11, 52,154, 70,108,255, 81,138,185,175,139,104,143, 2,230,207,159,143,160,160, 32,210,222,190,247, -234,171,175, 82, 9, 9, 9, 24, 57,114, 36, 6, 14, 28,216, 25,128,246,196,137, 19,225, 5, 5, 5,112,115,115,131,155,155, 27, -162,162,162,198,236,221,187,247, 36, 19,121, 59,255, 46,194,183,127,221,196,182,149,203,171, 59, 60,211,185, 95, 99, 67, 13,126, - 63,242, 23, 46, 95,249, 27,190, 20, 9,126,217, 61, 68,189, 61,123,220,158, 61,123,255,183, 92,176, 79, 16, 44, 77, 31, 89,243, - 10, 88, 83,213,137, 25, 51,102,152, 90,208, 68,116,116,116,115,231, 79, 44, 42, 43,183, 19,166,199,227, 38, 15,120, 32,238,255, -230,172,246, 22, 61,179,163,214,185, 61, 30, 0,123, 17, 19, 19, 35, 76, 74, 74,106, 66,254,150,202, 28, 65,110,110, 46,146,146, -146,164, 49, 49, 49,194,230,202,172, 18, 87,101, 17,206,221, 85, 64,174, 35,113,186,136, 68,153,150, 7,157, 42, 19, 53,215,223, -196, 79,139, 98,113,232,152, 12, 87,170, 40, 92,170,208,226, 90,149, 22, 85,165,101,205,122,229, 76,149, 0,129, 64,128, 59,119, -238,224,230,205,155, 0,244,113, 49,127,100,194, 62, 90, 0, 0, 32, 0, 73, 68, 65, 84,252,241, 71,147,185,252,230,230,235, 9, -130, 48,122, 1,104,121, 20, 69,161,168,168, 8,157, 58,117, 66,105,105, 41, 72,146,132, 64, 32, 48,202,106,110, 74,193, 20,133, -133,133, 80, 42,149, 8, 15, 15, 71,135, 14, 29, 68, 92, 46, 23,222,222,222, 24, 50,100,136,200,211,211, 19,133,133,133,168,171, -171,187,194,180, 29, 20, 22, 22,130,228,240,209, 62,108, 28,124, 59,132,130,195,117,129,155,119, 16, 58, 13,137, 2,223,195,143, -150, 87, 96, 75,206,230,205,155,133,181,181,181,210,146,146, 18,116,236,216, 17, 34,145, 72,244,243,207, 63,167, 85, 85, 85, 17, - 0, 48,116,232, 80,173,225,214, 80, 31, 31, 31, 72, 36, 18,155, 1, 15, 2, 65, 0, 2,130,250, 67,167, 85,161,252,110, 6,202, - 74,206,140,173,172,200,250,200, 32, 15, 0,112,175,172, 12, 6,121, 46, 76,219,158, 88, 44,158,145,144,144,128,217,179,103, 99, -214,172, 89, 0, 64, 30, 59,118,140,151,148,148,132,185,115,231,142,191,120,241, 34,113,246,236, 89, 34, 46, 46,142, 81,228,126, - 78,157, 28,203, 79, 93,194, 87,239,197, 98,228,164,113,254, 58, 74,139,189,191,158,194,247,235,127,198,145, 37,175, 97,107,255, - 78,232,228,195,195, 71, 31,197,177, 65,128, 79, 8, 46, 93,186,100,149,252,155,245, 0,152,207,237,219, 58,127, 26,241, 0,150, -224, 57,132, 47,158,253, 66,180, 96,193,130, 39,161,190,155, 76, 41, 60,224, 32, 61, 70,239, 33, 42, 42, 74,120,235,214, 45,169, - 90,173,110,182,172, 37,168,169,169, 65, 99, 99,163, 52, 42, 42, 74, 84, 84, 84,116, 95,217,225,195,135,173,190,187,236,106, 5, -100,106, 18,217, 21, 90,148,214,106,209,250, 15, 30,250,237,205,197,157,130,107,248,251, 79, 53,180, 60, 46,212, 36,160, 84, 83, -168,161, 72, 4, 53,179,173, 61,189,220,143,158,187,167, 35,246,239,221,187,135,206,157, 59,163,160,160,192,232,242,231,241,120, -198,251,237,157,206, 51,205, 33, 64,255,125, 64, 83,130,181,112,110,204,135, 77,178, 38, 73, 18,141,141,141,250,193,145,199, 19, -189,249,230,155, 77,222, 93,125,125, 61,239,224,193,131,152, 50,101, 10,103,249,242,229,247, 86,173, 90,165,181,213, 22, 9, 66, -175, 16, 41,228,247,208, 80, 95, 36,154, 55,239,181, 52,137, 68,146, 14,224,171,250,250,122, 28, 60,120,208,168, 56,134,132,132, -168,153,180,237,149, 43, 87, 78,249,230,155,111, 18,163,162,162, 48, 98,196, 8, 0, 32,207,158, 61,203,249,237,183,223, 32, 20, - 10, 39,109,216,176,225,184, 61, 21,115, 87,174,194,171,201,127, 96,241,204, 40,204,120,117, 58,228,202, 58, 28, 56,152,134,181, - 27,119,226,191,227,159, 69,183,242, 98,150, 77,159, 2,101,128,169, 7,192,217,160,204, 58,178,173,115, 22, 38,120,208,228,239, - 68,171,221,154, 71,193,209,249,255,230,218, 5,163,246,114,248,240,225,180,238,221,187,139,252,252,252,154, 45,107, 9,252,252, -252,208,189,123,247, 38, 68,111,169,204, 18, 20, 58,111,104, 8,224, 66,165, 10,229, 58, 29, 78,228, 43,177, 55, 81,137,147,197, - 65,200,229,251,160, 88,166, 65, 81, 61,137, 70, 45, 32,215, 82,112, 13,104, 99,147,152,233,245,253, 58,157, 14, 90,173, 22, 1, - 1, 1,240,244,244, 68,231,206,157,161,209,104,140,229,150, 18, 2,153,203,163,215,247,107,181, 90, 40, 20, 10, 80, 20,133,142, - 29, 59,162,164,164, 4,109,219,182, 5,143,199,131, 74,165,130, 90,173, 54,126, 47,147,233,193, 78,157, 58, 65, 32, 16, 32, 51, - 51, 19,197,197,197, 82,157, 78,135,186,186, 58,226,207, 63,255,148, 54, 52, 52,160, 83,167, 78,240,246,246,126,158,233, 24,213, -169, 83, 39,112, 72, 53, 74,178, 82, 81, 91,156, 3, 82,167,129,162,174, 2,133,127, 30,134,186,177,134,150,215,133,137,114, 67, - 35, 32, 32, 64,186,105,211, 38,163, 23,167,170,170,138,184,118,237, 26, 12,164, 77, 2,104,109, 41,225,145, 57,180, 90, 5,180, -154, 6,184,121,180,129,192,205, 31, 18,201, 22,161, 88, 44,214,174, 88,177, 34,192, 68, 30,182,110,221, 10,153, 76, 70, 47, 97, -188, 15, 43, 86,172,160,134, 15, 31, 78, 13, 28, 56,144,250,236,179,207,126,159, 50,101, 10, 38, 77,154, 4, 0,184,120,241, 98, - 93, 82, 82, 18,102,204,152, 49,229,196,137, 19,135,153,212,217,138, 21, 43,168, 17, 35, 70, 80, 47,191,249, 54,198,236, 59,133, -101,255,154,134,119, 62, 88, 8,165,186, 1,183,243,138, 32,145,236,197,111,147,135, 65,216,177,149,195,125, 99,194,132, 9,236, -184,254, 8, 17, 22, 22,214,132,244,205, 3, 1, 31,106, 42,224,232,232,104,161, 61,231, 15,205,210,183,178,102,223,220,218,103, -106,253, 91,147,247, 70, 96, 32,245, 70,224, 63,238,124,243,115, 91,158, 8,103,201,179, 98, 73, 59, 66,212, 15, 12,102, 74,132, -195, 30, 0, 0,216,181,107, 87,218,228,201,147, 69,166,201,105, 44,149, 57,130,144,144, 16, 76,158, 60, 89,180,107,215,174,180, -230,202,172,126,190,123, 8,186,123,112,225, 69, 0, 26,138,194,141, 26, 53, 18,114, 85,216,117,174, 20,127,229, 85,163, 84, 1, - 84, 41,117,200,107,160,112, 87, 69,161, 65,173, 17, 53, 71, 94,244,210, 60,181, 90, 13,133, 66,129,182,109,219,162, 79,159, 62, - 6, 69,207, 31,131, 7, 15, 54, 18, 54, 77,218,214, 8,155, 38,116,141, 70, 3,181, 90, 13,130, 32, 16, 28, 28,140,218,218, 90, - 20, 21, 21,161,186,186, 26, 93,186,116, 1,135,195,129, 90,173,134, 74,165, 50,126,198, 22,130,130,130, 68, 29, 58,116,192,181, -107,215,112,244,232, 81, 28, 58,116, 72,122,232,208,161,147,167, 79,159, 6,151,203,197,115,207, 61,135,110,221,186, 41, 96, 8, -188, 99, 32,111, 74,107,127, 31, 84,229, 95,194,223,199,127,196,181,195,155,112,227,176, 4,119,206,255, 6, 87, 14, 73,203, 43, -177, 37,231,173,183,222, 74,107,221,186,181,200,219,219, 27,217,217,217, 40, 46, 46,150,198,199,199, 11, 77, 21, 1,131, 39,128, -147,144,144,128,222,189,123,219,124, 54,181, 74, 6, 89,109, 46, 92, 92, 60,224,235,223, 67,234,225,217, 30, 63,252,240,139,144, - 32, 56, 67,233,123,188,106, 83, 33,253,239, 59,136,232,209, 96,181,109, 31, 62,124, 24,110,110,110,232,221,187, 55,186,116,233, - 66, 79, 31,104,107,106,106, 26,246,237,219,231, 27, 22, 22, 54,101,207,158, 61, 73, 76,219,110,114,242, 97,120,123,123, 98,212, -232, 33,242,176,129,253, 48,245,205,185,144, 19, 90, 84,148, 87, 99,193,162,207,177,106, 80, 8, 6,182,114, 92, 73,158, 48, 97, - 2,245,245,215, 95,179, 74,192, 99,162, 8, 88,194, 99,179, 23,192,163, 94, 85,224, 8, 1,219,139,237,149,122, 5,194,148,168, -233,178,199, 65,222,227,234, 81, 48,243, 4, 80,246,120, 0,104, 44, 91,182, 44,109,236,216,177,162,193,131, 7, 91, 45, 51,189, -214, 28, 76,239, 31, 59,118,108,147, 96, 63, 75,101,205, 90,135,174, 30,162,190,109, 3, 49, 60,192, 21,207,250,241,209, 78,192, -129, 43, 69, 65,160,210,162,147, 39, 15, 53, 20,133,171, 13, 90,228, 52,106,209,190, 85, 0,186, 60, 59,218,170, 44,218,234,167, -151,250,117,234,212, 9,253,251,247, 71, 77, 77, 13,106,107,107, 81, 91, 91, 11, 47, 47, 47, 12, 29, 58, 20,106,181,218,152, 19, -192, 26, 97,211,202,132, 70,163, 1, 65, 16, 8, 13, 13,133, 66,161, 64, 69, 69, 5,202,203,203, 81, 81, 81,129,198,198, 70,132, -134,134,130,199,227, 25,229, 89,203, 43, 96,174,148,181,110,221, 90, 20, 28, 28,140,219,183,111, 35, 37, 37, 5, 25, 25, 25,112, -119,119,199,152, 49, 99,208,191,127,255,195, 2,129, 96, 41,211,101,123,187,118,237, 74,106,221, 42,232,149,224,182,190,104,200, -251, 19, 57, 41,219, 81,146,241, 59,252, 92,117, 24, 55,118, 12,250,247,239, 63,231,221,119,223, 61,200, 68,150,183,183, 55, 6, - 14, 28, 8,138,162,112,238,220, 57,100,102,102, 74, 75, 74, 74,164, 95,125,245,149, 48, 46, 46, 78, 68,103, 78, 28, 52,104, 16, -210,211,211,109,202,155, 63,127,110,154,172, 38, 87, 84, 93,113, 5,174, 2,127,180,105,247,156, 52,168,205, 96,169,151,119,151, -195,223,172,254,126, 50, 45,111,215,187,238,216,125, 86, 5,107, 74, 79, 78, 78, 14, 2, 3, 3, 49, 98,196, 8,242,217,103,159, -133, 92, 46, 71, 99, 99, 35,214,175, 95,239,217,163, 71,143, 23,165, 82,105,146, 61,125,226,239,191,115,208,185, 83, 7,188,252, -242, 20,247,143,255,189, 24, 85,245, 50, 84, 86, 85, 34,246,157,207,241,249,212,177, 24,219,169,117,139,200,127,237,218,181,232, -211,167, 15,214,173, 91,199, 42, 1, 15, 17,166,243,254,182,240,208, 50, 1, 58,115, 85,129, 33,185,143, 83, 50, 1,218,130,121, - 34, 30,103, 40, 1,206, 36,107,103,203,115,198,171,134, 19,210, 3,155, 41, 16,132, 21,143,133, 93,120,235,173,183,210,204, 63, -103, 90,182,109,219, 54, 70, 50,233,251, 44,221,207, 84, 6,141, 29,187,246,164, 45,127,117, 38,180, 25,201, 40,144, 1,158,132, - 11, 58,123,114, 80,162, 35,192,117,229, 33,189, 92, 7, 37, 9, 4,185,114, 17, 60,104, 20,222, 93,189, 53,173, 57, 5, 64,163, -209,128,203,229,162,107,215,174, 24, 56,112, 32,234,234,234,160, 84, 42,141,235,243,213,106, 53,252,253,253, 49, 98,196, 8, 36, - 37, 37, 25,167, 4, 44, 65,167,211, 25,179, 8,246,236,217, 19, 6, 55, 61,148, 74,165,177, 63,211,158,132,158, 61,123,162,186, -186, 26, 13, 13, 13, 86,251,178, 57,153,159, 62,125, 58, 45, 38, 38,102, 76,239,222,189, 79,154, 36, 2,170, 29, 57,114,228, 73, -129, 64, 48, 91, 44, 22, 43,237,169,203,211,167, 79, 39,196,196,196,212,245,238,221,251,160,137,188,202,145, 35, 71,174,127,247, -221,119, 25,103,235, 89,184,112, 97,218,166, 77,155, 68,145,145,145,184,125,251,182,244,230,205,155, 40, 44, 44,132,151,151,151, -212,215,215, 23, 17, 17, 17,216,182,109, 27, 6, 13, 26,196,248,217,222,120,227,213,180,109,219,118,136,148,202,106,248,250,133, - 74, 61,189, 58,194,203,187, 19, 26,235, 75,146, 86,174,218,142,152,151,199, 97,215,187,238,198,122,178,100,177, 77,156, 56, 17, -201,201,201, 40, 46, 46,230, 84, 87, 87, 67,169, 84, 34, 61, 61,157,103, 80, 58,235,206,158, 61,107, 87,127,136,138,154,136, 3, - 7,146, 80, 87, 91,133,226,210,187,120,247,173,127,169,223,255,112, 5,127,234,152, 97, 24,161,170, 3, 92, 28,163,135, 9, 19, - 38, 80,159,126,250,169, 49, 29,116,112,112, 48,190,254,250,107, 0,160,142, 28, 57,194,166, 13,127, 68, 74,193,163, 84, 0,136, - 25, 51,102,152,186,208, 8, 51,119, 63, 97,175,251,223, 25,228,110, 36,249,202,237,176,149,109,207,158,224,191,202,202,237, 48, -117,197,155, 18,179,185,203,158, 9,105, 87,110,175,116,170,188, 39, 0,255, 83,131, 68,151, 97, 34,209,101,149, 86, 90,113,242, - 4, 92,180, 10, 92,174,167,144, 90,175, 5,159, 32, 16, 64, 81, 16,181,245,133, 95,155, 32, 81,135, 33, 66, 96,199, 30,155, 30, -128, 46, 93,186, 96,240,224,193, 80, 40, 20,208,104, 52,224,243,249, 70,194,166,173,244,160,160, 32, 12, 31, 62, 28, 41, 41, 41, -205,122, 0,120, 60, 30,250,247,239, 15,130, 32, 32,151,203,141,222, 5, 90,105,167,179, 11,146, 36,137,190,125,251,226,143, 63, -254,128, 61,193,149,187,118,237,146, 2, 32, 36, 18, 9, 1,192, 19,250,108,123,133, 98,177, 88,227, 72, 93,238,218,181, 43,201, - 32,207, 19,128, 63,128,106,177, 88,108,119,110,226,133, 11, 23,166, 1,192,134, 13, 27, 68, 46, 46, 46,200,207,207,135,191,191, -191, 20, 0, 74, 74, 74, 48, 97,194, 4,172, 89,179,198, 46,153,243,230,205, 73,147, 72,182, 8,213,106,153,200,173,174, 64,234, -237, 27, 12,119,207,118,112,247,108,135, 99, 39,238,129, 24,219,188,197,253,211, 79, 63, 17,243,231,207,167,170,171,171, 49,113, -226, 68,117, 64, 64, 0,159, 36, 73, 20, 22, 22,218,237, 17, 3,128, 29, 59,126, 34,196,226, 88,202,251,122, 38,222,122,235, 13, -116, 8,237,206,255,122,241, 27,228,142,141, 63,113,214,115,149, 14,181,229, 9, 19, 38, 80,203,151, 47,135,175,175, 47, 74, 75, - 75,225,230,230, 6,146, 36,225,225,225,129, 47,191,252,146, 85, 2, 30, 2,194,194,194,172,122, 1,152,166, 2,118, 58, 30,243, - 85, 5, 68,229,246, 74,139, 23, 28,180,254,137,237,149,247,203, 51,183,212,105,215, 61, 3,210,118,182, 60, 22,143, 17, 12,100, - 67,188, 20, 53, 65,232,163, 85, 73,185,119,242, 17,162,185, 11,175,128,214, 24,214,183, 7, 2,218, 7,138, 62,216,180, 51,109, -119,198, 66,155, 94,180,174, 93,187, 98,196,136, 17,198,249,120, 46,151, 11,149, 74,101, 76,221,107, 58, 77,208,177, 99, 71, 12, - 31, 62, 28,105,105,150,187,158,155,155, 27,194,194,194,192,227,241,160, 86,171,141,159, 51, 93, 58,104,186, 17, 16,135,195,193, -128, 1, 3,144,153,153,105,119, 29, 24,188, 3,245,134,163,197, 48,144,126,139, 55, 37, 48,120,136,140,253,112,211,166, 77, 66, -185, 92, 14,149, 74,133, 30, 61,122, 32, 62, 62, 94,106,223,115,197,166, 1,128, 68,178, 69,164, 80, 84,192,213,213, 15, 46,124, - 47, 41,135,195,195, 47, 9,135, 69,175,204,142,106, 86,222,214,173, 91, 9,137, 68, 66,124,251,237,183,164, 66,161, 0, 0,132, -134,134,218,149,126,217, 20, 18,201, 22, 98,219,182,173, 19,230,126,250,109,178, 94, 30,197, 9, 13,125, 6,161, 47,190,248,202, - 91,111,189,149,224,136,204, 85,171, 86,177,157,250, 49, 81, 2,154, 35,255,135,170, 0, 60,169,112,230,178, 63,115, 98,110, 41, - 81, 59, 81,158,179, 21, 6, 86, 1,113, 0,123, 14, 31, 73,107, 82,119,117,133, 56,125,187,144,241,231,163,163,163,225,231,231, -103,140,240, 39, 73,210,232,194,167, 61, 0,116,208, 31,189, 35, 96,112,112, 48, 8,130,192,238,221,187,239,147,183,118,237, 90, - 36, 38, 38, 26,239,213,233,116, 54,183, 3,230,243,249, 24, 52,104, 16,152, 68,199, 63,193,202, 90,139,219, 58,173, 8,232, 73, -125, 59,244,225, 88,164,148,137, 60,131,178, 68, 0,192,166, 77,155,168,133, 11, 23, 18, 39, 78, 56,190, 52,127,222,188,249, 71, - 12, 94, 19, 14, 73,146, 58, 14,135,227,102,239,244, 11, 13,214,186,127,188,148, 0,155, 3,181,163,251, 8,179, 96,193,130, 5, - 11, 22, 44,158, 92,112,216, 42, 96,193,130, 5, 11, 22, 44, 88, 5,128, 5, 11, 22, 44, 88,176, 96,193, 42, 0, 44, 88,176, 96, -193,130, 5, 11, 86, 1, 96,193,130, 5, 11, 22, 44, 88, 60, 21,104,178, 10,224,210,165, 75, 14, 71,112, 90, 10, 38,100,229,177, -242, 88,121, 79,165, 60,234,133, 23,197,248,253, 55, 9, 36, 18, 9,199, 82,182, 62,182,254, 88,121,157, 58,117, 50,222, 83, 88, - 88, 72,176,245,247,112,229,217,173, 0,208,157,187,153,251, 29,121,192, 39, 89,158, 35, 50, 31,247,223,219, 4, 18,137,132, 15, -192, 27,128,187,161, 61,144, 0, 42, 29, 73,158,242,128, 65, 57,235, 55, 91,169,211, 71,178,124,105,245,234,213,194,115,231,206, - 73, 79,157, 58, 5, 0, 24, 61,122, 52,134, 13, 27,198, 56,149,240,163,120, 15, 47,188, 40,198,196, 9, 3,181,128,152, 39, 22, -139, 73,176,203, 62, 89,152,161, 83,167, 78,212,228,201,193,198,243,164, 36, 80,182,148, 0, 22,143,216, 3, 96,236,225,123,239, -223, 0,130,152, 89,211,146,239, 33, 28, 32,222,135, 38,207,210,239,109,225,111,126,172,127, 47, 77,252,215, 46,159,254,113,239, -174,245, 99,219,180, 15,110, 45,147,105,224,227,227,130,178,146, 60,178,119,239,254,213, 18,137,100,176, 88, 44,190,109,143, 76, -241,156,254, 84,126, 94, 14,242, 10,148, 40,186, 75,161, 99, 91, 2,193, 93, 4,232, 22, 28, 10,201,142,236,199,165,243, 91, 82, - 36,232,189, 6, 30,250, 51, 94,185,114, 69, 26, 22,118, 20,155, 55,203,145,150, 6,124,242,201, 49, 20, 21, 21, 73, 39, 79,158, - 12,129, 64,128,210,210, 82,209,212,169, 83,225, 12,133,224,149, 87, 94,161,100, 50,153, 40, 34, 34, 2,239,188,243, 78,154, 3, -109,134, 35, 22,139, 49,113,194, 64, 50, 54, 54,150, 7,108,193,239,191, 1, 18,137,132, 96,154,179,159,197,255, 14,212,234,229, - 72, 73,137, 69,100,228, 22, 76,158,188, 10, 73, 73,250,190,199, 42, 2, 15, 7,108, 34, 32,123, 24,214,132,236, 9, 2, 32,247, -248, 61,181,191,117,253,186, 53,175, 30, 58,248, 67, 92, 72, 72,247, 30,211, 94, 28,141,142,237,189,225,235,227,138,154, 90, 37, - 74,238,118,228,220,202,175, 9, 60,116,240, 7,233,250,117,107,190,125,123,209,210,117,182,228,189,251,246, 44,225,237,156, 67, -210,242,210,108,188, 20, 5, 12, 15, 7,130, 59, 3,185, 5, 20,206, 92, 80, 32, 89,154,141, 41,227,189,169,174,161,147, 68,223, -173,223,233, 40,145, 57,211,242, 39, 44,200,126, 36, 74, 64,117,117, 53,222,121, 71,142,160, 32, 32, 58, 26, 88,185,178, 1, 89, - 89, 89,208,106,181, 16, 8, 4,104,213,170,149,244,208,161, 67,152, 63,127,190,104,235,214,173,118,213,221,194,133, 11,133, 87, -175, 94, 69,235,214,173,165,251,246,237, 35,126,249,229, 23, 0,144,166,166,166,226,141, 55,222,192,246,237,219,237,253,173,124, - 0, 72, 62,114,145, 3,108, 33,245,127,239,207,241,207,130,181,254, 1, 96,250,244,253, 72, 73,209,255,141,141,205, 3,237, 17, - 96,189, 1, 15,151,248, 77,203,205,149, 0, 54, 8,208,130, 23,224,105, 38,127,137, 68,194, 59,158,178,247, 99,209,168,129, 61, -166, 69,133,162,127,239, 86, 8,240,115, 3, 1, 2,222,158,174, 8, 13,246, 71,196,232, 46, 24, 61, 98, 64,231,227, 41,123, 63, -150, 72, 36,109,108,201,188,157,115, 72, 58, 50,188, 14,123,215, 3,115,163,129, 30, 6,207,159,135, 59,208, 51, 4,248,108, 9, - 48,180,127, 29,110,231, 28,146,182,228, 21,181,212,235, 97, 67,145,120, 36, 3,146,191,191, 63, 14, 29,114, 67, 69, 5,144,152, - 8,212,212,240, 16, 18, 18,130, 73,147, 38,209,219,189, 34, 45, 45, 13,153,153,153,210,213,171, 87, 11,153,202,141,140,140, 20, - 94,187,118, 77,202,231,243,165, 53, 53, 77, 61, 89, 10,133, 2,219,183,111,135, 72, 36,178,183, 62, 73, 0,248,253, 55, 9,146, -143, 92,228,252,254,155,164, 69,191,125,222,188,121, 20,125, 52, 87,198,176, 93, 80, 14,148, 53,139, 45,155, 55, 11,183, 44, 89, - 34,188, 52,127, 62, 85, 52,113, 34,117,126,206, 28,106,195, 59,239, 8,183,108,222, 44,108,201,111,110,105,155,177, 36,131,105, -217,131,150, 71,187,254, 39, 79, 14, 70,108,108, 74,147,191, 52, 38, 79, 14,110, 18, 31,192,226,193, 32, 44, 44,172,201, 97, 73, - 57, 96, 21,128,199,129, 5, 30, 34,174, 93, 62,189, 50, 36, 36, 36,116,240,192,182, 77, 27, 2,135, 0,159,207,133,155,128, 7, - 23, 23, 14,130,187,250, 33, 56, 56,164,213,181,203,167, 15, 73, 36, 18,171,158, 34,241,156,254, 20, 23,117, 88, 50, 23, 80,170, -128,219, 69, 64,141, 12,168,173, 3,118, 30, 4, 22,125, 10,196,173, 6,134, 13, 4, 56, 84, 29,196,115,250,179, 29,223, 4,125, -251,246, 21,253,254,123, 79,180,106, 5,204,154,197, 67,155, 54,207, 98,244,232,209,162, 67,135, 14, 17,147, 38, 77, 18, 69, 70, - 70,162,117,235,214,184,120,241, 34,246,236,217, 35,157, 62,125,186,240,251,239,191,111,150,128, 70,142, 28, 41, 84,169, 84, 82, - 23, 23,151,102,191, 91, 42,149, 98,236,216,177, 76,200,140,154, 61,123, 54, 37, 22,139,213,134,152, 17,152,144, 63, 1, 0,179, -103,207,182, 91, 65,203,200,200, 48, 30,205,149, 57,216,109,137,150,116,239, 45,155, 55, 11,187,221,188, 41,157,122,233,146,180, - 99, 78, 46,248,117,117,104,155,115, 19,194, 63,206, 75,131,178,179,165, 18, 7,149,128,140,140, 12,204,155, 55,143, 90,180,104, -145,195, 74, 4, 45,131, 73, 25, 83,121,230, 68,207,164,204, 22,104,210,167,255,170, 39,135,176, 29,254, 33, 18, 63, 19, 60,169, - 10, 0,101,225,112,154,224, 7,248,124,148,147, 31,147,178,183, 46,174, 93,207,158, 16, 26,236,111, 36,125, 75,219, 52, 11, 92, -121,208,106, 73,132, 6,251,227,218,245,236, 96, 0, 62,214,228,229,231,229, 32,106,140,254,255,163,233,192, 27, 31, 2,155,119, - 2,165,247,128,155,185, 64,214, 53, 10,169,103,129, 19,231,128,200,209,250,251, 91,160,155, 17, 15,240, 21, 63, 18,197,100,217, -178,101,105, 13, 13,250,120,203, 89,179,102,225,252,249,243,132, 68, 34, 73,163,175, 85, 87, 87,139,122,246,228, 97,254,124, 96, -192,128, 11,208,233,110, 74,139,139,139,173,122, 82, 22, 46, 92, 40, 36, 8, 66,202,116,115,152,242,242,114,155, 94,153,217,179, -103, 35, 33, 33, 1, 0,168,244,244,116,181,201,187, 32,104,226, 79, 72, 72,192,236,217,179, 31,229,120,224,104,153, 69,168,174, - 94, 69,215, 63,255, 52,108,130,164,134,150, 36, 65,106,116, 32, 53, 90, 4,157, 78, 71, 29,195,253,214,173, 17,238, 95,127,253, - 37,125,238,185,231, 30,184, 18,224,136,119,161,165,228,175,158, 28, 98,241, 72,137, 77, 97,217,249, 49,131, 69,203,174,153,224, - 55,202, 65,195,153,114,162, 60,226, 49, 24, 92,154,125, 6, 27, 65,133,148, 51,234,207,145,192, 69,137, 68,194, 75, 79, 63,210, -171, 93, 27, 79, 80, 20,112,250,124, 17,228, 10,253,174,171, 3,251,183, 65, 80,128, 27,138, 74,234,201,220,219, 53, 28, 30,143, -131,238,221,252,208,174, 93,136, 47,244, 91,180, 90, 68, 94,129, 18,195,195, 1,149, 6, 56,114, 10,144,158,167,208,174, 53,129, -110,157,128,177, 35,128, 30,193, 4,120, 92,253,214,226, 67,195,128,111, 36, 74,166,245, 77,216,249, 63, 83, 37,130,194,253,177, - 0,212, 35,106, 91, 0, 64,111,231,138,126,253,250,137,204,175,113,185, 92,105,175, 94,229,136,139,211, 63,230,138, 21, 57, 40, - 40,232,109, 85,150, 82,169,180,105,249,155,162,160,160,192,230, 61, 9, 9, 9, 70, 43,159, 86, 4, 76,174,209, 10, 2, 97,184, -246, 56, 56,237,136,150,142, 27,221, 43,171,164,106,141, 6, 28, 14, 7, 20,151, 11,146, 36,161, 33, 73,144, 58, 29,116, 58, 18, - 29,238,222,149,182,164,189,200,229,114, 0,144,206,155, 55, 15, 4, 65,216, 29,223, 97, 74,248,219,182,109, 35,154, 43,123,152, -228, 15, 0, 41,177, 41,136,220, 18,137,233,251,129,216, 20,253,255, 52,249,171, 39,135,128,159,148,203, 50,239, 67,132,169,219, -159,209,118,192,214, 86, 1,180, 96,117,128,181, 40,118, 71,162,219, 41, 27,131,187,195, 74,131, 21, 82, 37, 28,177, 34,154, 9, - 42,116, 68,158,213,207,208,223, 67, 0, 32,247,218,140, 93, 32,245,209,254,174, 0,128,162,210, 58, 40, 20, 90, 0, 64, 72, 55, - 63, 4, 5,184, 33,251, 90, 57,231,239, 91,213, 16, 8,184, 8,238,234,139, 26,153, 26, 0,172, 10, 46,186, 75, 33,184,179,254, -251,159, 31, 5,132,245, 34,224,202, 7,180, 90, 96,252, 72,192,215, 11,200, 47, 4, 34, 71, 1,157, 59,232,239,127,196, 32,204, -188, 39,143, 74,177,124, 32, 40, 47, 47,183,171, 31,214,215, 51,223,125, 55, 33, 33,129, 48, 81, 2, 76,189, 3,143,188,238,186, -117,235, 70,229,231,231, 19,142, 94, 55,135, 75, 94, 46, 84, 26, 53, 8, 46, 15, 58,138, 2, 1, 64,171, 35,161,209,146,160,116, - 58, 16,183,254,118,202,115, 95,189,122, 21,129,129,129,210,175,191,254, 90,244,193, 7, 31, 56,172, 4,152, 79,163,216, 75,220, -206, 34,255,194,194, 66,162, 83,167, 78,212,244,253, 77, 21, 2, 0,136,220, 18, 9,126, 82, 46,146,146,242,140, 43, 1,216, 88, -128, 71, 71,254, 86, 21,128, 39, 0,205,145,168,221, 4,219,194, 37,142,214,229, 62,224,213, 4,196,204, 26,123,191,131,240,241, -113, 65, 77,173, 18,129,254,238,136,158,210, 3, 90, 29, 9, 87, 87, 46,184, 28, 14, 40,138,194,164,241,193,136,138, 8, 6, 65, - 0, 85, 53, 10,248,248,184, 0, 64,181, 53,129, 29,219, 18,200,187, 67,161, 71, 48, 48,230, 57,125,101,223,204, 5,250,245, 0, -252,188,129, 9, 66,128, 36, 1, 30, 23,200,185,173,191, 63,191,136, 98,250,110,237,249,191,165, 3,201, 35, 89, 6,184,105,211, - 38,225,234,213,171,145,151,151,135,244,244,116,233, 55,223,124, 35,242,244,244, 52,110, 59,171,211,233, 68,215,175,183,146,254, -231, 63, 37, 32, 8, 2,229,229,161, 8, 13,237,130,156, 28,203, 83, 41, 36, 73, 90, 44, 31, 59,118,236,253, 94, 36,138,194,201, -147, 39,237,250,205,166, 74,192,227, 68,254,206, 80, 18, 76, 81,221,161, 61,248, 55,255, 6,229, 2,240, 73, 10, 4, 1,104,116, - 90,168, 41, 29,228, 90, 45, 20, 33, 61,128,235, 55, 91,252,236,125,250,244, 1, 65, 16, 14,145, 63, 0, 12, 30, 60, 24,219,182, -109, 35,250,245,235, 71, 53, 87,102, 11,219,182,109, 35,204, 9,223, 82,153, 61,136, 77,249,135,248, 1,220,103,249,211, 1,131, - 73, 73,121, 44, 83, 63, 2,242, 7,216, 32, 64, 83, 18, 49, 63, 90,108, 21, 82, 20,192,121,169,230,129, 61, 52,181,215, 79,255, - 29,204, 21, 24, 94, 89, 73, 94,101, 81,137,222,234, 91,179,233, 47, 92,186, 90, 14,141,134, 4, 73, 82, 6,165,133, 48,198, 6, - 20,149,212,163,172, 36,239, 54, 0,171,102,101,112, 23, 1,206,102,234,255, 15, 12, 7,178,174, 1,177, 49, 64, 72,103,189,219, -255,139,245, 0,223, 5,224,112,128,179,153,250,251, 91, 64,208,206,142,161, 48,127,223, 15,221, 26,185,126,253, 58, 4, 2,125, -157, 28, 62,124, 24, 9, 9, 9,210,180, 52, 61, 23,172, 94,189, 90,232,239,239, 47,189,113, 67,139,173, 91,129,172,172, 65,224, -114,123,136, 58,116,232, 32,178, 38,207,195,195,131,241,119,107,181,218, 39,190,227,154,146,127,183,110,221, 40,107,135,189,202, - 66, 94, 80, 43, 81,141, 90,133, 58,181, 26, 10,181, 6, 42,173, 22, 26, 74, 7,185, 70,131,122,181, 26,165,237,218,137, 90,242, -220,238,238,238,240,240,240, 16,109,219,182,141,112,196,253,111, 74,244,182,202,236, 81, 2, 6, 15, 30,108,179,140,137, 23,192, - 26,249,155, 90,255, 44, 30, 45,249,179, 10,192, 67,192,131, 94, 82, 72,237,245, 3, 5,198,138,134,182,119,239,254,165,185,183, -107, 64,146, 20, 62,124,119, 40,114,114,171,113, 35,167, 10, 4,129, 38, 1,129, 36, 73, 33,247,118, 13,122,247,238,127, 21,128, - 85, 63,113,183,224, 80, 28, 62, 9,232,116, 0,149, 15, 72,207, 3, 73, 39,128, 9,175, 3,162, 89, 64,218, 31,250,251,116, 58, -224,240, 73,253,253,143, 16,150,230,255,225, 12,101,207, 81, 84, 87, 87, 75,123,246,188,141,140, 12,224,252,121, 29, 58,116,184, -140,172,172, 44,233,228,201,147,169, 67,135, 14, 73, 83, 82, 82,112,239,222, 61, 12, 28, 56, 16, 47,189,244,146,104,255,254,253, -105,205, 37,241,161, 40, 74,100,205, 11, 96, 14, 90,241,176, 23,244, 20,192, 35,154,243,111, 2, 83,139, 62, 63, 63,159,176,118, - 88,186,191, 57,248, 13, 24,128,170,145,163, 80,173, 80,162, 70,163,130, 82,171, 69,131, 70, 7,153, 90,141,250, 49, 99, 17, 24, - 30,238,160, 87,144,192,224,193,131,209,183,111, 95,209,249,243,231,211, 90, 34,195,148,232, 45,149,181, 68, 9, 48, 29, 11, 44, -149, 49,129, 37,242,167, 45,127,243, 76,129, 44, 30, 62,249,179, 10,192,147,238,182,152, 89, 99,215, 52,128, 88, 44,214,245,238, - 55,114, 76, 94, 94,238,205, 63, 51, 75, 65,146, 20, 38,140,235,134,203,215,202,241,229,154,243,248,226,219,115, 70,242,255, 51, -179, 20,121,121,185,119,122,247, 27,249,182, 88, 44,214, 88,147, 41,217,145, 77,232,224,141,248, 31,244, 36,191,249, 11,224,191, -191, 2,162,161,192,128, 94, 64,218, 46,125,121,252, 15,128, 14,222, 45,201, 8,216,210, 85, 0,148, 13, 57,143,100, 46,178,177, -177, 17,125,251, 42,241,236,179,192,179,207, 2,131, 6, 81,200,207,207, 71, 82, 82, 18,254,248, 67,175, 61, 9,133, 66,132,135, -135, 51, 74, 15,188,127,255,254, 52, 38,196,174,213,106,225,229,229,101,183, 21,107,136,250, 55, 70,252,211,231,142, 90,176,244, -209, 92,153, 61, 74,128, 51,238, 3, 0,241,194,133,105,234, 33, 67, 68, 55,198, 71,136,202,158,121, 6,101, 46, 46, 40,235,209, - 3, 57,145,145, 34,221,115, 67, 69, 98,195, 20,141,189,120,246,217,103,209, 18,171,223, 84,134,173, 50,166,117,104,201,234,127, -246,217,103,109,150, 57, 2, 58, 71,192, 63, 73,129, 88,143,192,131, 2,147,165,128,108, 38,192, 7,104,153, 63,142,223, 33, 22, -139,171,214,175, 91,179, 54,229,232,158,247,139,239,214, 7,135,116,245, 67,212,248, 96,248,249, 10,240,255,219,187,246,248, 38, -170,109,253, 77,146,166,105,105,121, 83, 94, 90,105,121, 40,130,128,130, 88, 69,165, 81, 16, 99, 27, 64,218,136, 23,245,130,200, -105,229,120, 16,181, 66,208,123,188,162,247,120, 33, 28, 42, 92,185, 30, 72, 21,161,222,115, 84, 76, 11,150,242,176, 90, 78,234, -241, 40,120,160, 10,200, 67, 45, 45, 90,164, 64,161,208,119,210,100, 50,251,254,145, 76,153,166,121,204, 36, 83, 90,112,127,191, -223,252, 50,179,103,102,101,102,246,204,254,214, 90,123,237,181, 47,213,218,241,221,247,231,112,226,228, 37,148,151,159,248,122, -218,131,179,183, 2, 56, 21, 76,102,194,136, 84,237,151,165, 59,172, 95,151,214, 35,229, 62,224,157, 21,238, 76,128,229,191, 0, - 27, 63,118, 91,254, 46,116, 71,194,136, 84, 45, 62,251, 64, 14, 2,151,251,220, 78, 27, 5,112,230,204, 25,109,175, 94,125,173, - 7, 14,156, 7, 0,252,244, 83,119,220,126,251,205,232,211,167, 15, 52, 26, 13,206,156, 57,163, 77, 77, 77,149,148, 10,120,200, -144, 33,218, 31,127,252,209,234,207, 98, 99, 89, 22,195,134, 13,195,198,141, 27, 37,145,144,119,223,191, 96,155,132, 18, 11,224, -203, 90, 13,213,130, 13, 70,238, 82,200, 95,168, 4,180,121, 47, 14, 31, 14,187,190,195,181,208,165, 60, 55,177,255, 37,183,188, - 64,228, 47,132, 67, 63, 12,160,253,255, 87,196, 19,224, 79, 49,144, 52, 12, 48,140, 96, 57,185,199, 94,147, 16,247, 93,145,235, - 11,242,156,100,185,190,112, 2, 23,255,176,232, 5,179,217,108,254,232,232,225, 47,255,178,173,224,139,196, 1,131,135, 38, 9, -230, 2,216, 55,106,212,216,127,165, 78,159,255,114,102,102,102,147, 24,121,158,244,190, 76,230,188,177,100,203,206,159,240,223, -111,251,153, 11, 32,116,242,151,197, 97,210,213,200, 31, 0, 30,125,244, 81, 28, 58,116, 8, 79, 62,121, 0, 0, 48, 97,194, 4, - 60,242,200, 88,237,243,207, 63,223, 74,206, 95,125,245,149, 36,153,235,215,175, 47, 1,192,164,164,164, 36, 55, 52, 52, 88,149, - 74, 37, 20, 10, 5, 88,150,133, 90,173, 70, 76, 76,140, 54, 92,242, 7, 32,139, 18, 64,113,109,162,178,178,146, 41,202, 40, 34, -131, 22, 13,210, 98,136,239, 99,170, 50,138,172,212,250,239, 92,168, 36, 52,148,114, 55,188, 29, 33,143,233,226,215,215, 21,228, -241,158,128, 58,179,217,252,248,168, 49,247,240, 25, 99, 98, 0,244, 5,112, 6,128,205, 51,203,155, 36,120,187,247, 43, 78, 17, - 84,156,178, 1, 95, 30,234,236,231,208,149,242, 74,180,129,135,232, 91,175,225,200,145, 35,178,201,222,185,115,103,137, 92,247, - 39,232,247,103,188,202, 25,120, 18, 1, 81, 80,120, 43, 1,149, 75, 42,209, 85,191,189,107, 21, 98,179, 0, 2, 0, 19,234, 60, -194, 20, 20, 20, 20, 20, 20, 20, 87, 47,104, 16, 32, 5, 5, 5, 5, 5, 5, 85, 0, 40, 40, 40, 40, 40, 40, 40,168, 2, 64, 65, - 65, 65, 65, 65, 65, 65, 21, 0, 10, 10, 10, 10, 10, 10,138,107, 3,109, 70, 1, 28, 60,120, 48,228,168, 76, 95,193,132, 84, 94, -135,201, 11, 58,137, 77,103,202, 51, 24, 12,201, 0,172, 22,139, 69, 22,121,179,103,207, 78,230, 56, 78, 54,121,244,253,235, 28, -121, 11, 23, 46,156,157,153,153,249,113, 71, 94,159,217,108,142, 0,160,241,188,211,118, 0, 28, 0,146,153,153, 73,104,125, 80, -121,191, 37,121,114,121, 0,136,136, 69, 10,228,150,119,197, 64, 46,174, 34,164,113,173,232,235,243, 16,161,108,247, 43,144,135, -236,236,108,109,128,231, 41, 89,222,145,183,187, 35, 92,121, 60,102,222,190,203,154,208,189, 16, 0, 48,126,252,248,176,235,115, - 68,255, 45,184,161,223, 30, 68, 69, 69, 97,202,148, 41,157,253,126,144, 16,150,171, 89, 94,176,255,145,130,189, 29, 85, 41, 57, - 57, 57, 15,189,251,238,187, 47, 70, 68, 68,108, 83,171,213,165,106,181,250, 7, 0,102,165, 82,105, 97, 24,230, 47,102,179,185, -175,217,108,166,195,206, 40, 40,252,121, 0,124,125,228,132,248,255,198, 37,230,134, 38, 30,129,114,201,147,100,193,202,137,244, -244,116,114,226,196,137,160,228,106,177, 88,172, 70,163, 17,113,113,113, 62, 83,174,102,101,101, 89,165,144,181,197, 98,177,102, -103,103,107,179,178,178,172,251,246,237,179,122, 41, 2, 33,201,227,142,253, 39, 20, 55,191,142,247,255,238, 0, 0,112,199,254, -243,178,118,120,243,235,146,158,203,135,127,238, 70, 56, 2,124,244,169, 91,150,110,114, 4, 70, 13, 59, 10,192,173, 4,148,150, -150, 74,170,155, 85,111,107,147,107,127,174, 65,163,163,151,181,169,165, 27,116,211,106, 49,120, 0,131,132,132,185,164,190,222, -142, 45, 91,182,116, 86,131,206,132,248,110, 94, 17,121,129,190, 49, 25,191,185, 80,224, 16,190,127,121,121,121,214, 89,179,102, -105,243,243,243, 75,194, 17,250,238,187,239,234, 84, 42,213,189, 42,149,234, 81,165, 82,217, 75,161, 80,196,152, 76, 38,197,146, - 37, 75,230,187, 92, 46,176,110, 60,234,114,185,244,102,179,249, 43,143, 55,192,225,105,255, 58,188, 27,116,250,244,233, 68,236, -179, 47, 40, 40,144, 84, 33, 51,102,204, 32,225,156, 79,113,237,131,207, 8, 40,117, 58,224,160,228, 63,126,252,120,148,150,150, - 74,106,176, 2, 53, 56, 34,229,181,147,111, 52, 26, 81, 81, 81, 1,143,139, 88,182,105, 93, 73,213,120,130,168, 17, 96,122,125, -200, 0, 0,211,123, 41,147,158,158, 30,180,117, 21,146,117,117,117,181,213, 31,249, 27,141, 70,152, 76, 38, 73,228,239,217, 70, - 82, 82,146, 54, 41, 41, 41, 44,121, 60,217,243,191, 43,255, 11,109,200,127,105,154, 6,171,242,237,162,158,213, 71,107, 99,200, -232, 4, 5,154,108, 4, 47, 60,161,193,190,163, 44,108, 77, 4,205, 14, 64, 59,238, 40,142,254,228,194,248,241,227,137, 88, 37, -192,248,199,155, 72,249,119,245,136,237,174,198,128,129, 49,232,215,127, 24,126, 41,119, 96,200,205, 78, 68,104,170, 81,188,237, - 2, 30,124,240, 65,242,233,167,159,210, 6,239,234, 65,235,244,131, 22,139,197,170,215,235,145,159,159,111,245,245,189,238,223, -191,159,188,246,218,107,216,177, 99, 71,192,250,221,184,113,227,125,106,181,122,180, 90,173, 94,164, 86,171,163, 79,157, 58,133, -225,195,135, 67,169, 84, 34, 54, 54, 22, 39, 78,156, 64, 76, 76,140,106,255,254,253, 61,247,238,221,251,229, 51,207, 60, 51, 4, -192, 47, 0,212,112,119, 15,248,109,248,132,237,159,176,221,226,203, 25,134, 1, 35, 66,131,218,190,125,187, 95, 25,194,114, 41, -138,155,128,240,195, 58,191, 35,177,112,225,194,100, 79, 86, 74,138, 78, 34,253, 80, 61, 0,162,200, 95, 44,140, 70, 99,208, 99, -196, 16,151, 63,242, 95,185,114, 37,150, 45, 91,230,173,116,132, 68, 12,228,192,120,130, 62, 35,192, 36,124,200, 8, 45,254,188, -188, 60, 6, 0,248, 95,127,125, 46,222,100, 29,136,252, 61,158,129,160, 86,187,197, 98,177,122, 91,248,124,153,240, 25, 75,149, - 23,200,194, 95,154, 38,126,166,184,252,181,221,200,240, 27, 20,136,138,100,112,195, 32, 37, 46, 92,226,224,100,149,168,169, 37, -168,107, 36, 56,241, 43, 7, 40,128,190,209,135,249,231, 19,176, 81,120,249, 63,110, 76, 30, 49, 52, 17,123,207,158, 67, 66,124, - 63,140, 30,147, 8,101,100,111,220,144,112, 9,151,108,118, 84,159,117,225,215,115,118, 68,171, 42, 68,201,187, 2, 32, 50, 88, -246,178,203,243,199, 77,157, 72, 20,156,192,250,135, 70,163,209, 2,176,122,215,225,129, 3, 7, 68,145, 63, 0, 68, 68, 68,244, -212,104, 52,243, 46, 92,184, 16, 61, 98,196, 8,220,122,235,173, 80,169, 84,120,235,173,183,224,114,185,112,203, 45,183, 96,235, -214,173,216,191,127, 63, 14, 31, 62, 12,165, 82,249, 23,179,217, 60, 99,253,250,245,129,172,234,214,231, 39,135,199,210,108, 54, -107, 7, 12, 24, 96, 37,132, 4, 60,231,236,217,179,218,204,204, 76, 73, 15,148,151, 29,234,249, 60, 81, 31, 63,126, 60, 96,187, - 49,114,228, 72,173, 84, 50, 63,126,252,184,117,206,156, 57,232,209,163,135,150, 42, 2, 93, 19, 42,127,141, 79, 48, 75,189,171, -160,162,162, 2,203,150, 45, 11, 85,129,240,139,244,244,116,194, 12,202, 99,210,211, 19,136, 37,103, 34,176,249,110,194,196, 60, - 23,244,139,247, 69,214,222,164, 28,168, 91,192, 31,132, 10,197,190,125,251,172, 73, 73, 66,237, 17,236, 0, 0, 26,206, 73, 68, - 65, 84, 73,109, 92,255, 82,229,125,176, 36,198,111,227,246,216,234, 38,209,114,214,175, 95,159, 28,169, 92, 2,133, 2,136,142, - 2,106,235, 57,180, 16,130,110, 81, 12,236, 28, 96,107, 33,184,174,159, 2, 28, 11,148,157,114,161,162,162,194, 26,136,200, 22, - 63, 59, 53, 57,225,134,104,171, 90, 77,240,187,121,119,192,229, 34, 56, 91,237, 64,229,233, 90, 32,226, 20,162,122,181,224, 76, -245,207, 80,168,235,112,236, 88, 45,122,244, 10, 44,239, 10,130,241,241, 29,133,204,180,222, 19, 61,121,230,126,144, 44,239,226, -197, 41,109,182,123,247, 46, 14, 74,108, 18,149, 18, 34, 65, 73,113,241,223, 72,106,106, 42,120,210,183,217,108,173,117,200, 91, -254,133,133,133,162,234, 52, 50, 50,242,174,166,166,166,155, 70,142, 28, 9,173, 86,139,172,172, 44, 60,245,212, 83, 0, 0,167, -211,137,205,155, 55,163,180,180, 20,223,126,251, 45,182,108,217, 2,155,205, 54,140,227, 56, 93, 16,139, 93,214,247,105,231,206, -157,162,186,230, 24,134,145,252, 46, 11,101,135,114,190,231, 27, 46,153, 51,103, 14,170,170,170,124,238, 31, 52,104, 16, 66, 37, -240,170,170, 42, 84, 85, 85, 81, 69,224, 10, 67,232,238, 15,228, 13, 80, 73,181,216,229, 38,218,112,225,113,251,135,110,186,141, - 7,193, 64,128,217,225,254,112,152, 9,165, 76,122,122, 66,107,163,150,151,151,199, 32,103, 34,241,246, 4,136, 37,235,234,234, -234, 54,228, 28, 10, 89,139,133, 64,233,144,165,159, 88,224,254,247,121,240,134, 13, 27,200,249,163,207, 99,224, 8, 37,154,108, -151, 15,177,185, 8,236, 14,192,233, 41,115,178, 4, 68,225, 94,255,254,112, 41, 12, 6, 67,114, 89, 89,153,207,255,140,141,173, -179, 54,217, 20,232,219,187, 39,106, 47, 54,163,182,174, 22,251, 14,156,197,233,115, 4,234,110,205, 24, 60,172, 17,182,230, 11, - 24, 62,198,137, 33, 35, 91,176,229,157, 82, 60,252,240,195,201, 39, 79,158,164, 95,253, 85, 0,222,250,103, 24, 6,169,169,169, - 4, 0,118,236,216, 1,131,193,144,108, 52, 26,173, 82,200,223,108, 54, 71,214,214,214,206,117, 58,157,138,232,232,104,220,123, -239,189, 88,189,122, 53, 34, 34, 34,144,153,153,137,220,220, 92,148,150,150, 98,223,190,125,216,179,103, 15,190,255,254,123,244, -237,219,183, 47,203,178, 55,192,143,251, 95,232, 2, 13,214, 5,160, 80, 40, 68, 93,103, 71,118, 1,108,223,190, 93,150, 46,128, - 30, 61,122,104,171,170,170,172,254,246,133, 91,239, 84, 17,184,122, 60, 0, 87, 19, 24, 63,228, 36, 89, 11, 78, 79, 79, 39,150, -101, 39, 1,165, 26,232, 25, 1,244, 28, 2, 38,207, 35, 76,100,223,127, 7,128, 8,173,126, 0, 16, 90,254, 62, 26, 87, 36, 37, - 37,105, 3, 4, 3, 74,190,135,191,189,216,205,175, 71, 32,182, 62, 11, 63, 59, 8,206, 94,224, 0, 40, 16, 19,237,118,113, 58, - 89, 2,123, 11, 96,119, 0,246, 22,192,225, 4,236, 54,192,209,114,217, 75,226, 43, 32,229,111,111,119, 35,197,251, 26,112,125, - 66, 12, 72,132, 10, 23,108, 54, 88,191, 56,133, 99, 39, 78,227,226,197, 70,140, 26,239, 66,147,157,133,189,197, 5, 91, 51,135, -179,149,128,173, 9,216,182,109,155, 85,202, 4, 24, 20,178,121, 56,164,126,107,132,183,254, 53, 26,141,214, 98,177,148,240, 67, - 70,109, 54,155,117,194,132, 9, 82,100,177, 0,134, 1,224,198,141, 27,199,105, 52, 26, 69,110,110, 46,230,207,159,143, 21, 43, - 86,128, 16,130,111,190,249, 6, 95,124,241, 5, 14, 31, 62,140,186,186, 58, 12, 31, 62, 28,245,245,245,209, 10,133, 34, 46,152, -240,153, 51,103,250, 37, 84,169, 30,148,174,222, 5, 16,200, 11, 16,142,245, 79, 21, 1,170, 0,116, 8, 41, 26, 12, 6,173,160, -207,208, 91, 9, 96,132,214,134,199, 37, 31,146, 75,143, 39,253,188,188, 60,198,146, 51, 17, 80,171,193,228,229, 93,209,155,229, -163,254, 45, 22, 11, 99, 48, 24, 72, 48,111,136,119,108,128, 20, 66,247,133, 64,199,206,125,169, 9,131,250, 43, 48, 71,175,134, -189, 5,232, 17,203, 64,193,120,172,126, 16,216,155,129, 38, 7, 65,147,141,160,201, 78,192, 17, 64, 17, 32,230,122,238,226, 38, -220, 50,182, 2, 3,110,186,136,207,119, 87,227,226, 69, 59,198,221, 89,143, 49,189, 27,129,136, 22,216,155, 57, 84,159, 38,104, -106, 98,192,178, 12,122,247,101, 0,134,163, 95,241, 85,244,237, 10,222,213, 18,225, 47, 15,189, 94,223, 46,254,200, 71, 44, 0, - 95,233,195, 0, 28, 92,186,116,233, 93, 42,149, 42,230,253,247,223,199,166, 77,155,240,228,147, 79, 98,229,202,149, 96, 24, 6, - 63,255,252, 51,108, 54, 27,140, 70, 35, 88,150,197,211, 79, 63,205, 49, 12, 19,244, 3,144, 51,154,190,171,119, 1, 4,242, 2, -200, 97,253, 83, 80, 5, 64, 86,248,232, 71,102, 2, 28, 39,222,196,153,224,142, 80, 79, 79, 31, 76,128, 50, 88,222, 58, 9, 68, -141,104,245, 4,240, 74,129,152,110, 0,185,192, 91,243, 6,131,129, 8,173,127,222, 35, 32,220, 54, 24, 12, 16, 36,203, 33, 82, - 9,221, 27,130, 81, 0, 62,229,177, 46,160,169,153,160,197,225, 14,246,107,113, 16,168, 34, 47,239,179, 55, 3, 54, 39, 65,205, - 69,130,243,151, 8,190, 61,198,130,227, 0,131,193,160, 45, 43, 43,107, 87, 55, 44, 11, 84,157,114,224, 84,249, 37,252,115,239, - 37, 16,194,224,216, 15, 28, 82,231,176, 80,171, 8,206,159, 3,254,249, 25, 80, 95, 79, 64, 56,224,238,251, 24,104, 52,128, 78, - 55, 3,191,252,242,139,168,123,210,221, 9,178,123,111,135,196, 12,200,234, 33,242,244,249,135,141,222,189,139,187,156, 39, 97, -199,142, 29,237,202, 94,125,245, 85,178, 99,199, 14, 20, 22, 22,138,149,163, 0,112, 4,192,193,236,236,236,177, 61,123,246,140, - 1,220,110,240,247,222,123, 15,243,231,207,199,166, 77,155, 90, 45,245,236,236,108,212,214,214,162,190,190,190,177,185,185,185, -194,227, 65, 80, 7,250, 3,142,227,218,196, 67,241, 22, 60, 33, 68,180,251, 31,184, 58,186, 0,124,121, 1,228,182,254,121,153, -212,242,167, 10, 64, 88, 40, 45, 45, 13, 26,253,237,217, 47, 78, 96,100, 55, 88,134,252, 3,120, 59,129, 32,161, 27, 48,180, 5, -204,141,133, 12,222, 26,223,218,247, 31, 78, 55,128,247, 80, 64,127, 67, 3,125, 53,150,124,123,193,147,191,119, 0,160,199,138, -106, 45, 11,226, 1, 96,100, 38, 43,230,238,201,211,147, 79,159,217,109,229,250,113, 80,168,128, 8, 79,187,232,228, 8, 88, 22, -104,104, 32,112, 56, 1,214,233, 86, 10,102,204,116,123,111,252,184,236,153,164, 59,167, 39,183, 92,216,101, 29, 53,138,195,151, - 95,184,192, 40,128,243,103, 25,104,162,128, 47, 62, 5, 28, 54, 6, 12, 1,198,220, 22,129,170, 74, 14,147, 39,167,160,160,160, - 64,212,180,214,186, 59, 65, 86, 61,227,190,127,153,149, 0, 70,102, 5, 64, 22,121,193, 92,206,157, 65,254,190, 10,249,168,127, -225, 49,188,247, 46, 45, 45, 77,155,159,159,239, 79, 94, 35,128,147,223,125,247, 93,227, 61,247,220,211, 15,130, 49,253,239,189, -247, 94, 43, 33, 58,157, 78,184, 92, 46,148,149,149,161, 95,191,126, 23, 56,142, 19,165, 45,206,156, 57,211,159,165, 46,233,166, -175,134, 46, 0, 95, 94, 0, 57,173,127, 74,252,215,160, 2,224, 25,179,127, 69, 91, 24,222,202,181, 88, 44,188,197,203,248, 56, -134,240,228, 47,176,138, 37, 65, 56, 10,128, 47,147,106,249,123, 7, 0,122,208, 90,150,149,149,101,245,116,103,136,146, 39, 36, -127, 95, 49, 1, 82,229, 5,195,170,124, 59,130,201, 43, 40, 40, 40,233,211,147,193,253, 73, 17,224, 0, 56, 29, 28, 34,213,238, -199,212,208, 68,208,226, 36, 96, 93, 64,233, 17, 23, 92, 28, 65,176, 33,123, 5, 5, 5, 37,253,251, 49,152,156,172,196,195,143, - 41,209,216, 64,208, 80, 7, 52, 53, 48, 72, 24, 78,224,114, 50, 80, 41, 52,168,189,200,161,234, 87, 7,202,126, 16, 23, 48,166, -187, 19,100,237, 98, 96, 68, 60,176,238, 5, 96,209,155, 29,162, 4,200,233, 25,144, 69, 94, 7, 14,249, 11,229,217,113,190,200, -127,249,242,229,237,220,252,121,121,121,124,158,128, 18, 63,214, 63,224, 78,230,115,240,198, 27,111, 44,183,219,237,131,149, 74, -165, 38, 58, 58, 26, 0,144,159,159,143,180,180, 52,216,108, 54,216,237,118,180,180,180, 32, 38, 38,198,238,114,185, 10, 8, 33, -103, 69, 90,215,178,188, 31, 87, 75, 23,128,208, 11,192,175, 83,226,167, 10,192, 21, 35,127, 49, 50, 61,132, 79, 60,235, 0, 64, -132,195, 18, 75, 75, 75,219, 16,190, 47, 5,161, 29,148, 12,160, 86, 0, 81, 74, 32, 70, 5,180, 52,192,178, 34, 2, 88,251, 20, - 65, 84,111, 32,170,183,228,190,127, 63,228, 15, 31,100, 45,234,195,240, 38,127,239,152, 0,169,242, 36,144,127, 80,121, 53,181, -132,217, 89,226, 36, 26, 13,192,113,192, 45, 55, 42, 47,215,199,247, 46, 56, 93, 4, 46, 78,137, 89,179,102,137, 82, 78,206,157, - 39,204,238, 79, 93,132,101, 1,135,147,192,197, 2, 10, 6, 72, 78, 1, 26,106, 25,252,112,200, 6,155, 93,129,233,250, 89,216, -186,117,171, 40,242, 95,254, 20, 48,236, 58,247,246,208,193, 64, 7,121, 2, 40, 36, 32, 64,178, 31,146,146,146, 34,102, 52,128, -178,103,207,158, 7,109, 54,219, 95, 43, 42, 42,134,140, 29, 59, 54,145,101, 89, 85, 68, 68, 4, 10, 10, 10, 48,117,234, 84,216, -237,118, 52, 55, 55,163,172,172,172,190, 87,175, 94,127,183,217,108,239,115, 28,215, 4,145, 25, 0,133, 1, 9, 82, 93,255, 2, - 69,162,157,231,160, 43,118, 1, 8,189, 0,114,200, 9, 37,119, 0,197, 85,160, 0,116,134,229,239,195,250, 32, 94,215, 35,151, -149,226,215, 35, 32,214, 3, 32, 55,249,243,202,142,151,123,159, 8,203,164,202, 11, 22, 11, 32, 85, 94,147,157, 48, 77,118, 16, -133, 2,248,103,169,187,175,159, 15,248,115,247,251,207,146, 36,175,161,129, 48,140,194,147,147, 66,225,150,241,175,127, 0, 77, -141, 28, 8, 7, 76,159,158,130,173, 91,183, 6,173, 15,221,157, 32,198,199,129,158, 49, 64,213, 5, 32, 42, 18,224, 8,208, 77, - 3,188,145, 73,149, 0,137, 32, 34,190, 75,209,240, 69,254, 12,195,144,148,148, 20, 0, 64,106,106, 42, 97, 24, 38,144, 34, 16, -227,112, 56, 26, 21, 10, 69,241,160, 65,131,174,107,104,104,120,230,192,129, 3, 3,111,189,245, 86,142,101,217,230,186,186,186, -115,135, 14, 29,250, 57, 33, 33,161,188, 79,159, 62, 21, 54,155, 45,159,101,217,115, 25, 25, 25, 77,227,198,141, 19,165, 0,240, - 73,129,194,129,217,108, 22, 77,168,161,116, 1,132,115,190, 63, 47,128, 28, 47, 11, 37,255,171, 84, 1, 16, 49,214, 95,210,135, - 46, 33,119,128, 20,185,140, 32,202, 63,100,242, 98, 74,193,164, 39, 60, 72,240, 19,128,159,188,247,214,121, 22,105, 99,204, 61, -247,107,149,139, 92,189,158, 11,225,243, 12,120, 2, 4, 25,129, 55, 36, 36,121,127,123,177,155, 80, 41, 8, 69, 94,171,220,180, -180,203,117,194, 7,252, 89, 44,150,146, 80,228, 17,174,109, 29, 55,214, 3, 41, 41, 41,216,185,115, 39,195, 91, 85,162,234,227, -175, 87,156, 8, 59, 85, 94, 23,235,247,111, 99,177, 11, 55,188,201,159,143,219, 17, 6, 9,234,245,250, 64,242, 42, 29, 14, 71, - 36, 33,164,129,227, 56,179,195,225,248, 38, 62, 62,190,111,109,109, 45,243,202, 43,175,212,215,213,213,213, 12, 30, 60,184,161, -177,177,177,201,225,112,212, 59,157,206,150, 5, 11, 22,216, 36, 90,216, 97, 63,204,204,204,204, 14, 35,194,142,148, 77,241,219, - 84, 0,228,110, 61, 58,172, 53,242,144, 40,227,203, 90,150, 2,153,163,250,197,100, 11, 12,235, 15,164, 76,250, 35,135, 55, 32, -132, 58,241,187, 29,174,188,157, 59,119, 74,170,171, 14,176,238,127,107,242,228,148,205, 0, 64, 78, 78, 14, 81, 40, 20,224, 23, -161, 11, 91,167,211,129,227, 56,112, 28,135,140,140, 12, 38,200,168, 0,134,101,217,104, 66,136,139,227,184, 22,167,211,249, 15, -165, 82,201, 40, 20,138, 72, 0,145, 28,199,193,229,114, 41, 89,150, 85,179, 44, 59,112,193,130, 5,199, 5,231,118,248, 36, 64, - 20, 20, 93, 1,129,114,164, 48,161,206, 35, 76, 65, 65, 65,209, 5,208, 44, 32,116, 78, 96,216,168, 4,229,103, 0,244, 0,160, -161,196, 79, 65, 17,216, 3, 64, 65, 65, 65,113,181, 64,227, 81, 2, 56, 1,241, 43,112,121,230, 65, 21,128,129,158,117,154, 53, -138,130,130, 42, 0, 20, 20, 20,215, 8, 20, 0, 98, 4,219, 60,241,171, 5,164,207,121,142,163,214, 63, 5, 5, 85, 0, 40, 40, - 40,126, 35,109, 26, 37,125, 10,138, 0,218, 51, 5, 5, 5, 5, 5, 5,197,111, 89, 91, 62,120,240,160,112, 34, 29,226,149, 68, -135,160,237, 68, 59,149, 22,139, 37,158,223,246, 21, 76, 40,148, 39, 21,215,162, 60, 31,195, 22, 25,250,252,104,125, 92, 45,242, -226,227,227, 91,143,169,172,172,100,164,202, 91,184,112, 33, 50, 51, 51, 25,250,254,133, 38,147,126,191, 84,158, 20,121,146, 21, - 0,137,232, 39,242, 56, 98, 48, 24, 36,103,150,242, 55, 95, 60,218,143,153,246, 53, 27,160,175, 99,174, 56,120,130,241,140,133, -183, 90, 44,150,214,108, 93, 93,101,172,182, 94,175, 79, 46, 44, 44,108, 37,193,148,148, 20,237,206,157, 59, 75,174, 69,109,215, - 87,125, 28, 63,238, 30, 25, 54,114,228,200,206,190, 60, 50, 99,102, 38, 10, 62, 49,251,124,103,103,204,204, 36,158,125,126, 95, -156, 25, 51, 51, 3, 54, 2, 5,159,152, 67,126,233,226,227,227,137, 94, 63,180,117,187,176, 16, 36,152, 18, 16, 12,171,179, 87, - 39,111,255,108, 59, 18, 71, 37, 90,193, 0,199,191, 59,166,189,115,220, 93, 88,251,230, 90, 73,239,223,220,185,115,219,221,119, -110,110, 46, 77,238, 68, 65,209,129, 10,128, 90,236,129, 73, 73, 73,146,133, 7, 80, 0,124,146,168,247, 68, 27, 18,136, 54, 20, -205, 73, 76,227, 66, 44, 22, 11,140, 70, 35, 76, 38,147, 53, 64,154, 78, 49,255,223,230,152,193, 9,215, 3, 0,206,217,237, 96, -109, 45,238,194,218,122,158,228,196,165, 63,110,109,200, 11,219,228, 20,240,228, 22,151, 52,199,187,130,113,103,215,227,127,129, -160,235,157,209, 56,183,169, 15,158,248,195,168, 15, 57,239,129,204,152,153,137,135,116,183,217,129, 76,141,135,232, 67,250, 15, -129, 2, 33, 59, 28, 14, 35,138,138, 50, 48,109, 90, 14,244,122, 19, 10, 11,221,207, 42, 20, 69,224,137,103,159, 32,181,189, 47, - 98,141,121, 53,122, 69,247, 2,199,186, 96, 39, 45,214, 79,191,249,108,218,108,215, 35,228,174,196, 73,218,197,139, 23, 7, 85, - 4,230,206,157, 75, 22, 46, 92,232,243,153, 82, 37,128,226,183,140,131, 7, 15,122,123, 9,218, 29, 19, 78, 12,128,164,115,189, -167,175,149, 11, 27,204,230,228,176, 91, 95, 66, 68, 47, 98, 69, 26,141, 70, 16, 66,176,114,229,202, 64,231, 17,201,249,187,123, -118,199,225,138,143, 80, 86,241, 79, 92,170,250, 31,148,255, 57, 3, 91,159, 78,235,212, 23,237,240,247, 71, 90, 73,254,200, 17, -247, 58,112,121, 93, 88,206, 17,209,117, 34, 10, 82,234,227,248,241,227,152, 55,111, 30, 2,146,191, 8,133,241,254,251,119,135, -170, 56,250,197, 67,186,219,154, 51, 50, 50, 52, 15,233,110, 11,153,216, 61, 22,126,160, 37,100,235, 31, 0,210,210,220,179,242, -165,165,229,163,176,176, 28,122,253, 80,232,245, 67,219,116, 13, 4,253, 94, 55,108, 72,158,253,252, 35,228,119,127,152,143,151, -103, 46,197,109,241,183, 99, 72,247, 33, 24,210,107, 8, 70,197,221,130, 63, 76,249,125,209, 75, 47, 44,195,222,234,175,173,107, -214,172, 17,245,109, 95,184,112,161,205,114,199, 72, 27, 54, 47,254, 10,179,103,207, 38,194, 37,156,250,209,233,116,178,214,183, -220,242, 58, 18, 11, 23, 46, 76,150, 67,134, 12,114,250, 0, 24, 15,224, 37, 0,107, 1, 20, 1, 48, 1,248, 47,207,114, 19,165, -125,223,228,239,175,172,141, 7,192,104, 52,146,138,138, 10, 0, 64, 98, 98, 34,132,147,205, 88, 44,150, 54,219,222,251, 3, 89, -236,213,213,213, 86,139,197, 34,218, 19, 16, 76, 89, 16, 90,245, 79,123, 82, 97,122, 91,250, 82, 93,236, 57, 57, 57, 65,143, 41, - 46, 22, 53,183, 58, 49, 24, 12, 88,185,114,165,207,157,203,150, 45,131,201,100,130,209,104,244,123,140, 47, 12, 78,184, 30,167, - 47,213, 97,235,211,105,232,195, 76, 66,249, 59, 47, 34,241,225, 68,124, 94, 94,131, 89, 43, 55,117,234,203, 54,230,150,209,173, -235,163, 71,143,110, 83,206,123, 6,132,229,114, 91,246, 65,200,141, 24, 12, 6,204,155, 55,207,231,206,205,155, 55,195,100, 50, - 65, 55,233, 86,236,254,234, 59, 32,182, 27, 80,223,120,197,159,225,174,221,223, 70, 3, 57,216,181,251, 91, 89,228,157,251,115, -159,128, 4,211,127, 73,141,168, 15, 68,232,250,207,200, 40,130, 94, 63,180,245,151,135, 94, 63, 84,116,151,192, 59, 31,190,131, - 21,111,255, 9,247, 12, 79,134,171,165, 5,172,139, 5,163, 98, 0, 40, 65,192,225,220,249, 42,140,236,119, 19, 94,126,250,101, -252,105,213,159, 68,121,163,188, 27,182,148, 65,155, 1, 0, 91,182,108,105,115,238,236,217,179,137,119,153, 88,178,222,245,202, -110, 60, 4, 29,217,189,123,119,216, 94, 5,157, 78, 71, 86,173, 90, 5, 0,178,200,235, 72,226,175,171,171,227,189,101, 97, 93, -103, 93, 93, 29,223,166,135, 42, 39, 6,192,191, 1,248, 14,192,251, 0,166, 2,120, 16,192,239,225,158, 21, 18, 0, 46, 80,234, -111,139, 12,163,155, 99,114, 76,203,130, 91,241, 38,147,137,177, 88, 44,140,197, 98, 97, 42, 42, 42,192,175,243, 46,101,225,182, -175,253,254,192, 43, 21, 89, 89, 89,214,234,234,106,171, 47, 5, 65,184, 29, 36, 85,174, 47,171, 38,208,246, 21,255,192, 62,254, -248, 99,159,196,207, 48, 76, 59,242, 95,182,108,153, 40,153,191, 86, 84,162,241,189,197,152,181, 33, 31,131, 19,174, 71,255, 62, - 81,168,216, 86,225, 38,255,158,221,221, 7, 69, 40, 37, 95,171, 94,175,215, 6,218, 22, 3,142, 0,215, 69, 3,219, 51,129,184, - 72, 96, 84,175,203,110,255,248,110,192, 39, 25,151,203,165,130, 97, 24,159,139, 20,188,254,250,235, 62,137,127,228,200,145, 48, -153, 76, 88, 53, 47, 21, 71,202, 79, 97, 64,226, 64,160,169, 89,140,245, 15,145, 94, 0,209, 86, 94,193, 39,102,236,218,253,173, - 79, 75, 95,208,183, 47,233,198, 87,125, 64,252, 46,161,128, 39,125,254,215,161, 31, 38,233,252,102, 91, 51, 38,205,190,203,154, - 52,240, 14,180, 52, 53, 1, 74, 37, 84, 42, 21,148, 74, 37,148, 74, 21, 78,158, 60,137,173,219, 10, 78,219,157,205, 24, 18, 25, -143, 91, 39,143,155, 50,255,119,243, 37, 91,141,111,236,154,135, 7,140, 9,237,202,183,108,217,194, 72,245, 4,240,228,143, 33, -107,176,235,149,221, 97, 91,238, 58,157,142,172, 93,187, 22,163, 71,143,198,186,117,235,186,164, 39, 96,225,194,133,201,115,230, -204, 33,199,143, 31,183, 86, 85, 85,201, 34,175,170,170, 10, 85, 85, 85,225,120, 19,180, 0, 38, 3, 56, 4,224, 52,128, 1, 0, -126, 4,240, 11,128, 83,158,197, 6,138, 86,133,152, 39,127,225,186,183,178,124, 69,242, 0, 8,250, 94, 81, 81, 81,129,184,184, -184,118, 10, 2, 95,230, 75, 65, 16,217,184,134, 28,252,247,200, 35,143,116,216,189, 11,201,202,151,213,239,153, 56,136, 9, 70, - 22, 54, 84,162,241,225, 59, 64, 98, 95, 4,166,188,130, 70,124, 8,188,235,182, 22,137,229, 69, 68,252,251, 58,176,172,244, 68, -103,133,133,133, 37,194,231, 20, 36,247,186,111, 15,207,123,192,107, 27,128,235,175, 3,206,237, 80, 35,119,163, 3,243, 62,242, - 95, 46,201,188,151,121, 62,123, 97,176,223,153, 79, 86, 34,118,148, 6, 49,195,159,195,199, 43, 23, 96,236,232, 1,184, 49,245, - 79,162,234, 67,204,165,223,127,255,110,236,217,163, 19,211,151,207, 0, 32, 94,228,207,240,129,127,161,244,235,139,181,240,197, -192, 31,209, 23,121,121, 2,130,225, 76,245, 25, 60, 96,120, 0,177,221,123,193,197,176,248,242,139,127,160,161,177, 17,250,233, -211,113,190,186, 26,121,249, 91,241,212,147,243, 6, 71,106, 34,161, 32, 17,152,118,219,180,226, 31,173,235, 66,178, 26, 47, 93, -186, 20,246,125, 11,201, 31,128, 71, 9,120, 62,100, 79,128, 78,167, 35,203,151, 47,199,176, 97,238,231, 57,116,232, 80,116, 37, - 79,128,151,197, 47, 27, 4,214, 63,191, 30,202,189,222,236,249, 38, 35, 0, 68, 3, 24, 5,224, 24,128,193, 0,234, 1,212, 66, -254, 73,186,174,121, 92,177, 68, 64,113,113,113, 90,131,193,208,174, 43,192, 51,183, 61, 0,180,206,119, 47,149, 28, 66, 12,254, - 19,235,113, 8, 25,188,117,239,207,221, 47,214,250, 7,128, 79, 95, 90, 14,253,138, 55,193, 78,153, 4, 21,128,152,189, 39,240, -121,121, 13, 0,128,157,178, 8,206,239,251,130,233,247,123,201, 36, 21,128,144, 68,163,102,230,135, 88,244,228, 41,252,244,244, - 82, 52,237,113, 96, 64,223,192,229,161, 42, 80,225, 42, 7,155, 55,111,118,107,195,250,123,177,175,170, 26,177, 99, 99,113,186, -168, 28,208, 68, 34,109,209,191,163,247,117,169,157,249, 45,250,139,250, 15,169, 78, 2,120, 17,124,121, 31, 2,202, 46,202, 40, -194,180,156,105, 72,203, 7, 50,138,220,235, 69, 25, 69,173,202,129,186,240,132,168,107,104,180, 55,160,111, 84, 31,176,246,102, - 16, 5,193,237, 19, 39, 98,219,182,109,246,181,111,190,169,225, 8,193, 99,143, 63,134,222,125,122,163,185,177, 17,172,139, 69, -108, 68,119, 56, 21,206,144,238,183,182,182,182,205,232, 0,169, 1,129,237,200,159, 71,136, 74,128, 78,167, 35, 70,163, 17, 19, - 39, 78,108, 83, 62,122,244,104,188,241,198, 27,157,170, 4,116, 20,241,243,178,133,114,121, 47, 64, 8, 83, 5,127, 3,224,160, -135,236, 31, 4,240, 0,128, 50, 0, 99, 0, 20, 0,216, 4,192, 9,138,176, 20, 0,226, 69,138, 68,226,254,128, 72, 76, 76,108, - 37,253,164,164, 36, 45, 31, 27,192,123, 7, 18, 19, 19,173,124,119, 65,103, 53,188,114, 34, 88, 95,191,192,250, 15,138, 89, 27, -242, 65,166, 39,224,220,157,183,161, 15, 38, 33, 42,109, 29,216, 51,231,129,158,221,161,170,249, 16, 59,214,150, 2, 74,101, 40, -247, 30,182,214,124,232,133,127,195,132,113, 64,226,162, 35, 24, 21,243, 36,126,188,193, 0,252,239, 82,191,229,157,229, 1, 48, -153, 76,184,231,246, 27, 49,101,210, 8,232,111, 89,138,236,181,235,113,172,244, 52,158,190,111, 2,206, 22,236, 66,221,165,122, -185,222,135, 54, 93, 5, 30, 47, 64, 80,130, 22, 18,190,156,228,239, 71,166, 40, 84, 86, 86, 50,241,241,241,196, 19,255,215,170, - 16, 0,192,180,156,105, 80, 23,158, 64, 97, 97,121,235, 72,128,192, 1,129, 12, 56,142,131,139, 3, 8,199, 34, 50, 74,131,199, -159,120, 66,243,218,171,175,162,127,255,254,220,224, 1, 3, 20,246,166, 70,184, 8, 64, 56, 23, 56, 46,184, 71, 43, 55, 55,151, -153, 58,117, 42,169,169,169, 65,125,125,125, 27,197,209,107,116,128,232, 81, 1, 58,157,142,100, 47, 56, 10,104,134, 1,103,223, -110,127,128,102, 24,178, 23, 28, 5, 68, 42, 1, 58,157,142,204,152, 49, 67, 59,122,244,104,107, 77, 77, 77,187,253,241,241,241, -152, 49, 99,134, 22, 93, 60, 38, 32, 92,235, 63, 76, 47,128, 80, 97, 24, 8,119, 87,192,195, 0,154, 64, 33,155, 2, 32, 37, 17, -144,175,253, 62, 97, 48, 24,124,122, 1,120,178,143,139,139,211, 26,141, 70,171,135, 16, 97, 48, 24, 2, 6, 21, 6,178, 14, 67, - 24, 95,223, 33,195, 0,121,235, 62, 80, 48,160, 20,148,255, 57, 3, 17,105,235, 96,171,250, 9,170,189,235,224,204, 95, 4,230, -161,213,216,254,251,116,252,178,253, 36,244,171,222, 7, 84,157,147,217,121,169, 5, 40, 90,181, 13,163,126,153, 6, 92,104,194, -146,169, 75, 3,150,203,225, 1, 8,213,250, 47,216,182, 28,202,193, 55, 35, 6, 35, 80,249, 69, 14, 26, 24,130,127,253,116, 10, - 83,142,156, 22,117, 57,123,246,232,252,146, 61, 0,120,246,251, 60, 78, 44,249,251,121, 71,195, 34,134,112,114, 0,240,200, 40, -186, 76,252, 0,218, 89,254,124,192, 96, 97, 97,185,207,243, 99,163, 98, 81, 85, 87,133,137, 67,238,128,173,197, 14,216,236, 96, - 29, 78,188,108, 52,130, 81, 64,209,220,212, 8,142,115,129,117, 17, 68,170, 34,112,190,241, 60, 34, 92,193, 71, 27,127,254,249, -231,173,247, 54,119,238, 92,194,183, 55, 23, 46, 92,142, 9, 59,115,230,140,232,251,116,147,176, 91, 9, 24,153,208,254,255,143, -159,116, 32,235,221, 81, 16, 75,214,158,227,200,196,137, 19, 17, 31, 31,223,110,255,145, 35, 71, 80, 80, 80, 96,237, 44,242,247, - 88,227, 12,239, 9,144,163,223,223,151,245, 47,131, 23,128,199, 3, 30,133,160,133, 82,184,188, 10, 64,135,128,183,252, 1, 32, - 41, 41, 73,107,177, 88,172,188,235,223,143,114,160, 45, 43, 43, 11, 22, 11,192,200,101,205, 75, 33, 19,177, 10, 6,111,253,251, - 34,126, 94,209,145,114,189,135,202,107,224,252,254, 53,156,195, 87, 24,240,208,106,160,174, 30,229, 57, 47, 98,232,194, 53, 56, -187,233, 69, 32, 66, 5, 40, 58, 39,179,115,101, 19, 48, 50,238, 97,209,229,157,225, 1, 48,153, 76,141,179,167,220,113,166, 7, -215,235,250,102, 68,104,242,215, 44,194, 95,118, 28,196,146, 7,239,198,188, 55, 63, 64,250,127,255, 95,135,122,131, 2,221, 98, -193, 39,102,120,146, 0, 49,225, 42,167,225,184,250, 3,121, 1, 50,138,138,136, 47,242, 23, 90,255,193, 48, 40,110, 16, 62,253, -178, 8,119, 93,127, 23,162,187,197,128,227, 8, 20,132, 5,199, 48, 32,132,192, 69, 0,150, 35, 96, 89, 22,182,186, 38,236,220, -191, 19,106,151, 90,114, 80,170,119,160,211,127, 44,154,132,148, 65, 21, 96, 62, 19, 47,195,159, 18, 32,149,252,189,149,128, 85, -171, 86, 97,224,192,129,151, 21,251,242,114,152, 76, 38,116, 5,203, 95,110, 69,192,151,245, 31,166, 23, 0, 0,146, 1,220, 0, -224,143,184, 60,241, 19, 69, 87, 86, 0,226,226,226,180,222, 30, 1,190,223, 93,168, 28, 8,215,195,180,224, 37,191, 88, 50, 14, - 3,244,105,253,135, 74,252, 60,102,173,220,132,173, 0, 30, 92,145, 2, 98,121, 17,204, 35,217, 56, 84, 94, 3,166,119, 47,156, -248,181,222,109,253, 75,239, 2,144, 5, 71,142, 28,105, 29,242, 39,102, 93, 14, 15,128, 20,229, 96,243,230,205, 14, 0, 13, 11, -146,199,212, 63,183,250,127, 28, 47,189,108,180,247,235, 30, 87,115,244, 88,101,255,121,199, 62,136,233, 36,226, 23, 67,206,194, - 46, 26,209, 94,128,142, 74, 6,228,139,252,121,203, 31, 64,208,128,192,197,139, 23, 51,119,221,127,215,116,235,164,146, 2,195, - 45,233,168,183,215,131, 81, 0,238,193, 72, 28, 92, 46, 2,142,101,209, 45, 50, 22, 95,215,125,135,178,189, 39,144,103,206, 43, - 9,251,194,203,127, 7, 64,250, 48,192, 54, 74,192,192, 74, 28, 63, 19, 31, 18,249,123, 43, 1,235,214,173, 67,207,158, 61, 81, - 83, 83,131,229,203,151,163,171,185,253,229, 80, 4,252, 89,255, 33,122, 1,250,195, 29,245,175, 0,112, 43,128, 44, 0,229,148, -190,101, 86, 0, 58, 42, 15,128, 63,143, 64,118,118,182,214, 91, 81, 48, 24, 12,146, 19, 6, 9,137,160, 43,164,216, 21, 90,255, - 66,226, 55, 26,141,124,183,135,240,185,138,190, 96, 94, 9,120,120,197,123, 32,249, 64,223,121,102,148, 60,151,142,187, 77,127, - 3, 34, 34,208, 77,163,238,148,251, 21,142,241,247,181, 30, 98, 30, 0, 22,128,194, 83,183,138, 48,235,227,220,236, 41,119, 84, - 61,151, 83,152,240,242, 83, 15,116, 31, 52, 32,217, 1,224,176,193, 96,232, 1,247,248,226,144,234,131,127,229,246,236,209,241, - 17,255,161, 40,119, 76, 48, 11, 94, 10,161,203,225,234,151, 2,111,210,231, 61, 2,189,123,247,246,169,157,125,189,231,235,237, -241, 55, 93, 15,215,108,246,240,228,235, 39,143,233, 19,219, 7,118,167, 29,132, 16,168, 85,106,212,218,154,177,239,215, 61,216, -252,215, 92,104,111,214,106,243,144, 23,246, 53,190,177,107, 30,114,115,115, 81, 86, 38, 61, 7,192,101, 37, 0, 97,145,191, 80, -222,162, 69,139,200,170, 85,171,176,116,233, 82,116,229, 62,127,161, 34, 80, 82, 82, 18,210,185,129,142,145, 32,115, 6,220,227, -253,237, 0, 94, 0,176, 31,128,139,210,183,111,140, 27, 55, 14, 7, 15, 30, 68,142,105, 89,187, 60, 0,222,217, 0, 85, 94, 13, -101,192, 62,126,225,182,247,126, 41,147, 17, 4, 34,250, 16,189, 0, 97,161,163,134, 1,242,202,136,217,108, 70,113,113, 49, 87, - 81, 81, 33, 36, 50,173,197, 98,145,108,221,204, 90,185, 9, 16, 36,254,153,252,242,134,214,245, 78,138,134, 9,218,128,113, 36, -164,103,183, 22,192, 69,184,135,255, 60, 30,230, 53,158, 93,144, 60,166,101,106,241, 55,221, 31,123,245,125,152,205,102,117,113, -113,241, 64,180, 77,103, 29, 82,125,116,180, 39, 32, 88,126,255,160, 45,103, 7,116, 9,248, 35,127,135,126, 24, 80, 24,220, 48, -251,232,237, 45, 76, 55,101, 12,217, 27,191, 15,147,238,152,132,193,177,131, 1,142,224,188,189, 6, 95,127,251, 53,206, 30, 61, -139,251, 70,222,167,125,246,217,103, 59,189, 62,132, 74,128, 92,100,205,123, 2,174,150,128,191, 48,250,234,229, 66,142,103,161, -144,250,224, 76,203,196,123, 0, 58, 10, 89, 89, 89, 62,201,222,107, 38, 54, 33,172,190,242, 22, 7, 35,218, 80,209, 17,195, 0, - 77, 38, 19,204,102, 51, 91, 92, 92,172,242,116, 29,240,228,127, 95,128,251,246, 9,207,100, 74, 29,145, 74,153, 4, 40,239,148, -198,201,108, 54, 71,122,222,203, 87, 60, 69,174,204,204,204, 39,194, 20, 27, 57,245,143,239,148,154,205,230,123,139,139,139, 81, - 92, 92,108, 7,160,241, 44,114, 16, 63, 35,114,188,191,100,146,246,236,111, 83, 95, 82,137, 91,142, 46,129,202,202, 74,166, 40, -163,136, 12, 90, 52, 72,139, 33,190,143,169,202, 40,178,138,141, 7,216,248,214, 70,102,205,154, 53,201,155, 86,108, 66,252,176, - 27,172, 0,240,227,145, 31,180,169, 83,245, 88,187,126,109,201, 71,248, 40,164,235,204,205,205,101, 30,120,224,129,118,163, 2, -156,206,240, 70,136,201, 77,214,215, 90,180, 63, 69,215,244, 2,120,151,137, 86, 0,130, 89,226, 18, 44,245, 80, 95,116,210,193, -242,229, 58,223,167, 60,131,193, 64,138,139,139, 85,194,231, 37,244,176, 72, 84, 80, 74, 58,136,144,187, 98, 35, 20, 11,160, 17, - 32, 4,238,196,252, 81, 8,111,124, 47, 95, 31, 63, 23, 23, 23,243,227,202,234, 19, 19, 19,251,153, 76,166,200,174,240, 44, 59, -210,109, 47,167,236,202,202, 74,166,114, 73,165,108,207,224,249,231,159, 47,241, 62,239,235,191,239, 13,251, 58, 63,251,236, 51, - 74,174, 20, 84, 9, 16, 97, 68, 51,161,206, 35, 76, 65, 65, 65, 65, 65, 65,113,245, 66, 65, 31, 1, 5, 5, 5, 5, 5, 5, 85, - 0, 40, 40, 40, 40, 40, 40, 40,126, 3,248,127, 37, 93,196,116, 64, 61,103,188, 0, 0, 0, 0, 73, 69, 78, 68,174, 66, 96,130, + 0, 0, 4,115, 66, 73, 84, 8, 8, 8, 8,124, 8,100,136, 0, 0, 0, 9,112, 72, 89,115, 0, 0, 13,215, 0, 0, 13,215, 1, + 66, 40,155,120, 0, 0, 0, 25,116, 69, 88,116, 83,111,102,116,119, 97,114,101, 0,119,119,119, 46,105,110,107,115, 99, 97,112, +101, 46,111,114,103,155,238, 60, 26, 0, 0, 32, 0, 73, 68, 65, 84,120,156,236,157,119,120, 20, 85,247,199,191,103,218,206,182, +244, 78, 9,157,208, 91, 64,164, 35,210, 4, 81,169,130, 72,243,149, 87, 5, 20,105, 74, 81, 64,154,136,250,170,168, 40,160, 2, +210, 4, 11, 69, 68,154, 20, 81,106,232, 73, 40,161,132,150, 66, 72,219, 94,239,239,143,221,141, 1,147,236,110,192,246,115, 63, +207, 51,207,110,102,103,191,115,118,179, 51,231,220,115,207,189,151, 24, 99, 8, 16, 32, 64,128, 0, 1, 2,252,187,224,254,106, + 3, 2, 4, 8, 16, 32, 64,128, 0,127, 62,129, 0, 32, 64,128, 0, 1, 2, 4,248, 23, 18, 8, 0, 2, 4, 8, 16, 32, 64,128, +127, 33,129, 0, 32, 64,128, 0, 1, 2, 4,248, 23, 18, 8, 0, 2, 4, 8, 16,224, 79,134,136, 2,247,222, 0,127, 57, 62,253, + 8,137, 72, 8,147,233, 17, 34, 82,221,175, 19,255,157, 47, 0, 34,234, 70, 68,123,220, 91,183,191,218,158, 0,165, 67,110,254, +106, 59,254, 46, 72,178,156, 73, 68,172,180, 77,169, 84,102,254,213, 54,254,219, 17, 69,113, 65,215,174, 93,141,178, 44,191, 87, +158,247, 19, 81,227,136,136,136,205,193,193,193,153,106,181, 58, 63, 50, 50,114, 47, 17, 61, 94, 94,123,254,238,122, 1,254, 56, +200,151, 97,128, 81, 42,106,211, 52, 38, 44,225, 68, 86, 65,102,166,193,254,125,185, 79, 70,212, 90,146,184,110,156, 72,149,136, + 40,159,217,113,203,102, 99,103, 28, 14, 71, 18, 99,236,186,175, 58,178, 58,180,151,221, 98,244, 57, 24,225, 85, 33,102, 75, 97, +214, 6, 63,236,252,245,243,159,217,131, 78, 6,252,167, 29, 29, 96,140,181,242,245,189,127, 6, 68, 36, 72,146, 52, 69, 20,197, +103,236,118,123,168,197, 98,121,132, 49,182,255,175,182,203, 3, 17,213,141,142,142,126, 14, 0,178,178,178, 62, 97,140,165,252, + 65,231, 81,191,250,116, 66, 87,187, 3,214,183, 87,159,221,194,238,113, 76, 43, 17,201, 0, 98, 1, 92,103,140,217,124, 56, 62, + 52, 56, 56,120,110, 65, 65,193, 43,140,177,194,123, 57,247, 93,186, 97, 49, 49, 49, 13,156, 78,103, 69,158,231,175,101,100,100, +156, 97,140,229,250,248, 94,246,237,254,100, 40, 68, 30,146,192, 67, 18,133, 59,158,215,175, 18, 13,198,152, 79, 1,147, 44,203, +153, 22,139, 37,218, 31,219,149, 74,101,150,209,104,140, 41,197,182, 76, 0,126,233,113, 28,151,229,112, 56,254, 20,189, 18,244, + 9, 64, 71, 89,150,159,181,219,237,157, 4, 65,216,101, 54,155,151, 0,216, 93,222,223, 26, 17,133, 12, 30, 60, 56,111,197,138, + 21, 24, 52,104,144, 99,237,218,181, 97,254,252,118,180, 90,237,139, 60,207,207,155, 51,103,142,242,161,135, 30, 34,141, 70,131, + 3, 7, 14, 96,226,196,137,250,130,130,130, 77,249,249,249, 79,249, 99,207,223, 93, 47,192, 31,139,224,237, 0, 34, 10,171, 95, + 41,186,214,198,109, 63,112,221,186,116,138, 80, 17, 85, 54, 50,118,213,159,147, 16,145, 36,136,220,252,168, 10,218,218, 51,223, +152,172,123,236,209,254,194,165,244,115, 13,107, 86,171,183,114,213,202,117,150, 73,227,167, 36, 16, 81, 24,128, 51,140, 49,167, + 55, 61,139, 69,167, 58,127,249, 22, 85,140,144,189,158,251,108,186, 1, 77,235,199,120, 63,240, 78,226,212, 10, 96,127, 26, 0, +160,130,159,239,253, 67, 33, 34, 65,169, 84, 30,108,214,172, 89,163, 89,179,102, 9,223,126,251, 45,150, 46, 93,186, 28, 64,245, +191,216,174, 10, 97, 97, 97, 35, 20, 10,197,176,206,157, 59,107, 71,143, 30, 29, 1, 0, 31,126,248,225,147,113,113,113, 58,139, +197,178, 44, 55, 55,247,115,198,216, 13,111, 90,130, 32,100, 58, 28,142, 50,111,236, 9, 9, 9,223,188,241,159,250,235,166, 12, + 77, 24, 57,107,121,234, 10, 0, 81, 0,178,238, 62, 78, 20,197, 36,187,221, 30, 81,124,159, 36, 73, 57, 22,139,165,217, 93,246, +171,102, 61, 91,255,161,113,131,106,245, 84,119,252,246, 19, 34, 58, 85,214,111,145,136, 42,135,134,134,254,212,171, 87,175,248, +239,191,255, 62,145,136,250, 50,198,210,189,125,182, 50,244,228,200,200,200, 4, 81, 20,235,116,234,212, 73, 26, 61,122,180,162, + 75,151, 46,216,190,125,123,194, 7, 31,124, 80, 37, 38, 38,198,170,215,235,147, 13, 6,195,121,198,152,165, 52, 29, 81,161,200, +234,221,166, 94,169,223,157, 44,203,191,251,142, 74,195, 98,177, 68,239,223,191, 31, 68, 4,142,227, 32, 73, 18, 20, 10, 5, 68, + 81,132, 36, 73, 16, 69,241,142,231,130, 32, 64,150,229,178,254,111,209,239,188,243, 14,148, 74, 37, 76, 38, 19, 76, 38, 19,204, +102, 51,204,102, 51, 44, 22, 11, 44, 22, 11,172, 86,107,209,102, 54,155,241,253,247,223,151,169,183, 96,193,130,223,233, 89,173, + 86, 88, 44,150, 59,158, 91,173, 86,152, 76, 38,108,221,186,213,107,192, 64, 68,213,101, 89, 30, 33, 73,210, 48,181, 90,109,237, +220,185,243,225,168,168,168, 77,217,217,217,218, 29, 59,118,124,102, 48, 24, 36,165, 82,185,220,108, 54,127,198, 24,187,232,235, +247,233, 38,129,231,121, 92,189,122, 21, 60,207,243, 0,234, 2, 56,232,203, 27,137,168,169, 86,171,125, 51,245,224, 14,101,172, +100, 2,156, 25,128, 5,168,212, 44, 26,143, 30,220,161,121,176,123,255, 94,146, 36,253,215,106,181,126,234,143,222,233,211,167, +149,149, 42, 85, 42,218, 95,169, 82, 37,244,232,209, 67,211,186,117,235,191, 84, 47,192, 31,143,215, 0, 32, 70, 35, 61,188,124, +249, 42,161, 96,195, 34,188,211,189,137,212,115,197,129,246, 68,180,134, 49,102,247,245, 36,188,200,125,218,228,129,234,149,118, +108,221, 95,165,192,116,227,216,249,204,237,223,175,219,240,117,187, 49,195,199,237,125,249,197,177,226, 11,255,125, 49, 47, 50, + 50, 18, 58,157, 46, 30,192,101, 95, 52, 43, 70,200, 24,240,174,225,142,125,146, 4,104,100, 64,173,228,161, 22, 1,141,146,135, +196, 59,124, 53,179, 56,199,183,236, 57, 25,175, 80,133, 0,192,249,242, 8,252, 81, 72,146, 52,165,105,211,166, 13, 87,175, 94, + 45,124,254,249,231, 88,178,100,137,222,108, 54, 15,189, 87, 93, 34,234,160,209,104,254,203,243,124, 16, 17, 41,109, 54,219, 85, +131,193, 48,131, 49,118,197,135,247, 86, 36,162,244, 22, 45, 90,176, 21, 43, 86,240,145,145,145, 69,175,245,234,213, 43,242,214, +173, 91,145, 67,134, 12,153,190,109,219,182, 25, 68, 20,239, 45,219,227,112, 56,162,147,146,146,160,213,106, 97, 52, 26,209,184, +113, 99,164,166,166, 66,173, 86,195, 98,177,224,228,201,147, 87, 51,142,175,216,243,124, 55,105,228,194,175, 47,172,159,185, 52, +249, 2, 0, 67, 73, 90,118,187, 61, 34, 63, 63, 31,193,193,193, 0, 0,189, 94, 15,173, 86,123, 71, 64,224,113,254,147,135, 36, + 12,122, 99, 89,202, 94, 0, 34, 0, 5, 0, 83, 41,159,183, 97,100,100,228, 15,115,231,206,173,208,184,113, 99, 60,242,200, 35, +205,150, 44, 89,114,168, 78,157, 58,118,189, 94,111,118, 56, 28, 59, 50, 50, 50,222,103,140,157,245,246,221, 1, 64,173, 90,181, +218, 37, 36, 36, 84,125,238,185,231,164,199, 30,123, 76,120,241,197, 23,123,140, 30, 61,186, 69,118,118,118, 88, 84, 84, 84,110, +211,166, 77, 15, 31, 60,120,112,203, 55,223,124,243,192,226,197,139,155,196,199,199, 95, 74, 79, 79, 47, 49,227, 99, 53,155,139, + 90,183,181,234, 54,220,172, 84, 42,155,114, 4,112, 28,129,136, 64,196,225,129, 7, 91,223,224, 56,192,100, 52, 31, 59,113, 60, +233,209,178,108, 19, 69, 17, 75,151, 46,133, 40,138, 80,171,213, 80, 42,149, 80,169, 84, 80, 42,149, 80,171,213,144,101, 25, 26, +141, 6, 42,149, 10, 29, 58,116,240,250, 89, 53, 26, 13, 58,117,234, 4, 81, 20,209,178,101,203,162, 32,162,180,205, 27,106,181, + 26, 83,167, 78,133, 32, 8, 16, 4, 1,193,106, 21, 70, 53,111, 1,133,211,137,165,231,206,193,236,116, 22,189,230,139,158, 36, + 73, 73,162, 40,214, 76, 76, 76, 60, 60,114,228,200,207,159,126,234,169,235,128,131, 86,172,248,178,210,144, 33, 79, 31, 5,248, +159,190, 92,181,170,226,226,197,139, 31, 60,116,232,208,104, 73,146, 46, 88,173,214,102,222,116,221, 93,158, 51, 7, 13, 26, 52, +101,244,232,209,136,140,140,196, 75, 47,189, 4,198,216, 47, 68, 52, 23,192,116,111,141,159,224,224,224, 57,243,231,207,151, 99, + 69, 35,216,138, 1,128,206, 29,203,105,162, 97,127, 98, 41,230,207,159,175,233,219,183,239, 60, 0, 62, 57, 88,143, 94,113,103, + 13, 0,118,187, 29, 38,147,233,158,244,142, 28, 57, 2,139,197, 21,167, 10,130,128, 26, 53,106,248,173,247, 79,132,136, 4,142, +227, 50,156, 78,103,209, 61,134,231,249, 28,135,195, 17,235,143,207, 44,166,199, 1, 24, 8, 64, 93,108,183, 1,192, 26, 95, 26, +203,222, 40, 51, 0,208, 18,213,123,186,119,215,160, 90,200,133,238,250, 5,196,134,133,226,249,135, 26, 42, 22,237, 63,245, 32, +128,159,125, 57, 1, 17,245,138,140, 83, 55,216,182,101, 79,212,233,203,223,255,184,239,212,167,123, 32,209,173,155,217,217,198, + 77,123,231,157, 79,168,222, 67,167, 80, 64, 89, 88, 88,104, 34,162, 42, 68,164,100,140,149,120,227, 45, 11,165, 12,168, 37,151, +211, 87,203,128, 82,226,161, 86, 2, 74,240,254, 74, 1, 64,241,150,156,215, 22,235,159,137, 32, 8, 35,102,207,158, 45,174, 91, +183, 14,111,190,249,166,222,108, 54,119,103,140,237, 39,162, 54, 42,149,106,185,209,104, 28,234, 79,119, 0, 17, 85, 86,171,213, + 31,134,134,134,182, 31, 63,126,124, 65,116,116,180, 77,165, 82, 57, 15, 29, 58, 84, 99,241,226,197,125, 53, 26,205,231, 6,131, + 97,108, 89, 63, 54,198,216,117, 34,170,125,236,216,177,113,141, 26, 53,234,253,228,147, 79,170, 70,141, 26,165, 5,128,143, 62, +250, 72,183,118,237, 90,163,195,225,248,150, 49,246,174,175, 93, 61, 90,173, 22, 27, 54,108,128, 66,161, 0,224,186,209,239,223, +191, 31,130, 32, 92,205, 58,185,114,193,243,221,164,199, 63,249, 33,247,167,183,214,101,247, 5,176,138, 49,166, 47, 77, 43, 56, + 56, 24, 95,125,245, 21, 66, 67, 67, 17, 26, 26,122,247,231,191,195,249,191,241, 89,202,113, 0,151, 74,251, 13,138,162,216,185, + 66,133, 10, 95,190,245,214, 91,209, 53,107,214, 68,112,112, 48, 30,122,232, 33,122,248,225,135,163, 1,192, 96, 48, 96,211,166, + 77,213,231,204,153,243,184, 36, 73,143, 88,173,214,227,222, 62,107, 65, 65, 65,252,182,109,219,236,209,209,209, 5,173, 90,181, +250, 95,124,124,124,232, 55,223,124,163,175, 91,183,238,181,148,148, 20,113,202,148, 41,109, 58,116,232,208, 96,251,246,237, 99, +213,106,181,248,202, 43,175, 84, 5,224,245,127,172, 80, 40,154,207,253, 96,113,180, 36,242,144,120, 1, 10,145,131, 40, 10, 80, +240, 60, 36,145,199,176,167,158,244,122,113,136,162, 8, 34, 66,159, 62,125,138,246,237,218,181, 11,159,125,246, 25, 34, 35, 35, + 49, 97,194, 4, 40,149, 74, 56, 28,190, 5,218,102,179, 25,125,251,246, 5,207,243, 94,157,191, 47, 14,219,108, 54, 67, 16, 4, +212,175, 17,139,215, 30,173,135,214, 22, 6,125, 54, 15, 46,211,140, 17,118, 59,146,234,213,195,251,121,121, 72, 55, 24, 32, 8, + 94,219, 59,176,217,108, 77,227,227,227,143, 95,187,118, 45, 92,202, 62, 93, 17, 7, 63,137, 6,115, 80, 29,251,213, 32, 28,248, + 36, 10,196, 51, 49,243,146,120,233,210,165,240,144,144,144,180, 91,183,110, 53,245,233,131, 3, 51,151, 47, 95, 62,109,200,144, + 33, 0, 0,167,211,137,230,205,155, 99,213,170, 85, 92,215,174, 93,167, 13, 29, 58, 20, 0, 94, 43, 75,192,110,183,183,232,212, +169, 19,129, 93, 5,116, 89,160,119, 92,189, 16,108, 60,193,160, 47, 68, 88, 88, 77, 72,146,164, 36,162, 10,190,100,218,138,244, + 60, 56,237,176,231, 94,131,190, 32, 15,198,194, 66,196,169, 28, 8, 86,203,229,210,179, 88, 44,104,211,166, 13, 28, 14, 7,118, +236,216,129,188,188, 60,132,133,133,249,101, 95, 89,244,239,223,159, 7,128,117,235,214,149,171,133,247, 7, 18,195,243,188,178, +248,245, 32,203,178,210,221,237,228,115, 55,119, 49,148, 0, 24, 99, 44,201,179,131,136,106,187,247,151,216,232,241,135, 82,175, + 8, 34, 82, 86, 10, 81, 55,159,247,193, 39,156,238,157, 17,128,168, 2,175, 80,225,191, 15,181,224,214, 38, 93,174, 65, 68,103, + 24, 99,121,222, 78, 32, 42,248, 49,211,102,190,232,184, 85,120,225,198,190, 83,139, 47, 51,112, 65,204, 1, 61, 0,132,216,205, +102,247, 97,158,155,109,182,251,131,149, 25, 0,240,188,188, 88,165, 82,105, 75,123, 93,161, 14, 55,188,185,230,210,179, 26,153, +135, 88, 46,255,255,247,197,106,181, 86,168, 82,165, 10,142, 29, 59, 86,180,143,136,218,104,181,218,237, 19, 38, 76, 80,206,153, + 51,103, 11,128, 96, 95,180,136,168,141, 44,203, 91,158,121,230,153,130, 57,115,230, 92,212,104, 52, 78, 0, 40, 44, 44,228,154, + 53,107,102,234,216,177,163,121,220,184,113, 79, 95,191,126, 61, 13,192, 7, 37,105, 4, 7, 7, 39, 43, 20,138,116, 0, 51,179, +178,178, 94, 32,162,177, 31,125,244, 81,239,175,190,250,234, 21, 0,200,201,201,153,111,181, 90,191,101,140, 89,137,232,193,224, +224,224,143, 28, 14, 71,148, 94,175,111, 82,150,109, 70,163, 17, 10,133, 2,146, 36, 1,112,221, 80,238,118,254,215, 89,139, 49, + 25, 25, 63,197,148,229,252, 61,132,133,133,253, 46, 0, 40,197,249, 95,100,140,221, 46,229,251,170, 21, 25, 25,249,213, 7, 31, +124, 16, 90,177, 98, 69,132,132,132, 32, 36, 36, 4, 28,231,170,103,181,217,108,184,121,243, 38,194,195,195, 49,116,232,208,152, +221,187,119, 31,210,104, 52, 31,235,245,250,177,222,236,179, 88, 44,234,129, 3, 7,246,175, 92,185,114,200,238,221,187, 51,137, + 72, 0,192, 61,240,192, 3,230,111,190,249,198,216,187,119,239,168, 71, 31,125,244,153,126,253,250,109,130,151,235,163,152,230, +145, 41, 47,142,116,101, 0,136, 64,156, 43, 3,224,202, 8, 0, 38,147,249,152, 55, 13, 73,146,160, 86,171,225,116,254, 22,255, +189,247,222,123, 48, 26,141,184,112,225, 2, 14, 29, 58,132,246,237,219,195,102,243, 90, 50,225,177, 9,153,153,153,119,116, 33, +220, 75, 0, 96,177, 88, 16, 20,164,194,142, 55,131,113,243,114, 30,222,216,229,196,119, 73,215, 33, 8, 2,122,213,168,141, 1, +102,134,183,236, 2,158, 85, 42, 97,245,177,219,254,171,175,190,250,100,255,190,125, 49,103,143,172, 27,152,159,126,162,102,176, +104,231, 19, 1,176, 84, 32,223, 38, 56,146, 46,213,184,240, 64,243,230,107,234,214,175,159, 57,103,206,156, 50, 91,179, 68, 20, + 4,160,238,160, 65,131,166, 12, 25, 50, 4,169,169,169, 24, 54,108,152,238,232,209,163, 55, 19, 19, 19, 99,151, 45, 91, 22, 52, +100,200, 16,108,219,182,109, 10, 17,109, 1,112,150, 49,150, 95,146,150,221,110, 87,170,213,234, 18,111,251, 6,131, 17,183,245, +183, 33,138, 34,131,171, 91,193, 23,135,237,210,115,227, 72, 63, 2, 91,210, 26, 8,121, 55,160,177,217, 0,210,160, 85,245, 96, + 90,159,149, 83, 46, 61,167,211, 9,163,209, 8,163,209,136,252,252,124,220,190,237,159,125,119, 67, 68, 45,131,131,131, 39, 18, +209, 67, 38,147, 41,216,225,112, 32, 56, 56,184,128,136,126, 42, 40, 40, 88,192, 24,243,169, 43,229,126, 35, 8,194,215, 28,199, +213, 0, 0, 81, 20,101,181, 90,237, 28, 56,112, 32,100, 89,134, 66,161, 64, 80, 80,144,179,176,176,112,167, 74,165, 58, 99, 52, + 26,251,122,211, 35,162, 14, 0, 60,254, 77, 0,160, 7,144, 84,236,144, 10, 0,186, 16, 81, 30, 99,108,207, 61,217, 94,218, 11, +145, 10,161,253,123, 11,230, 75,182, 77, 31,226, 76,102,161,118,200,166,253, 83,230, 61,209,254,131,158,173, 42,102, 44, 26, 53, + 80, 28,252,206,231, 93, 0,124,229,237, 4,204,201, 26,246,120,164, 87,206,209,243, 95,157, 38, 32, 8, 96, 32, 7,172,140, 57, +217,200,145, 71,239,184,107, 48,198,140,190,140, 52,112, 88, 13,218,235,183,237,136, 10,230,224, 10, 95,139, 5,177,140, 65, 33, +114,106,141,204, 67,173,228, 32,149, 47, 3,240,183, 69,150,229,203, 87,174, 92,169, 89,191,126,125,204,153, 51, 71, 51,109,218, +180,173,130, 32,240,155, 54,109, 82,230,228,228, 64,150,101, 95,139,197, 90,132,133,133,173, 89,189,122,245,249,174, 93,187,234, + 60,187, 47, 93,186,164,184,116,233,146,188,118,237,218,208, 11, 23, 46,168,180, 90, 45, 47, 8,194, 36,148, 18, 0, 40, 20,138, +240, 55,223,124,179,238,146, 37, 75, 30,136,136,136,184, 45,203,242, 92,179,217,188,230,198,141, 27,107,221,231, 81,136,162,248, +148, 86,171,157,146,144,144, 16,218,173, 91,183,240,229,203,151, 95,243,102, 95,227,198,141,239,248,123,246,236,217,121,137, 21, +243,138,156,255, 53,103,243, 49,241,241,149,125, 42,230, 50, 24, 12, 8, 13, 13, 45, 10, 2,220,118,249,229,252,221, 92,178,219, +237,151, 15, 28, 56,160, 26, 58,116,168, 34, 36, 36, 4,174,110, 92, 87,218, 52, 61, 61,189,104,171, 86,173, 26, 6, 13, 26, 36, + 62,249,228,147,253, 0,120, 13, 0, 0,224,220,185,115, 15, 46, 95,190,220,100,179,217, 36,183,141,214,236,236,108,197,213,171, + 87,149,125,250,244,177,207,152, 49,227, 1, 0,155,124,209, 2,128,243, 41,167,138,210,251,178, 82,153,105, 49,155,239,238,255, +142,115,143, 12, 40,181,112, 79, 20, 69, 40,149, 74, 48,198,138,182,225,195,135, 99,231,206,157,168, 94,189, 58, 18, 19, 19, 97, +177, 88, 96,183,219,225, 75, 93,156,205,102, 43,114,238, 59,127,252, 30, 2,156,120,108,192,211,229, 14, 0,172, 86, 43,130,131, + 84,224, 35,205, 24, 50, 85,143,236, 92, 75, 81,202,127,251,205,107, 56, 21, 28,130,137, 17, 53,161, 53, 93, 67,129,181,212,210, +137,223,209,182,109,171,236,248,234, 5,251,131,127, 57,154,224,105,105, 3, 64,200,120,226,123,181,106,184,255,251,220, 10,217, +222, 52,100, 89,126,239,201, 39,159, 28, 45,203, 50, 63,122,244,104, 0,192,176, 97,195, 10, 15, 31, 62, 92,147, 49,150, 77, 68, + 81,195,134, 13, 75, 59,116,232,144,118,204,152, 49,156,209,104, 60,224,254,220,111,219,108,182,137,119,235,169,213,234, 51,199, +142, 29,107,222,163,142, 22,208, 68,131,141,119,221,247,242,249, 48, 76,121,255, 75,124,191,247, 40, 66, 66, 66,148, 97, 97, 97, + 27,100, 89,118, 50,198,102, 89,173,214,183, 75,203,222, 21,233,245,232, 1,155,205, 6, 83, 94, 22,180, 7, 22,194,212,236, 89, + 24,110,223, 70,165, 43,107, 16,169, 73, 80,148, 71, 79, 16, 4,108,219,182,173, 40, 0,152, 53,107, 22,118,237,218,229,151,125, + 30,136,136,215,104, 52,159,196,196,196, 60, 57,113,226, 68, 85,255,254,253, 57,158,231,241,238,187,239, 34, 61, 61, 61,164,101, +203,150,143, 47, 88,176,160,139, 86,171, 93,171,215,235,159, 99,140,249,155, 21,224, 0, 48,247,230, 55, 14,135,163,207,179,207, + 62,139,228,228,100,216,108, 54, 68, 69, 69, 65,146,164,162,173, 95,191,126, 90,157, 78, 87,251,203, 47,191,172,237,163,100, 45, + 0,223, 3, 8, 1,144,239,222, 64, 68,228, 46, 62,221,233,126,173, 39,128, 61,229,177,217, 67,137, 1, 0, 17, 85,232, 88, 55, + 62,174, 91,243, 6,200, 91,244, 37,166,236, 62, 63,164, 79,195,170,161,243,126, 60, 56,178,103,135, 86,111, 52, 74,168,192,186, +183, 76,212,198,106,181,245, 50,116,186,228,210,196,137, 72, 25, 17,167,188,204,152, 35,244,118, 97,186,147, 17, 69, 48, 64, 3, +222, 25, 18, 87, 61, 56,232,217,215,235,110,224,121, 78,224,120,136,238,138, 91,234, 49, 52, 62,157,136, 70,122,251, 81, 84, 8, +227, 49,242,227, 92, 40, 68,114,109, 18, 65, 22, 1,133,224,186, 40,212, 74, 14, 26,217,213,153,235, 15,110, 59,226,170,199,168, + 32,107,100, 0,136, 33, 34,190, 28, 63,170,251, 14, 17,117, 84,169, 84,149, 67, 66, 66, 80, 88, 88,136,102,205,154, 97,249,242, +229,154, 26, 53,106, 32, 44, 44, 12,211,166, 77, 51, 88,173,214,101, 62,232, 52,168, 92,185,242, 7, 75,151, 46, 61,216,185,115, +231, 92,184, 35,168,171, 87,175,202, 41, 41, 41, 65,243,230,205,171,125,230,204,153, 84,189, 94,191, 89,163,209,180,225,121, 62, +164, 44,189,196,196, 68, 36, 38, 38,134,101,100,100,132,173, 90,181,234,195, 77,155, 54, 77, 6, 80, 27, 0,148, 74,229,169,198, +141, 27, 87,104,219,182,173, 58, 50, 50,210,167,155, 58,128,162, 62,127,179,217,140, 57,115,230,228, 37, 86,204,123,253, 78,231, + 31, 31, 19, 18, 82,166, 89, 0, 92, 5,127, 26,141,230,142, 62,127,165, 82,121,123,202,224,234,254, 58,127, 48,198,236, 68,212, +102,217,178,101,175,124,245,213, 87, 61, 56,142, 11,209,104, 52,234,110,221,186,105,218,183,111,175, 53,155,205, 72, 79, 79, 71, +120,120, 56, 90,181,106,133,215, 95,127,221,145,146,146, 50,220,167, 15, 12, 32, 39, 39, 39,172,110,221,186, 69, 45,163,188,188, + 60,225,202,149, 43,210,245,235,215, 69,147,201,196,231,231,231,151,154,245,242,134,197,108,142, 62,115, 57,243,142, 81, 1, 10, + 81,128, 36,240,208,168, 20,165, 22,198,137,162, 8,149, 74, 5,167,211,137,107,215,174, 33, 42, 42, 10,143, 60,242, 8,186,119, +239, 14,167,211, 9,187,221, 14,171,213,234, 87, 6,192,227,220,255, 59,234, 69,240, 28,119,207, 25, 0,158,151,128,160,142,112, + 98, 15, 4,193, 81, 20, 0, 8,130, 0, 78,148,112,169,102, 99, 80,106, 38, 4,231,159,119, 9, 19, 17,215,181,107,215,231, 86, +175, 94,205,223,188,121, 19,161,161,161,112, 58,157, 56,122,244,104, 6, 99, 44, 27, 0, 24, 99,217, 60,207,223,116, 56, 28,181, + 19, 18, 18, 48,106,212, 40,212,169, 83, 7,133,133,133, 99,136,232,149,187,239,129, 5, 5, 5, 11,199,142, 29,187,168,227,222, + 45,106,219,227,139, 97,212,235,112, 59, 55, 15,143,191, 52, 31,109, 59, 84,197,141, 27, 27,225,190, 38, 84,105,105,105,120,242, +201, 39, 95, 79, 75, 75,107, 15,160, 71, 73, 54,122,244,218,183,111,175, 54, 26,141,112, 24, 12,208, 2, 80, 13, 90, 12, 21, 92, + 93, 11, 31,125,244, 17, 62,170,241,144,223,122,213,170, 85, 67,126,126, 62, 50, 50, 50, 48,108,216, 48,180,111,223, 30, 55,110, +220,240,203, 62, 15, 42,149,106,102,163, 70,141, 6,110,221,186, 85,125,234,212, 41, 24,141, 70, 28, 56,112, 0,111,191,253, 54, +250,246,237,139,196,196, 68,238,252,249,243,154,238,221,187, 15, 60,126,252,120, 22,128,105, 62,252,139, 56,184,178,205, 10,252, + 22, 0,216,102,206,156,233,156, 49, 99, 6, 1,224,221,251,172,190,116, 73,135,135,135,131,231,121,132,135,135,131, 49,134, 95, +127,253, 21,233,233,233,168, 94,189, 58, 58,117,234,132,154, 53,107,250, 96,210,111, 48,198,110, 18,145,231, 81, 67, 68,109, 0, + 84, 32,162, 12, 0,199, 61,175,223, 43, 37,142,197, 15, 85,160,105, 90,250,117,103,139, 78,143, 88, 18, 87, 30,175,174,141,140, + 77,120,123,233, 10,106, 26,165, 9,111, 60,241,157, 86, 15,141,159,111,219,127,250,188,211,198,177, 50,211,184, 0,204,121, 89, +230, 6, 57, 5, 87, 45, 60,137, 17, 96, 44,132,192, 98, 57,134,170,149,227,149, 66,149,132, 32,123,124, 77, 53,171, 84, 77, 35, + 84,168,170, 9,169, 80, 85, 45,109, 91,125,109, 16, 0,159,170,246, 57, 30,224,221,155,192, 1, 2, 71, 16,120,215,151, 18, 44, + 3, 65, 74, 30, 26,165,239, 25, 0, 34,170,165, 18,232,231,121,205,194,251,141,234, 81, 9,207,117,141, 64,207,103,234,118,149, +148,194, 97, 34,106,232,179,208, 31, 0, 17,181, 87,171,213, 63,108,216,176, 65, 97,181, 90,145,145,145,129,180,180, 52, 68, 69, + 69,225,242,229,203, 24, 54,108,152,225,196,137, 19,105,102,179,121,174, 23,157, 26, 9, 9, 9,147,151, 44, 89,178,187,115,231, +206,135, 1, 92, 4,144, 6,224, 98, 94, 94,222,181,139, 23, 47,230, 92,188,120, 49,187,176,176,176,135,195,225, 88, 88, 80, 80, + 48, 64,167,211,117,245,197,198,216,216, 88, 76,152, 48, 65,173, 80, 40,138, 28, 21,207,243,193, 93,187,118, 85,123,138,240,124, + 69,173, 86, 99,223,190,125, 56,118,236,216,213,226,206,255,170, 35,113, 76,229,202,149, 99,130,131,131,139,234, 3,202,194, 98, +177, 52, 99,140,197,123, 54, 0,117,166, 12,174,254,186,191,206,223, 3, 99,204,116,235,214,173, 25, 87,175, 94,109,126,229,202, +149,154,201,201,201, 53,223,121,231,157, 65,195,135, 15, 79, 63,124,248, 48, 34, 34, 34,208,182,109, 91, 76,159, 62,221,241,205, + 55,223,244,100,140,109,247,245, 51, 71, 68, 68,228,166,164,164,136, 0,160,211,233,184,171, 87,175,138,215,175, 95, 23,111,220, +184, 33, 22, 22, 22,114, 33, 33, 33, 94,187,220, 74, 67, 33,203, 89,245,171,198,160, 86,197, 8,196, 71,135, 34, 54, 60, 8, 97, + 65, 42,104, 84, 10, 40,149,202, 82, 71, 6, 72,146, 4,165, 82,137,169, 83,167,226,217,103,159,197,192,129, 3,145,158,158, 14, +187,221,142,220,220, 92,188,246,218,107,152, 61,123,118, 81,193,151, 55,138,103, 0,114,114,110, 35, 55, 47,255,158, 2, 0,171, +213, 10,226, 69, 28, 8,173, 0,230, 30,137, 80,188,232,143, 36, 5, 46, 85,174, 3, 78,144,124,170, 1,184, 95, 48,198,156,187, +118,237, 90, 56,100,200, 16, 76,158, 60, 25,201,201,201,224, 56, 14,137,137,137,113, 68, 20, 5, 0, 68, 20,149,152,152, 24,203, +243, 60, 82, 83, 83,241,254,251,239, 99,212,168, 81,142, 61,123,246,124, 82, 82, 3,200,110,183,127,121,235,214,173,189,237, 31, +123,202,112, 44, 95,139,107,138,154,120,109,217, 46,116,120,184, 43,190,120,127, 54, 66,114, 79, 1,105, 63, 1,105, 63,161, 6, +221,192,206,175,151,169, 35, 35, 35, 59, 8,130,240,116, 73, 54,122,244, 58,118,236,104, 72, 78, 78,134,209,104, 4, 0,220, 92, +212, 31,108,195,157, 73,171, 26, 53,106, 96,219,182,109,126,233,229,231,231,227,189,247,222, 67,167, 78,157,176,172, 28,246,121, + 32,162,255,142, 31, 63, 94,173,213,106,161, 84, 42,177,124,249,114, 60,255,252,243,144,101,151,155, 80,171,213,208,106,181, 24, + 63,126,188, 26,192, 72,111,255, 27, 34,234, 61,102,204,152, 24, 0, 65,112,181,164,195, 0,132, 29, 62,124, 56, 70,146,164,184, +166, 77,155, 70, 39, 38, 38, 70,175, 88,177,162,157, 36, 73, 61,189,233,185, 53, 65, 68,144, 36, 9,167, 79,159,198,135, 31,126, +136, 31,126,248, 1,141, 27, 55,198, 47,191,252, 82,212,149,233, 39, 30, 15,223,224,248,241,227,189,117, 58, 93, 68,108,108,172, + 1, 64,163,242,136,149, 68,137, 87, 68,158, 5, 63,228, 89, 28, 60, 12, 6, 69,180, 70,158,247,217,154,117, 82,193,186, 57,152, +217,185,129,226,161, 47,246, 63,122,236,202,205,201, 0,114, 0,148,217, 74,103,140, 49,165, 90, 76,217,188,249, 91, 85,221,196, +200, 10,185,250,116,145, 57,201,225,116,146,137,192, 28, 28,136, 7, 72,102, 96, 18, 8,202, 75,103, 10, 20,130,196, 93,182, 89, + 29, 70, 95,140,151, 69, 42,218, 60,153, 0, 89,242,100, 0, 92, 69,128,190,124,237,238,254,214, 9,237, 98,228,153, 75, 90, 71, + 73,181,130, 68,156,254,104, 60,142, 84,141, 64,163,142, 81,168, 82, 63,168,233,214, 47,206, 39, 17,209,155, 0,102, 49,198,172, +190,216,119,191, 32,162,118,106,181,250,199, 13, 27, 54,200, 65, 65, 65, 56,113,226, 4, 94,126,249,101, 35,207,243,153, 70,163, +177,178, 82,169,204,116, 56, 28, 43, 77, 38,211,244,178,198,175, 19, 81, 92,195,134, 13, 7,189,245,214, 91, 59,187,116,233,226, +105,249,123,126,100,164,213,106,149,162, 40,230,139,162,168,130, 43, 8,243,173, 89,247, 7,224, 46,238,186,122,235,244,234, 5, +197,157,191,167,229,175, 80, 40,124, 10, 0,138, 83, 66,218,223, 14, 32, 14,128,182, 88, 52,109,102,140,253,226,171, 38, 99,204, + 0,224,123, 34, 10, 51, 24, 12,203,218,182,109, 75, 83,166, 76,113,124,253,245,215, 61, 25, 99, 63,250, 99, 95,237,218,181, 15, +204,157, 59,183,125,211,166, 77,173, 87,174, 92, 17,175, 92,185,194, 93,187,118, 77, 50, 26,141,220,190,125,251, 16, 22, 22,118, +168,172,247, 75,178,156,105, 43, 97,220,190, 66,150,179,204, 38,147, 79,221, 37,119,227,233, 2,200,204,116,205, 31,100, 52, 26, +145,158,158,142,136,136, 8,236,223,191, 31,201,201,201,136,143,143,135,213,106,245,187, 11,192,179,173, 89,242, 30,120, 56,240, +236,132, 55,252, 14, 0,108, 54, 27, 32,114,216, 32, 95, 2,164, 59,157,191, 32, 8, 32, 73, 66,122, 68, 60, 72, 20, 32, 56,124, + 11, 0,172, 86, 43,119,242,248,241,240, 60,253,149,200,142,156,194, 36, 78,224, 37,155,131,241, 2, 7,135, 13,162,229,122, 78, +126,200,245, 12, 46, 56,190,106,213, 18,251,234,139,217, 54,145,136,230, 0, 72,112, 56, 28,191,172, 90,181,138, 91,182,108,153, +118,216,176, 97, 23,120,158,207,104,209,162, 69,220,178,101,203,180, 0,240,225,135, 31, 58,191,255,254,251,214, 0, 82,202,154, + 23,160,160,160,224,209, 83,167, 78, 77,232,222,189,251,107,193,193,193,124, 65, 65,129,242,250,245,235, 64, 78, 50,216,151,191, +141, 12, 96,154, 40, 56,122, 44,194,228,201,147, 85, 19, 39, 78, 28, 3,224, 75,111,122,143, 54,173, 32,118,137, 12, 85, 12,105, +200, 3,166, 60, 80,199, 73,128,164, 1,224, 26, 61, 99, 52, 26,253,210,187, 31,246, 1,128,193, 96, 24, 49, 98,196,136,181, 13, + 27, 54, 84, 53,108,216, 16, 31,127,252, 49,122,244,112, 37, 13,212,106, 53, 26, 53,106,132, 11, 23, 46, 96,248,240,225, 38,163, +209,248, 76, 89,255, 19, 55,103, 22, 47, 94,220,230,241,199, 31, 63,219,169, 83, 39, 17,128, 34, 59, 59,155,204,102, 51,139,141, +141,229,135, 13, 27,166,168, 89,179,102,196,144, 33, 67, 20, 0,202,188,230, 60,120, 2, 0, 65, 16,112,245,234, 85, 72,146, 4, +155,205,134,209,163, 71,163, 83,167, 78,247, 26, 0,196, 85,169, 82,229,140, 70,163, 57,156,145,145,113, 1,192, 99,229, 17, 43, +137, 18,175, 8,119,186,219, 17,174,224,231,140, 25,254, 84, 84,216,133, 95, 96,200,187,133,160,224,112,204,232,213, 42,120,230, +230,131, 75,174,229,235,203, 76,219,120, 48, 27,237, 11, 62,255,104,235, 7,111,127, 49,204, 46,112,178,195, 6,139, 14,140,113, + 4,198, 64, 0, 99, 80, 16,131,134, 17,147,182,174,185, 22,100, 51,219, 39,251,106,124,145,243,151, 8, 10,193,229,252,101,247, + 61, 67,173,116, 13, 9,244, 86, 3, 64, 68,221,100,158,190,124,167, 69,120,196,243, 9,193,176, 59, 25,222, 56,145,135,121, 43, + 22,237,181,243,156,169, 69,183, 10,221,218, 61, 81, 5, 79, 78,106, 40,156,218,151, 57,109,251,151,105, 99,137,104, 32, 99,172, +220, 19, 34,249, 3, 17,181, 85,171,213, 63,110,220,184, 81,214,106,181, 56,118,236, 24,198,143, 31,111, 48, 26,141, 3, 24, 99, + 91,252,208, 9,109,212,168, 81,203,233,211,167,239,232,218,181,107, 33,126,115,254, 69, 1, 64,181,106,213,184,102,205,154, 93, +105,218,180,169,213,106,181, 14, 36,162, 93,112, 5,122, 58, 63,135,156,220,211,132, 60, 0,112,236,216,177, 59,156,255, 21, 91, +211, 49, 85,170,252,214,242,151,101,185,168, 5,224, 11,165,244,249,199,185,135,234,121, 60,141,133,136, 42,149, 33, 83,154,118, +183,161, 67,135,126, 54, 97,194, 4,154, 60,121,178,115,253,250,245,126, 59,127, 0,120,253,245,215,127, 28, 58,116,104,163, 39, +158,120, 34,116,240,224,193, 54,189, 94, 79,249,249,249,180,119,239, 94, 74, 77, 77,205, 27, 52,104, 80,153,255,111,155,197, 18, +189,118,207, 73, 72,130, 0, 73,228,161, 16, 92,213,254,237, 27, 86,243,107,178,156,226,136,162, 8, 89,150, 49,107,214, 44,236, +221,187, 23, 49, 49, 49,104,210,164, 9, 44, 22, 11,234,212,169,131, 30, 61,122,160, 85,171, 86,229,202, 0,120,182,201,179,223, + 1,207,113, 88, 60,239, 21,216, 44, 38, 76,249,223,114,191, 50, 0, 78,135, 19,191,178, 61,168,248,113, 19,176,229, 74,100,238, + 77,129, 32, 8,136,123,176, 59,236,137,125,144,163, 8,129,154, 57,125,206, 0,204,157, 59,183, 93,197,138, 21,111,213,121,160, + 86, 90,110,141,151,111,243,112,210,132,119,151, 13, 31,214, 61,113,133,147, 4,103, 86,158,116, 59,235,214,173,176, 11, 23, 47, +214,240,166,229, 46,232, 59, 72, 68,115,187,118,237, 58,109,200,144, 33, 56,116,232, 80,144,195,225, 8,242,212,143,172, 88,177, + 2,171, 87,175,158,235, 75, 17,155,251, 58,124, 11,192, 91, 68,212, 57, 38, 38,102, 67, 68, 68,132, 10,249,142, 59, 70, 6, 96, + 60,193,168,215, 33, 34, 34, 2, 6,131,161,190, 47,122,213, 35,213, 61,179,116,145,235,159,125,116,174,235,194,226, 4, 32, 40, + 22, 58,157, 14,249,249,249,200,207,207,247, 75,239,126,216,231,214,220, 44, 73,210,184,230,205,155,191, 59,105,210, 36,197,128, + 1, 3,248,164,164, 36, 56,157, 78, 52,104,208, 0,111,188,241,134,253,127,255,251,159,205, 98,177,188,204, 24,219,236,195,119, +120,158,136,148,221,187,119,111,210,190,125,123,125,183,110,221,168,109,219,182,100, 50,153,232,204,153, 51,226, 47,191,252, 34, + 36, 37, 37,113, 54,155,237,136,175, 67,121, 61, 1,128, 66,161, 64,181,106,213,240,193, 7, 31,224,153,103,158,193,150, 45, 91, +208,160, 65,131,123, 13, 0,110, 54,110,220,248,102,122,122,250, 69,148,179,128,178, 52,202, 26, 5, 80, 51, 33, 54,252,191,227, + 38,188,194,231, 45, 24, 1, 82, 5,129, 83, 40,241,120,243, 10,220,151, 71, 46,180, 87,138, 98, 71,147,205,182,219,219, 9, 24, + 99,235, 84, 26,241,249,133,243,190,107,252,248, 51,213,110, 51,230, 84, 18, 72, 1, 34,157,147, 65,195, 1, 10, 16,184, 31, 86, +164, 71,230,102,153,207, 57, 28, 88,225,171,241, 37, 57,127,133,232,233, 2,112,101, 0,120,239,195,147, 94, 51, 45,159, 30, 1, +198,112,232,171,165, 24,249,235, 45,221,169, 92,235, 56, 0,159, 49,187,157, 17,209,224,243, 73,183, 23, 62, 50,162, 86,200,132, +209, 99, 48,238, 5,187,166, 99,227,151,166,194, 85,164,241,135, 35,138,226,182,205,155, 55, 43,213,106, 53,142, 30, 61,138, 9, + 19, 38, 24, 76, 38, 83,111,127, 82,203, 0, 16, 28, 28,204,130,131,131,183, 63,241,196, 19, 38, 20,115,250,197,158, 3, 0, 30, +120,224, 1,218,184,113,227,145,246,237,219, 71,219,237,246, 56,189, 94, 31,103,181, 90,175,163,148,249, 25,108, 54, 27, 46, 95, +190,140,170, 85,171, 22,237, 35,162, 82, 3,128,155, 55,111,122, 29, 50, 86,171, 86,173,111,110,157, 94,189,231, 78,231, 95, 37, + 38, 36, 36,164,200,241,251,147, 1, 40,173,224, 15,174, 74, 91, 17,192,233, 98,135,251, 21, 0, 16, 81,183,225,195,135,111,158, + 62,125,186, 48,118,236, 88,251,134, 13, 27, 30,245,215,249, 51,198,114, 38, 76,152, 16, 57,126,252,120,121,249,242,229,243,103, +204,152,209, 99,198,140, 25, 45,114,114,114, 66,181, 90,109, 94,104,104,232,225,126,253,250,109, 49,153, 76,142,109,219,182,153, +225, 10,202,126,135,168, 80,100, 61,217,161, 81,137, 25, 0,127,236, 41,142,167, 11, 64, 16, 4,244,236,217, 19, 54,155, 13, 22, +139, 5, 54,155, 13,106,181, 26,221,186,117, 43,218,231, 75, 6,192,110,183,255, 46, 0,200,203, 47,132, 40,138,152,243,209, 10, + 16,199,225,205,151,158, 66,197,112, 53,210,111,100, 97,233,210,165,101,234,217,108, 54, 56, 45, 78,168,135,197, 66,249, 92, 48, +232,185,154,168,223,243, 57,228,235,170,224,184, 89,141,122,134,179, 8,221,249, 33,172, 14,187, 79, 1, 0,199,113,105, 71,142, + 28,105,144,152,152,184, 81,211,160,235,213,171, 78, 39,129,156,180,234,200,130,225,202,122, 81,135,121, 73,102,130, 36, 49, 65, +208, 85, 78, 77, 77,109,201,113,220, 5, 31,191,202,233, 67,135, 14,197,182,109,219,166,140, 25, 51,134, 75, 72, 72, 64, 74, 74, + 10, 62,250,232, 35,231,234,213,171,231, 2,152,238,163, 78,113, 82, 12, 6, 67,169, 29,193, 6,131, 1,183,111, 59, 33,138,162, + 79,163, 70, 46,229, 24,143,223,178,228, 50,132,253,118, 45, 23,119,254,121,121,121,158, 74,126, 95,135,105,223, 55,251,172, 86, +235,167, 68,180,127,222,188,121,175,112, 28,215,222,104, 52, 70, 3,112,170,213,234,155,118,187,125,183, 94,175,127,151, 49,150, +234,163, 93, 96,140,157, 36,162,244, 3, 7, 14,196, 39, 37, 37, 85,212,235,245,145, 0, 32,138,226,109,163,209,120, 13,174,161, +192, 62,207,208,232,201, 32, 74,146,132,118,237,218,225,192,129, 3,232,219,183, 47,234,215,175,143,158, 61,123,222,107, 0,112, + 42, 61, 61,189, 49,128, 71, 1,220, 4,112,162, 60, 98, 37, 81,234, 21, 17,165, 18,215, 45,253,252, 11,173,110,245, 60,128, 23, + 65, 10, 37, 72, 82,130, 20, 74, 44,124,225, 41,117,143,153, 31,174,206,156,228,102, 0, 0, 32, 0, 73, 68, 65, 84,118, 79,234, +226, 53, 29,110, 50,216,123,156, 58,148,253,253,213,180,252,250,157,251, 85,202,171,222, 32, 56, 87, 20, 9, 78, 39, 44,105,103, + 10, 84,219,191,186, 22,150,151,109, 73, 54, 27, 29,221,125,109,105, 58, 25,220,133,127,238,212,191,219,249,123,186, 0, 28,214, + 60, 56,192, 3,240,106,158, 13, 54, 43,176,115, 57, 90,109,185,113,203,201,208,136, 49,150,225,121,145, 49,182,146,136,182,175, +152,125,252,244,240, 62,246,168, 83,151, 54,194, 23,209,251, 5, 99,140, 37, 39, 39,131,136, 48,105,210, 36,189,201,100,122,140, + 49,246,147,191, 58,249,249,249,101,166, 43,239,102,239,222,189, 87, 1,120,157,241, 49, 63, 63,255,241, 17, 35, 70, 44,109,221, +186,117,133,113,227,198,133,132,133,133,149, 24, 0, 20, 22, 22,226,199, 31,127,204,187,120,241,226, 53,189, 94, 95,106,154,142, +136,212,111,252,167,254,186,231,187, 73, 35,239,118,254, 30,167,239, 79, 6,160,172,106,255,123, 45,162, 33,162, 54, 35, 70,140, +216, 60,115,230, 76,225,197, 23, 95, 44,151,243, 7,128,236,236,236,173, 68, 84, 33, 37, 37,165,117,187,118,237, 84,211,166, 77, +219, 20, 28, 28,188,233,210,165, 75, 25, 59,119,238,140,117, 56, 28,248,249,231,159,173,233,233,233, 70,189, 94,255, 75,105, 99, +168,139, 79, 2,116, 55, 37,141, 2,144,101,101,150,201, 84,114,245,191, 7, 81, 20, 49, 96,192, 0,220,235,119,229,161,164, 0, +192,179,229,235,140, 16, 69, 17, 31,126,181, 3,193, 26, 37, 76, 86,239,243,166,216,237, 46,199,174,187, 84,136,139, 83,142, 67, +165,189,128,218, 93,130, 17,196,159, 71,237,159,191,131,221,110, 1,138,213, 5,120,195,233,116,214,189,125,251,246,200,121,243, +230,189,254,229,151, 95, 94,120,249,229,151,127,104,217,178,101,142,195,201, 96, 3,231,188,126,237, 90,196,175,191,254,250, 72, + 65, 65, 65, 77,167,211, 57, 19,192, 18, 95, 62,183,251,190,246, 26, 17,109, 49, 24, 12, 7,158,127,254,121, 44, 92,184, 16, 91, +182,108,105, 93,222,225,107,140,177, 27, 26,141,198,124,234,212, 41,101, 67,141, 0,166,137, 2,220, 35, 3,108,114, 24, 12, 38, + 51,174, 92,201, 98, 60,207, 31,246, 91,175, 97, 67, 20, 22, 22,162,160,160, 0,121,121,121,200,207,207, 71, 65, 65, 1,174, 92, +185, 82, 62,189,251, 99, 95, 50,128, 33,190, 28,235,163,158,167,194,254,228,189,106, 21,239, 2, 8, 15, 15,199,128, 1, 3,138, +238, 83,197,135, 51,251, 43,235,182,211, 0,192,231,110, 73,127, 40,241,138,208, 8, 52,236,177,166, 53,107, 53, 18, 13, 40, 72, + 79, 5, 23, 20, 6, 78,225,114,254,156,172, 66,124,100, 24,254,243, 88,151,136,207, 54,110,159, 11, 96,130,183,147, 48,198,140, + 0, 30, 18, 4,234,255,205, 39, 23,167,154,205,142, 38,130,200,217,236, 54,167,168,144,249, 52,139,201, 62,193,225,192,106,230, + 75, 19, 2, 0, 47,170, 10,120,142, 74,173, 42, 19, 36,141,174,126,237,202, 69,129,132, 66, 21, 81, 86, 77,193,155, 52,124, 46, +224,250,178,231, 21,119,254,197,236,207, 38,162,161, 29, 27,191,244,170,231, 61,190,216,121, 63,176,219,237, 93,199,141, 27,183, + 13, 0,108, 54, 91, 15,198,216,190, 63,235,220,190,224,190,121,213, 87, 40, 20,253,126,253,245,215,183,251,246,237, 27,238,112, + 56,184, 98,175,115, 59,118,236,208,159, 56,113,226,182,217,108, 30,107,183,219, 75, 93,147,129,136,104, 76,159,234, 15, 79, 25, +154, 48,114,225,215, 23,214,191,181, 46,187,111, 70,198, 79,101, 58,168,178,166,182, 37, 34,217,135,161,126,190,143, 13,251,253, +185,159,155, 58,117,170, 48,118,236, 88,251,119,223,125, 87, 46,231,239,193,237,212,215,201,178, 92,125,255,254,253, 15, 60,254, +248,227,138,198,141, 27,115, 73, 73, 73,182,180,180, 52,139,193, 96, 56,196,252,159,118,182,136, 59, 70, 1,184,187, 6, 98,195, +131,188,118, 13,120, 38, 2,186, 95, 24,141, 70,175, 99,255,117, 38, 11,204,118,167, 79, 93, 0, 70,163,241,142,126,127,102,119, + 32,109,251,218, 59,138, 1,253,153, 9,208, 93, 67,243, 17, 17, 45,187,118,237,218,184,241,227,199, 79, 72, 72, 72, 56, 10, 0, +155, 55,111,238,155,147,147,147, 72, 68,255,115, 58,157, 93,221, 55,102,127, 73, 33, 34, 71, 66, 66, 2,239,118, 10, 62,165,152, + 75,195,106,181, 78, 30, 50,100,200,219, 63,125,183, 66,227,124,228, 99, 24, 13, 58, 24, 12, 6, 24, 76, 22,100, 88,149, 88,184, +112,182,165,160,160, 96,170,191,122, 59,118,236,208,152, 76,166,162,150,127, 97, 97, 33,116, 58, 29, 22, 46, 92, 88, 46,189,251, +101,223,223, 17,158,231,179,102,204,152, 17, 13, 0, 59,119,238, 44,245, 56, 81, 20,125,205,196,233,137,104, 36, 0,111,215,158, +215,249, 79,188, 81,226, 98, 64, 81, 50,183, 9, 68, 15, 10, 60,199,136,120, 34,142,115,175,186,198, 17, 56,142,200, 29,238,216, +157,142,155, 55,110, 23,214,245,251,164, 68, 60, 92,213,151, 5,172, 28,211, 35, 6,248,123, 66, 68,130, 86,171,125, 81,150,229, + 54,217,217,217,189, 1, 64,163,209,108,118, 58,157,219, 77, 38,211,199,222,134, 82, 18, 17, 61,214,174, 66,247,218,149,180, 17, +111,173, 58,123, 1,192,105, 95, 38,249, 41, 67, 47,222,248, 83,239,241,111,174, 58,155, 92,146,243, 39,162,214,248,253,136, 19, +159,139, 0,137,168,137, 40,138, 47,217,108,182,229,140, 49,175,221, 97,126,216,205,105, 52,154,186,146, 36,213,214,235,245,231, +172, 86,107,138,159, 53, 24,191,163, 60, 25, 0,149, 74,149,105, 50,153,238,219, 98, 64, 60,207,103, 58,157, 78,191,244, 4, 65, +200,178,217,108,247, 77,143,231,249, 44,187,221,238,115, 65, 36, 17,133, 11,130,240,154,221,110, 31,195,113,220, 7, 78,167,115, +182,175, 35, 70, 74, 67,150,229,247, 58,116,232,240,220,174, 93,187, 22,150, 52,222,223, 95, 66, 66, 66, 86,133,134,134, 62, 54, +113,226, 68,117,116,116, 52,242,242,242,112,249,242,101,246,233,167,159,154, 45, 22,203,171, 58,157,174,196, 57, 60,254,169,122, + 1,238, 31, 62,173, 6, 24, 32,192,159,133,123, 30,134,104, 0,250,123,113,254,110, 45, 9, 64, 13,184,230,209,190,116,175, 55, +238, 0, 1,238, 23, 68,196,221,107, 80,119,151,222,227, 17, 17, 17, 47,155, 76,166, 70, 60,207,155, 69, 81, 60,114,251,246,237, +215, 24, 99,229,234, 47,254,187,235, 5,184, 63, 4, 2,128, 0,255,239, 33, 34,233,207, 30,186, 25, 32, 64,128, 0,127,119, 2, + 1, 64,128, 0, 1, 2, 4, 8,240, 47,164,196,153, 0, 3, 4, 8, 16, 32, 64,128, 0,255,191, 9, 4, 0, 1, 2, 4, 8, 16, + 32,192,191,144, 64, 0, 16, 32, 64,128, 0, 1, 2,252, 11, 9, 4, 0, 1, 2, 4,240, 27, 34,226,137,200,191, 37,206,202,214, + 11, 20, 35,253,203, 32,162,154, 60,207,123, 93, 82, 62,192, 31,199,159,183, 60, 86,128, 0,255, 15, 80,169, 84, 71, 45, 22, 75, +169,171,113,221, 61,113,135, 36, 73, 55,141, 70, 99,124,105,199,203,178,124,222,102,179, 85, 45,237,245,187,245,100, 89,190,172, +215,235,107,249,110,241,253,135,136, 36,142,227,126,108,210,164, 73, 19,158,231,175, 58,157,206, 86,229,156, 20,199,163,199, 24, + 99,158,199,251, 55,235, 80,128,191, 45, 68, 20, 78, 68, 63, 76,153, 50,229,250, 95,109,203,191,153, 64, 6, 32, 0,136,200,251, + 20,105,222, 53,136,136,158, 33,162,239,137, 40,147,136,110, 17,209, 86, 34, 26, 69, 68,126,255,206,136,136,147,120, 26, 19,174, +228,126, 81,138,156, 78, 45,113, 5,225, 42, 97,159, 32,208,127,168, 28, 83,211,253,166, 71,191, 40, 69,210,169, 69,174, 32, 92, +197,249,173,231,112, 56,106,158, 58,117, 74, 40, 44, 44, 20, 10, 11, 11, 5,157, 78, 39,232,245,122, 65,175,215, 11, 6,131,161, +104, 51, 26,141, 66,122,122,186, 96, 50,153, 42,151,165,103,179,217,170,158, 61,123,214, 39,189,180,180, 52,193,108, 54,151, 26, + 44,252,145, 16,145, 64, 68,245,220, 43,103, 70,180,108,217,178,241,215, 95,127, 29, 50,109,218,180,250, 0, 86,223,131,110,209, + 4,160,158, 32,224, 62,216,218, 70,161, 80, 92,116,175,161,238,183, 61,254,110,247,106,175,159,246, 69, 18, 81,172,143,199, 86, + 34,162, 42, 94,142, 9, 37,162, 56, 31,245, 98,136,168,186, 47,199,122,209, 81, 0,216, 48,124,248,112,219,172, 89,179,124,250, + 44, 1,254, 24, 2, 25,128,127, 57, 68,164, 6,144, 78, 68,227, 24, 99, 62, 47,196,116,151, 70, 4,128, 53,112,173,175, 61, 7, +174, 53,185, 29, 0,154, 1,152, 4, 96, 32, 17, 13, 40,109, 14,251, 18,244, 42,104, 36,108,238,255,240,131, 9, 83, 95, 24,164, +140,141,141,133,195, 88,128,243, 41,103,218,190,186,100, 75,211,131,103, 46, 14, 39,162,199, 24, 99, 37, 46,138, 83,154,222,128, +206, 15, 38,188, 58,226, 49,101,108,100, 24,236,133,217, 72, 73, 62,211,246,149,229, 63, 55, 61,145,150,233,151, 94,133, 10, 21, +112,252,248,113, 88,173,214,162,101,103, 69, 81,132, 36, 73, 69,207, 69, 81,132,103,181, 55,111,196,197,197, 33, 41, 41,233,142, +121,242, 5, 65,184, 67, 79,146, 36,216,237,190, 79,154, 73, 68, 53,227,227,227,215,214,168, 81,163,202,238,221,187,183, 59,157, +206,105, 28,199,205,110,221,186,117,231, 43, 87,174,164, 95,187,118,237, 73,198,152, 79, 11,217,184, 3,196, 83,205,154, 53,139, + 62,121,242,100,174,221,110,239,121,228,200,145,140,212,212,212,208, 23, 94,120,129, 59,114,228,200, 67, 68,244, 44, 99,204,167, +121,241,139,233,118,112, 63,122,156,127,209,126,198,216, 30,127,180,138,105,182,169, 92,185,242,143,139, 22, 45, 82, 63,241,196, + 19, 91,137,168, 59, 99,108,191, 63, 26,223,126,251, 45, 0,192,233,116,194,233,116,130, 49, 6,167,211, 53,103, 79,241, 96, 5, + 0,158,122,234,169,242,152,121, 47,136, 0,222, 38,162,247, 25, 99,165, 46, 85,235, 14,126, 30, 3, 48,223,139, 30, 15, 96, 30, + 17, 45, 41,235,123, 34,162,102, 0, 6,193,181,210, 95,185,113, 7,219,203,218,182,109, 27,181,116,233,210, 90,118,187,253,156, +175,171, 52, 2, 64,100,100,228,151, 57, 57, 57,115,124, 93,165,207, 7,123,186, 2, 56,228, 94, 23,224, 95,199, 63, 62, 3, 64, + 68, 79, 18,209, 38, 34,202,117, 63, 62,249, 87,219,244, 15, 35, 17, 64, 24,128,126,247,160,177, 24,192,121, 0,173, 25, 99,155, + 24, 99, 55, 25, 99, 89,140,177, 31, 0, 60, 4, 96, 31,128, 85,190,180,180,137,136,130, 36,108, 88, 57,247,165, 70, 75, 23, 76, + 83, 86,205,217, 7,121,207, 60,168,143, 46, 65, 19,225, 50,126,152,242,136,122,204,163, 45, 90, 4,171,132, 85,190, 24,230,209, + 91, 51,127, 92,163,197,179,199, 41,171,231,236,134,234,151,119, 16,148,188, 22, 45, 85, 55,176,107,108, 83,245,208, 86,113,205, +131,100,126,141,175, 31,150,136,224,112, 56, 96,183,219,225,112, 56,138,156,196,226,197,139,225,112, 56,238, 88, 24,196, 87, 61, +187,221,254, 59, 61, 83,163, 70, 69, 90,254,232, 1, 64,120,120,248,119,169,169,169,245,119,238,220, 25,246,221,119,223,117,232, +218,181,107,210,218,181,107, 59,108,220,184, 49,124,239,222,189,245, 67, 67, 67,191,243, 89, 12,104,216,188,121,243,184,117,235, +214,133,174, 94,189,186,122, 84, 84,212,110,155,205,182,110,244,232,209, 57,102,179, 25, 31,127,252,177, 38, 44, 44,236, 13,119, +203,206,215,207,220,129, 49,182,231,238,148, 63, 99,140, 24, 99,123, 60,193,129, 63,120,156,255,193,131, 7,213,146, 36,225,185, +231,158,211, 40, 20,138,173,254,102, 2,136, 8,167, 79,159,198,185,115,231,112,249,242,101, 92,191,126, 29, 89, 89, 89,184,125, +251, 54, 10, 11, 11, 97, 52, 26, 97,179,217,124, 90,253,240, 46, 93, 65,161, 80,188,174, 86,171, 47, 11,130, 96,211,104, 52,151, +149, 74,229,235,238,172,138, 79, 48,198,110, 2, 88, 6, 96, 19, 17,229, 20,203, 68, 20,205,168, 71, 68,221, 0,124, 13, 96,185, +183,160,214,253,250, 39, 0,214,151,246, 61,185,247,127, 15, 96, 37, 99,172,220, 43, 75,186,153, 93,181,106,213,150, 59,118,236, +168,165,211,233,112,246,172,127,126,156, 49,214, 35, 46, 46,110, 55, 17, 37,220,163, 29, 30, 66, 1,116, 34,162,144,251,164,247, +143,194,107, 0,224, 78,237, 46, 33,162, 60,247,227,223,166,143,142,136,166, 0,152, 10, 87, 10,178,161,251,113,170,123,255,189, +232, 10, 68,244, 57, 17, 69,222, 7, 51,255,238, 60, 8, 96, 11, 92,173,117,191, 33,162,222, 0,106, 2,120, 25, 0, 35,162, 23, +136,232, 20, 17,165, 18,209,203,112,101,153,166,193,213,210, 24,233, 77, 79,228,240,220, 19, 15,183,170,215,171,123,103,206,246, +237, 75,120,111,253,110,212,127,235, 12,234,191,121, 18, 11,183,158, 6,203, 76,197,235,189,106, 9, 17, 90,101,107,247,185,189, +234, 13,120,164, 67,189, 71, 58, 60,200,217,190, 29,139,255,125,123,192, 25,255,230, 69,125,245,249,231,116, 31,238,186,204, 96, + 42,192, 59,189,171,139,209, 65,138,150, 68, 52,192,199,207, 92,212, 42, 47,190,241, 60, 95,244,220,223, 21,192,138,191,199,179, +121,246,223,189,175, 12,187,234, 68, 71, 71,175, 15, 13, 13,205,235,217,179,103,221,148,148, 20, 41, 41, 41, 9, 81, 81, 81, 49, +235,215,175, 15, 14, 13, 13,141, 57,112,224, 0, 78,157, 58, 37,181,107,215,174,110, 72, 72, 72, 94,116,116,244,122, 34,170, 83, +134,166, 8,128, 59,118,236, 88,214,154, 53,107, 88,155, 54,109,176,109,219,182,152,250,245,235,143,189,116,233,210, 47,243,231, +207,183, 70, 71, 71, 99,192,128, 1,225, 0,158,240,241,251, 99, 0,188,173,157,176,219,159,244,122,113,231,159,146,146,130, 51, +103,206,160,110,221,186, 24, 63,126,188, 70,150,101,191,130, 0,198, 88,209, 2, 66,213,171, 87, 71,223,190,125,241,194, 11, 47, +160,119,239,222,168, 86,173,218, 29, 89, 26, 63,236, 19,100, 89, 62,208,175, 95,191, 87, 15, 29, 58, 84, 37, 63, 63, 95,216,185, +115,103,149,206,157, 59,191,162, 86,171, 15,248, 25, 4,108, 7,240, 2,128, 16,198, 24,110,222,188, 89, 8,160, 97,177, 46,137, +239, 0, 60,198, 24, 59,227,163,222, 1,184, 26, 0,191, 11, 2,220,127,175, 7,208,143, 49,118,220, 87, 27, 75,130,136, 70,132, +134,134,142, 56,122,244,104,149,188,188, 60,164,166,166, 34, 37, 37,197, 47, 13,133, 66, 97,221,181,107, 87,204,125, 12, 2,108, + 0,118,225, 95, 26, 4,248,146, 1,120, 30, 64, 29, 0, 77,220,143,207,151,247,100, 68,212,204,237, 88, 79, 18,145,201,253,248, +185, 59,189,228,175,214, 83, 0,254, 3,160, 51, 99,108, 45, 99,236, 58, 99,108, 45,128,206, 0,254,227,126,189,188, 36, 2, 24, + 14,160,245, 61,104, 20,225, 14,162, 90,221, 15,173, 63,128,150, 0, 86, 2,224,136,168, 26, 17, 13, 39,162, 51, 68, 20,229,227, +251,251, 0,248,208, 61,213,238, 16, 0,207, 0, 24, 3, 96,132,251,181, 81,238, 57,207, 23, 0,232,229, 77, 76, 43,209,160, 41, +255,233,173,196,161,207,177,228, 72, 1,174,134,183,193,158, 31, 55,225,155,183,198, 96,117,210,109, 44, 61,144, 9,137, 89, 48, +225,209, 6,234, 16,149,194,235,210,160, 90, 9,131, 38, 13,235,165,164, 3,159,226,163,195, 58,231,244,221,186,147,215, 10,236, + 93, 46,231,218,122, 78,217,122, 51,121,217, 9, 35, 19, 35,171, 97,106,207, 4, 77,136, 74, 26,232, 77,207,211, 26, 23, 69, 17, +171, 87,175,198,242,229,203,139,210,245, 60,207,255, 46, 48,240, 5,143, 94,135, 31, 51,208,122,243,213, 82, 3, 0,111,171,217, +197,197,197, 45, 93,176, 96, 65,223, 91,183,110,133,244,239,223,159,154, 52,105,130,196,196, 68,212,174, 93, 27, 6,131, 1, 53, +106,212, 64,143, 30, 61, 80,181,106, 85,180,110,221,154,118,237,218, 21, 50,109,218,180,190,113,113,113, 75, 75,177, 75, 4,112, +162,121,243,230,219,136, 72,158, 54,109, 90,218,164, 73,147, 44, 21, 43, 86,196,146, 37, 75, 66, 4, 65,104,188,126,253,250, 92, +142,227, 48, 96,192, 0, 17,192,139, 62,124,214,162, 62,255, 98, 14, 11, 86,171,245,119,251, 46, 94,188,232, 83, 77, 64,113,231, +159,156,156,140,211,167, 79, 23, 45, 23,221,176, 97, 67, 76,159, 62, 93,163, 84, 42,125, 14, 2,156, 78,215, 74,132, 53,106,212, + 64,207,158, 61, 97,181, 90,145,156,156, 12,171,213,138,166, 77,155,162, 66,133, 10, 62,175, 46,232, 65,146,164, 41,125,250,244, +169,247,217,103,159, 41,121,158, 71, 74, 74, 10,194,194,194,240,241,199, 31,171,154, 55,111, 94, 71,150,101,127, 27, 45,187, 0, + 24, 0, 88,140, 70,163, 5,112, 5, 46,185,185,185,133, 0, 44,101,117, 15,148,132, 59,253,223, 15,192,174, 98, 89,133, 12,252, +230,252,253,234, 70,185, 27, 34,122, 88,169, 84, 46, 56,120,240, 96,100, 94, 94, 30, 82, 82, 82,144,146,146,130, 27, 55,110,248, + 93, 67,145,144,144,128,251, 25, 4,184,211,255,255,202, 32,160,204, 0,192,221,218, 31, 11, 96, 34, 99,236, 10,128,137, 0,198, +250,155, 5,112,183,168,103, 1,216, 12, 32, 25,192,179, 0,162,220,143,201, 0, 54, 19,209, 44, 95,163, 96,247,249, 95, 7, 48, +156, 49,150, 89,252, 53,247,223,195, 1,188,126, 15,217,138, 78, 0,140, 0,252, 46, 34, 42,133,247, 0,236, 33,162, 63,109, 25, + 97, 63,104, 9,224, 87,184, 46,244,233,112,245, 25,102, 1, 24,234,227,251, 19, 1, 28,117, 63, 31, 9, 96, 26, 99,108,175,187, + 85, 49, 17,191,181,250, 79,185,143, 45, 19,147, 29,141, 98,162,194,129,188,116, 44, 58,164,195,171,163,134, 33,226,228, 18,212, + 54,159,194,236, 62,245,176,244,231,171,128,168, 68, 98,173, 10,112, 2, 45,124,209,139, 10, 11, 2,242,174,224,189,131, 70,163, +222,202, 70, 49,198, 14, 48,198,246,233, 45,206, 23,223,250,241,162, 1, 97, 85,208,176,106, 4,156,204,187, 30,240,155,195, 30, + 57,114, 36, 70,141, 26,133,101,203,150,129,231,121,240, 60,143, 69,139, 22,225,189,247,222, 3,199,113,126, 7, 0, 71,251,214, +196,201,129,117,209,104, 77, 74,209,123,111, 86,174,140,244,216, 88,159, 2, 10,155,205, 22,209,172, 89, 51,156, 60,121, 18,151, + 47, 95,134, 94,175, 71,118,118, 54, 12, 6, 3,244,122, 61, 12, 6, 3,146,146,146,160,215,235,113,233,210, 37,156, 56,113, 2, +181,107,215,134,205,102,139, 40, 69,178, 94,155, 54,109, 42,108,218,180, 41,244,155,111,190,169, 20, 21, 21,165, 89,185,114,229, +141, 79, 63,253,212,217,184,113, 99,188,248,226,139, 21,114,114,114,162,127,254,249,103,180,109,219, 22, 90,173,182,162,151,207, +121, 71,193, 31, 99, 12, 14,135, 3,102,179, 25, 22,139, 5,183,111,223, 70, 70, 70, 6,210,211,211,145,150,150, 6,139,197,130, + 19, 39, 78,148, 25, 4,148,229,252, 61, 91,211,166, 77,177, 96,193, 2,141, 74,165,242, 57, 8, 16, 69, 17,205,155, 55,199,245, +235,215,145,159,159, 15, 81, 20, 97,183,219, 97,179,217, 80,189,122,245,162, 44,128,175, 8,130, 48,252,213, 87, 95, 85, 94,188, +120, 17,185,185,185, 16, 4,161,168,187,103,220,184,113,106,133, 66, 49,220,103, 49, 23,102, 0, 70, 34, 82,212,168, 81, 35, 18, +128, 19, 46,199,111,246, 83,167, 8,183,147,151, 60,255, 27, 0, 49,184, 71,231, 63,127,254,252,224,225,195,135,143, 81, 40, 20, +223,110,220,184, 81,101, 54,155,249,148,148, 20, 36, 37, 37, 97,225,194,133,215, 95,125,245,213, 50, 87, 8, 45,141, 64, 16,112, +127,240,150, 1,232, 12,192,232,190,153,123, 82, 69, 70,247,126,127,152, 14, 87,107,186, 33, 99,236, 29,198,216, 97,198,152,206, +253,248, 14, 92,233,251,214,238,227,124,161, 51, 0, 3, 99,108,111, 73, 47,186,247, 27,202, 97, 39,136, 72, 3, 96, 20,128, 97, + 0,158,190,215, 31, 3, 17,189, 14, 87, 63,120, 29, 0, 61,136,104,252,189,232,221, 15,220, 1, 89, 5,114,141,227,182, 50,198, +174, 1, 88, 10,215,247, 53, 9,174, 66,190,193, 62,202,241,112, 21,252, 1,174,116,154,178,216,107, 74,247, 62,184,143,241, 90, + 21,199, 0,206,105,184, 13,240, 18, 64,132,172,227,219, 1,139, 30, 16,149,112,112, 18, 64, 28, 32, 42,193, 75, 50,152, 15, 25, + 44, 6,226,156,186,108,128, 19, 32,242,196,112,231,242,191,178, 70, 45, 19,212, 97,224, 69, 5, 24,152,207, 53, 49,162, 40, 98, +217,178,101, 88,178,100, 73,145, 3,231,121, 30, 19, 39, 78,196,180,105,211,240,254,251,239,131,227,124, 47,177, 17, 69, 17,137, + 95, 95, 64,163, 53,174,148,168,199,217,215,202,205, 69, 61,157, 14,201, 90,173,215, 0, 32, 47, 47,239,133,190,125,251, 22,232, +116, 58,244,234,213, 11, 7, 14, 28,128, 78,231, 90,127,189, 66,133, 10, 48, 24, 12, 40, 44, 44,196,129, 3, 7,240,192, 3, 15, +192,225,112, 96,212,168, 81, 5,121,121,121, 47,148, 34,121,246,224,193,131, 55, 86,174, 92,201,218,183,111,143, 61,123,246,196, +214,173, 91, 55,100,206,156, 57,186,130,130, 2, 60,243,204, 51, 2, 0,235,249,243,231,193,113, 28, 34, 34, 34, 68, 34,186,123, +121,229, 34, 24, 99, 69, 49,185, 39,147,194,243, 60,100, 89,134,213,106, 69,120,120, 56, 98, 99, 99, 17, 31, 31,143, 26, 53,106, +192,106,181,162,113,227,198, 40,109,104, 32, 17,181,169, 82,165,202,143,135, 14, 29, 82,199,198,198,150,232,252, 61, 91,243,230, +205,177,104,209, 34,159,130, 0, 79, 23, 64,108,108, 44, 12, 6, 3, 84, 42, 21,148, 74, 37,148, 74, 37, 68, 81, 68, 72, 72, 72, + 81, 23,129,175, 88, 44,150,138,149, 43, 87,134, 94,175, 47,210, 82, 42,149, 80, 40, 20,168, 95,191, 62, 12, 6, 67,153,193, 83, + 9, 54,154, 1, 84, 5,224,105, 0,241, 68,164, 8, 15, 15,143, 2,112,197, 31,173,146,204,117,111,184, 23,231, 63,117,234,212, +233, 6,131, 33, 43, 39, 39,103,174, 32, 8,154,180,180, 52, 62, 57, 57, 25, 75,151, 46,205,155, 50,101, 74,193,241,227,199, 55, + 88,173,214,118,229,213, 15, 4, 1,247,142,183, 95,240,235,248,125, 21,233,124,247,254,237,190,156,192,157,222,127, 22, 64,227, +210, 10, 82, 24, 99, 57, 68, 52, 8,192, 9, 34,218,192, 24, 75,242, 34,219, 15,192,167, 94,142,249,212,125,156, 79,118, 22, 99, + 38,128,157,140,177,245, 68,212, 9,192, 92,184,250,219,252,134,136, 70,193,213,146,110,195, 24,203, 32, 87,197,233,126, 34,186, +205, 24, 91, 86, 30,205,251,196,123,112,181,204,119,195,253,253, 48,198, 78, 2,136, 3, 92,147,188, 0,136, 35,162, 74,238,224, +160, 44,142,194,213,178, 63, 1, 96, 17,128,185, 68,228, 4, 96,133,235,187, 91,228, 62,174, 1,126,203, 20,148,138, 74,226, 78, + 93, 72, 77,121, 48, 81, 19,133,231,219, 85,196,136,121, 43,241,246,147,141,192,137,118, 76, 93,127, 26,255,233, 92, 31, 16, 85, + 56,122, 57, 29, 2,207,121,215, 19,113,234,194,217,148, 7, 19, 53,145, 24,223,222,160,121,245,135, 27, 31, 19,209,243, 0,148, + 90,153, 95, 56,115,248, 35, 42, 56, 28, 56,125,195, 0,129,243,174, 7,184,156,215,146, 37, 75,240,252,243,207, 67,169, 84,226, +147, 79, 62,249, 93, 13,128,175,206,223,227, 8, 27,174, 78,198,217, 97, 77, 32,138, 34,170, 47, 57,124, 71, 23,128,175, 45, 77, +155,205,182,139,136,250, 15, 26, 52,232,101,179,217,252, 0, 0,165, 36, 73,138, 45, 91,182,208,154, 53,107, 80,181,106, 85,244, +235,215,143, 89, 44, 22, 11,199,113, 38, 89,150, 15,101,103,103,255,143, 49,182,171, 36, 61,198,152,153,136, 90, 78,156, 56,113, +227,249,243,231, 31, 92,184,112,161,252,214, 91,111,133,245,236,217,211,178,127,255,126,244,238,221, 27,145,145,145,134,130,130, + 2, 5, 0, 4, 5, 5,241, 0, 34, 0,148, 58,182,219, 29, 4, 48,207,115,247,119,192, 44, 22, 11,238,222, 87,150,243, 7, 0, +133, 66,241,218,149, 43, 87,212, 53,107,214, 52,235,116, 58,121,198,140, 25,230,194,194, 66,121,224,192,129,214, 49, 99,198, 72, + 61,123,246, 52,231,230,230,202,131, 7, 15,182,206,154, 53, 75,234,217,179,167,217,104, 52,106, 52, 26,205,107, 0,186,150,245, + 93,138,162,136,140,140, 12, 4, 7, 7,195,233,116, 66,150,101, 40, 20, 10, 40, 20, 10,152, 76, 38,191,107, 0,100, 89,190,126, +230,204,153, 42,225,225,225,112, 58,157, 69, 1,128, 74,165,194,217,179,103,161,209,104,202, 51, 30, 94, 6,160,100,140, 33, 47, + 47,207, 18, 22, 22,102,102,140,221,171,227, 74, 39, 34,207,188, 21,233,229, 21,121,237,181,215, 94,201,207,207,159,148,147,147, +163, 8, 11, 11, 83, 84,172, 88, 17,227,198,141, 19, 36, 73,202, 53, 24, 12,199, 29, 14,199,139,140, 49,255, 10, 0,220,228,228, +228, 32, 35, 35, 3,199,143, 31,199,171,175,190,170,179, 90,173,138,136,136,136,169, 0,158, 46,143,158, 59,104, 85,194, 85, 16, +216, 12, 0,193,149, 93,244,215,119,252,227, 40,245, 23, 76, 68, 61,224, 90, 71,125,237, 93, 47,173, 5, 48,137,136,122, 48,198, +182,248,112,142, 81, 0, 22,220,157,170,191, 27,198, 88, 38, 17,189,237, 62,126,132, 23,205, 26,112, 85,194,150, 69, 50, 0,191, + 70, 4,144,171,120,176, 43,128, 14,238, 93,147,225,234, 19,155,197, 24,123,205, 79,173,129, 0,166, 0,104,199, 24,203, 0, 92, + 21,188,238, 32, 96, 15, 17,229, 50,198, 54,249,160,115, 5, 64,169, 19,201,148, 64, 58, 99,172, 74, 25,122, 60, 92, 65, 73,123, +184,254,151,191, 27,214,195, 24,115, 16,209, 22, 0, 61,241,155, 3, 47,141,205,112,117, 11, 45, 99,140,173, 33, 34, 11, 92, 1, +147, 8, 87,176,248,149,187,217,247, 50, 92,149,196,101,162, 51,179,245, 51,191,220,221,104,211,164,206,170,145, 29,173,128,164, +198,232,149,167, 64, 28,135, 81,143, 52,194,127,186, 53,131,157, 83,224,253, 13, 71, 12,121, 58,147,215,202,125,157,133,214,207, + 92,181,175,209,166, 81,205, 84, 35,219,218, 72, 27, 25,155,240,222, 79,215, 54, 43, 21, 10, 76, 27,214, 85,211,165, 83, 7, 56, + 46,254,130,249, 27, 79,234,243, 12,150,245,222,244, 60, 14,251,165,151, 94,194,135, 31,126, 8, 0, 69,142,159,231,121,188,251, +238,187,224, 56, 14, 83,167, 78,245,107, 20,192,197,103, 91,160,250,146,195, 69,251, 36, 73,130,157,227,112, 70,163, 1, 0,180, +112, 58, 97, 54,123,207,238,186, 11,196,138,110, 92,146, 36,237, 55, 24, 12,173, 43, 85,170, 4,189, 94,143,130,130,130, 95,109, + 54,155, 63, 5,113, 58, 0, 15, 17,209,169,158, 61,123, 54,232,213,171, 23,226,226,226,184,195,135, 15,163, 79,159, 62,104,208, +160,129,186,160,160, 0, 0, 16, 28, 28, 44,193, 75, 0,224,214, 36,186,171,202,223, 83, 3, 80,140,142,222,134, 2,154,205,230, +174,192,111,179, 8, 22, 22, 22,202,140, 49,154, 57,115, 38,139,140,140, 68,110,110,110,209,223, 65, 65, 65,184,117,235,150,236, +203, 68, 67,228, 30,113,145,154,154,234,201, 64, 20, 21,105,138,162,136,179,103,207,250,157, 1,112, 56, 28, 95,204,157, 59,247, +149, 69,139, 22,169, 24, 99,144,101, 25, 74,165, 18,178, 44, 99,198,140, 25, 6,171,213,250,133,207, 98,191,167,168,197,126,175, + 48,198,170,208, 61, 78,200, 52,126,252,248, 71,242,243,243,167, 55,109,218, 84, 89,177, 98, 69,108,222,188, 25,217,217,217, 80, + 40, 20,102,157, 78,183,192,225,112,220, 83, 87,232,240,225,195,245,113,113,113,154,183,223,126, 27, 99,198,140,185, 86, 80, 80, + 80,239, 94,244, 0,180, 2, 96, 7,112, 16, 64,125, 95,238,203,255, 95,248,221, 47,152,136, 84, 0,218,193,213,130, 30, 86,212, +105,231,134,185,174,222,137, 0,150, 17,209,127, 0,236, 99,140, 25,203, 56, 71, 51,184,134,153,248,194, 47,240, 45,138,171, 10, +224,170,151, 99,174,185,143,243, 10, 17, 85, 5,240, 33, 92, 45,224, 78,158, 76, 5, 99, 44,143,136, 30,134,171, 70,161, 29,128, +209,140,177,211, 62,232,117, 7,240, 62,128,135, 25, 99, 23,139,191,198, 24,187, 64, 68,143, 2,216, 74, 68,249,140,177,125, 94, +228,226,253,185, 24,125, 40,154,106, 10,224,138,187, 59,167,172,192, 98, 37,128, 37, 68,180,209, 61,244,168, 68, 24, 99,171,136, +232,105, 0,179,136,104, 10, 99,236, 91, 0,223,222,101,211, 43,112,205, 17,240,161, 55,251,109, 78,231, 7,251,146,175, 61,243, +222,166,163,117, 94,126,184, 26,247, 66,215,122,120,161,103, 51, 64, 84, 2,162, 18,140,151,241,234,138,189,142,107,183, 11,143, + 51,198,188, 14, 5,116,233, 93,127,230,221, 31,228, 58,227, 59,198,113,131,219,198, 97,112,175, 78, 26,104,162, 0,167, 3,236, +210, 47,152,186,250,128, 35, 61, 71,119, 26,128, 79,243, 32,120, 82,254, 47,191,252,242, 29, 5,122,175,189,246,154, 95, 78,161, + 56,162, 40,226,250,232,182, 69, 69,132,162, 40,162,133,217, 92,110, 61, 15, 54,155,205,162,211,233, 28, 61,123,246,228, 87,173, + 90,229,176,219,237,229,117, 20, 63,238,223,191,191, 65,175, 94,189, 80,189,122,117, 46, 55, 55, 23, 0,160,209,104, 4, 79, 0, + 16, 20, 20,164,128, 43, 0,240, 74,177,161,126,187, 1,192,147, 1,112,255,126,189, 58,255,146,232,223,191,191,117,230,204,153, +172, 75,151, 46, 78, 65, 16,238, 72,193,248,251, 61,138,162,136,156,156, 28,156, 62,125, 26, 53,107,214,132, 74,165,130,201,100, + 66,106,106,106, 81, 77,128, 63,154,102,179,121,238,158, 61,123, 30,125,234,169,167,234, 76,154, 52, 73, 93,191,126,125,156, 61, +123, 22,211,167, 79, 55, 36, 37, 37,165, 26,141,198,185,126, 25,232,150, 5, 96, 34,162, 96, 0, 10, 0, 39,203,161,113, 95,121, +230,153,103,106, 23, 22, 22,174,169, 92,185,178,210,100, 50, 97,217,178,101,216,178,101, 11, 24, 99,118,187,221,158,193, 24,187, + 39,231,175,211,233,148, 71,143, 30,253,197,104, 52, 86,124,251,237,183,235,245,239,223,191, 46, 17, 61,232,233,166, 46, 7, 74, + 0,121,112, 13,133,102, 0, 10,136, 40,146, 49,118,235, 94,236,252,167, 80,210, 47,248, 69,184,170,181,159,101,140,237, 44,233, + 77,140,177,157, 68,244, 44, 92, 93, 1, 50, 92, 78,165, 52, 8,174,244,176, 47,156, 0,176,206,135,227,150, 1, 40,213, 41,185, +185, 1, 87,191,182, 47,172,131,171, 53,252, 62, 99,236,142,217, 86, 24, 99,185,238, 62,195, 17, 0,214, 17, 81, 19, 31, 10,109, +102, 3,120,130, 49,118,170,164, 23, 25, 99,199,200, 53,228,108, 54, 92,193, 86, 89,164,250,244, 9,124, 63,254, 99,184, 42,242, +203,196,253, 63, 94, 6, 96, 3,188, 23,219, 13, 7,240, 21,128,157,238, 44,206, 17,184,250,252, 19, 1,188, 4, 32, 26,174, 98, + 34,175, 5, 63,238,236, 67,207,153,223,156,222,250,195,137,155,149, 38, 61,222, 68,157, 88,171, 34, 28,118,224, 72,202, 13,204, + 94,243,179, 62, 37, 61,251, 66,161,193,210,223,155, 86,113,189, 89, 91, 46,109,253, 49,229,118,165, 73,143, 88,213,137,213, 77, +112,112,151,112, 36,189, 16,179,191, 61,161, 79,185,118,251, 66,161,209,218,231,238, 96,183, 52,174, 92,185, 2,165, 82, 9,158, +231,139, 38,137,113, 58,157, 69, 99,249,253, 37, 35, 35,163,104, 34,156,178,244, 60, 78,210, 79, 46, 94,188,120,241,129,149, 43, + 87,170,175, 92,185, 98, 6,112,209,235, 59, 74,102,107, 90, 90,218, 40, 0, 42,173, 86,235,200,200,200,112, 2, 16,237,118,187, +227,198,141, 27, 78, 0, 34, 99,140,131,203, 17,249,132, 59, 8, 64,106,106, 42,172, 86, 43,142, 30, 61,138,196,196, 68,148,199, +249, 3,192,216,177, 99,165,200,200, 72, 8,130,192,229,231,223, 57,175,139,159, 67,246,138,106, 58, 10, 10, 10,112,226,196,137, +162, 22,191,167,250,223,223, 12, 0, 99,204, 78, 68, 15, 30, 57,114,100,202,224,193,131,135, 27, 12,134,138, 26,141,230,186,213, +106,253,194,104, 52,206,189,251,190,227,163,166,153, 92, 67, 56,175,220,135,212,255, 61,211,167, 79,159,150,249,249,249, 59,242, +242,242, 84, 23, 46, 92,192,181,107,215, 80, 88, 88,104,115, 7,157, 71,224, 61,179,235, 21,142,227, 86,101,102,102,190, 14,224, +201,213,171, 87, 47,252,239,127,255,139,165, 75,151,142, 4, 80,222, 0, 32, 11,174, 34,232, 26,238, 45, 21,174,122,173,127, 69, + 0, 64, 62,222,243, 2, 4, 40, 19,114, 77,247, 59, 10, 64, 95, 0,141,224, 42,208, 59, 5, 96, 19,128,119,253,189,193, 17,145, + 32, 75,194, 36,149,196, 15,212,155,237, 53,137,192,212,178,226,156,193,106, 91,102,177,216, 62, 96,174,161,133,229,208,227,220, +122,196,212, 10,233,156,193, 98, 95,102,177,249,174, 23, 20, 20,116,212,104, 52,150,186, 22,192,221, 40, 20,138,155, 6,131,161, +212, 76,139, 70,163, 57,239,207,244,190, 74,165,242,178, 78,167,243,121, 45, 0, 34,138, 81,169, 84, 75,162,163,163, 19, 51, 51, + 51,143,154, 76,166,103,189,117,199,149,162, 19, 77, 68,199, 58,118,236,168,248,233,167,159, 76, 68,132,182,109,219, 42,247,237, +219,103, 34, 34,180,107,215, 78,185,119,239, 94, 19,128,154,254, 86,162, 19, 17, 59,114,228, 8,154, 55,111, 94,102,159,127, 89, +239, 47, 44, 44,196,254,253,251,139, 82,235, 74,165,178,168,128,112,230,204,153,108,242,228,201, 80, 40, 20, 94,245,137,136,125, +251,237,183,176,219,237,119, 56,125,207,198,243,252, 29,127, 55,107,214,172, 92, 54,223, 47,220, 69,203, 27, 25, 99,157,238,163, +230, 33,198,216, 3,254,190,175, 89,179,102,155, 11, 11, 11,187, 20, 20, 20,152, 11, 11, 11, 77, 22,139,229, 28, 92,221, 81,187, + 25, 99,191,222, 47,251,220, 54,134, 52,110,220, 56,243,240,225,195,138,216,216,216,179, 57, 57, 57,165,206,101,225,163,158, 4, +160, 59, 92,247,171, 71,124,236,222,254,199, 19, 8, 0, 2,220,119, 60,165,222,190,182,168,255,233,122,255, 22,136, 40, 20,174, + 22,190,167,195, 94,186,251, 57, 99, 44,183,156,218,229,238,119,150, 36, 41,211,102,179, 69,223,189, 95,150,229, 44,147,201, 20, +147,152,152,152, 99,181, 90,195,211,210,210,178,140, 70, 99,140, 55, 59,252, 61,255, 95, 28, 0, 40, 0, 60,199, 24,123,255, 62, +106, 78,100,140,121,205, 18,254,213, 16, 81,239,160,160,160, 73,133,133,133,243, 25, 99,254,204,108, 89,154, 94, 45,184,186,141, + 47, 49, 31,167,201,254,167, 19, 8, 0, 2, 4, 8, 16,224, 31,138, 59,152,141,241, 20, 26,223, 39, 77,173,187,248, 51,192,255, +115, 2, 1, 64,128, 0, 1, 2, 4, 8,240, 47,228, 31,191, 24, 80,128, 0, 1, 2, 4, 8, 16,192,127, 2, 1, 64,128, 0, 1, + 2, 4, 8,240, 47, 36, 16, 0, 4, 8, 16, 32, 64,128, 0,255, 66, 2, 1, 64,128, 0, 1, 2, 4, 8,240, 47,228,222,166, 25, +243, 19,149, 74,149,105, 50,153,126, 55, 92,167, 56, 74,165,210,235, 80,157,251,137,123, 24,141,210,235,129,191, 97, 97,140,153, +254, 40,123,254,209,188,221, 85,128,202, 44,131,231, 21,112,130,192,129,193,225,176,192, 40,155, 49, 97,155,255, 51,228, 4, 8, +112, 15,184,231,166,168,200,113, 92,173, 26, 53,106, 84, 74, 75, 75, 59,239,112, 56,126,249,171,237, 10,240,247,133,136,132,242, + 76,202,244, 79,197,167, 81, 0,117,195,168,126,155,122,241, 35, 79, 95,202,222,119,240,166,233,155,242,142,159,166, 98,203,129, +150,113,204,159, 58,174, 86,150,229,243, 74,165, 50, 62, 40, 40,168,204,227,136, 8, 89, 89, 89,204,225,112,216,108, 54, 91,148, + 47, 65, 0, 17, 53,227, 56,238,225,144,144,144,135,156, 78,103, 13, 34, 58,157,151,151,247, 19,128,173,229, 29,103, 74, 68, 53, + 0, 60, 5,215, 66, 71,128,107, 25,223, 85,140,177,180,242,232,221, 51, 51, 59,114,136,132, 6,140,100,152, 10,148, 78, 99,182, +150, 51,235,131,156, 78,135,196,113,188,213, 41,107, 10, 57, 85,148, 14,202, 96, 19,136,153,161,130, 1,195,118,151,107, 9,208, +255,239,184,135,116,197, 73,146,148,224,112, 56,226,120,158,191, 97,181, 90,207,150, 53, 21,243,159,141,219,198, 96,158,231, 35, + 1, 48,135,195,145,195, 92,171,168,253,173, 32,162,232, 10, 21, 42,116,233,211,167,143,178,247, 19, 79, 32, 46, 46, 14,207, 61, +255, 60,126,250,233,167,207,203,186,193, 19, 17,215,164, 73,147,174,199,143, 31,175, 84,218, 49,178, 44,155, 76, 38,211,151,126, +218,195,213,171, 87,175, 75,211,166, 77, 43,127,249,101,233,111,149,101,217,108, 54,155, 87,250, 59,209, 85,177,243,200,112, 45, +227,155,233,235,132, 76,247, 58,247,255, 93, 90, 97,112,173,251,193, 1,120,199, 61,147,234,247, 0,122,184, 15,217,194, 24,235, +121,143,231, 8, 10, 14, 14, 30, 95,187,118,237,222, 10,133,162,226,245,235,215,175,223,184,113,227,176,213,106,157,123,247,212, +235, 62,234,133,132,134,134,206,126,232,161,135,186, 71, 71, 71, 87, 57,114,228, 72,214,233,211,167,127, 53,155,205, 51,125,153, +250,253,159,140, 79, 1,192,208, 86,149,222, 95, 54,241,137, 23,179,110,231,223,122,117,233,206,175,127, 62,159, 49, 55,110,166, +184, 0, 0, 32, 0, 73, 68, 65, 84,249, 98, 46, 43,240,251,100,238, 0,128,173, 30, 10, 88, 13,119,110, 22, 3,104,242,217, 63, + 61, 0,144, 36,169, 32, 43, 43, 43, 72,169,252, 45, 9, 64,197,150, 44, 45,254,120,238,220, 57, 36, 38, 38, 90, 44, 22, 75, 76, + 89, 55, 61, 34, 82,105,181,218,247, 37, 73, 26, 52,120,240, 96,177, 89,179,102, 98,213,170, 85,113,238,220, 57, 28, 62,124,216, +178,122,245,106,167,221,110,159, 99, 54,155,231,249,114,161, 19, 81, 52, 92, 11, 27, 13,170, 88,177, 98,139,129, 3, 7, 98,240, +224,193, 32, 34,172, 92,185, 18,171, 87,175,198,245,235,215, 15, 3, 88, 13, 96, 45, 99, 44,171, 44, 61,158,231,159,118, 58,157, + 62,101, 61, 4, 65, 48,217,108,182,146,239, 88,111,119, 21,160,182,134, 33,231,124, 12,204,186, 80,230,176,203,103,115,157,194, +103, 39, 29,170, 3, 55,156,242,131, 21, 56,243, 51,141,120, 99, 66, 24,103, 39, 94, 48, 59, 37, 85, 1, 23, 81,237, 22,148, 92, + 54, 70,236,183,149, 36, 73, 68, 45,241, 91, 70,198, 2, 32, 27,174, 41, 58,163,225,154,182, 51, 13, 64, 20,126,155,114,214,196, + 24, 59,232,203,103,113,235, 15, 2,160,113,255,169,103,140,173,246,245,189, 94,116, 43,132,134,134, 62,168,215,235, 67,180, 90, +109, 94, 65, 65,193, 49,187,221,126,217,199,247,134, 8,130, 80, 27, 64, 77,133, 66,225,236,210,165,203,205, 1, 3, 6,228,174, + 89,179, 38,108,231,206,157,113, 22,139,133, 3,112,222,110,183,159, 99,204,247,235,206,221, 2, 78,132,107,114, 19, 45,128, 66, + 0,151, 0, 28, 43,143,131,145, 36, 41, 65, 16,132,230,161,161,161,136,139,139,147,156, 78, 39, 50, 51, 51,173,121,121,121,176, +219,237, 71,172, 86,235, 89,111, 26, 10,133,162,175,211,233,244,124,255, 69,215,214, 93,118, 23, 61,231, 56, 78,111, 50,153,190, +246,199, 78, 34,226,226,227,227,159,250,113,235, 86,165, 66,161,192,175,191,254,138,111,191,251, 14, 27, 55,110, 76,182,219,237, +165,102, 0,136,136,107,216,176, 97,215,237,219,183, 87,140,137,137,161, 95,127,253,181,104,173, 7,207,250, 12,146, 36,161, 82, +165, 74, 96,140, 45,246,199,158,218,181,107,119,217,185,115,103,165, 47,190,248,130, 30,126,248, 97, 68, 69, 69, 33, 56, 56, 24, + 90,173, 22, 10,197,111,179, 39, 75,146,196,108, 54,219,231,190, 76,155,125,215, 57,148, 0,166, 7, 7, 7,255,183, 69,139, 22, + 33,167, 79,159, 46,204,204,204, 92, 12, 96, 6, 99,204, 80,198,251, 88,243,230,205,173,255,199,222,153,135, 53,117,109,125,248, +183, 79,230, 16,194, 60, 35, 40, 42,136, 32, 2,214,171, 84,173,162,173, 67,157,106, 29,107,181,218, 58, 92, 91,135, 42, 14,180, +106, 7,180,214,177,104,171,182,189,106,235, 80,253,234,112,109, 45,213,106,213,138, 56, 64,157, 16, 17, 21, 84, 4,100,146, 25, + 2, 33,211, 57,217,223, 31,129, 20, 21,146,128, 94,219,222,155,247,121,242,144,156,156,172,236, 29,206,217,107,237,181,215, 94, + 43, 37, 37,101,167, 78,167,155,209, 82,195,163,129,188,143, 39, 77,154,244,145,147,147, 19, 98, 99, 99, 83, 96, 40,180, 83, 91, + 93,109, 72, 43, 96,107,107, 11, 24,174,197, 33, 48, 76, 98,122, 3, 56, 5, 96, 42,165, 84, 97,129,252, 23,194,195,195,119, 69, + 69, 69,221, 13, 8, 8, 56, 26, 22, 22,118,171,168,168,200, 59, 41, 41, 41,252,173,183,222,234,163, 80, 40,214, 80, 74,191,109, + 70,123, 35, 95,125,245,213, 3,171, 87,175,118,210,233,116,144, 72, 36,176,177,177,129, 82,169,196,240,225,195,181,169,169,169, +179, 40,165, 91,155,255, 75,252, 61,104,212, 0,104,211,134,136, 37, 85,104, 71, 13,121,252, 65, 40,194, 22,191,214,115,209,248, + 23, 2, 2, 57, 86,171, 91,255,211,149, 11, 59,126,187, 57,243,102, 57, 77,107,214,151,213, 27, 0,187,198, 66, 50,197,112, 79, +171,214,116, 49, 26, 1,228,131,236,103,110, 0,136, 68,162, 42,133, 66, 33,255,249,231,159, 65, 41,125,168, 24, 75, 99,127,195, +194,194, 76, 26, 0,132, 16,185, 76, 38, 75, 29, 62,124,184,203,230,205,155,165,118,118,118,143,157,115,231,206, 29, 76,157, 58, +181, 38, 37, 37, 37, 85,161, 80,244, 50,117,211, 17, 66, 46,203,229,242,240,145, 35, 71,146, 9, 19, 38,160, 79,159, 62,143,149, +154,213,235,245, 56,125,250, 52,118,239,222,141,131, 7, 15, 82,133, 66,113,149, 82,218,197,132,204,233,123,247,238,133, 72, 36, +130, 70,163,129, 78,167,131, 78,167, 3,203,178,224, 56, 14, 44,203, 66,175,215,131,227, 56,204,159, 63, 31,122,189,190,241,193, +238,235,222,206,200, 79,107,123,175, 68,233,244,175, 20,206,230,183, 66,177,180, 85, 88, 63,209,224, 33, 67, 16, 17, 17,129,164, +164, 36, 28, 57,124, 24,185, 87,127,211, 68,122,168,107,167,135,242,148,237,221,108,139,225, 21,124, 23,211,227,155,250,253, 6, + 22, 20, 20,184,171,213,106,126,187,118,237,200,160, 65,131,200,176, 97,195,208,163, 71, 15,156, 63,127, 30,113,113,113, 56,122, +244, 40,189,123,247, 46, 21,139,197,172,167,167,231, 3, 74,233,177,166,250,218, 88,223,235,175,249, 58, 69,179,215,146,129,199, + 20, 66,161,176,131, 92, 46,127,126,251,246,237,252,174, 93,187,226,226,197,139,152, 52,105, 18, 91, 93, 93,125,146,101, 89,147, + 69,171, 4, 2,193, 8,134, 97,108,187,116,233, 82, 52, 99,198,140, 7, 42,149,138,196,199,199,203,203,203,203,133,142,142,142, +218,200,200, 72,133, 80, 40,164, 91,182,108,241, 72, 78, 78,118,211,235,245,149, 58,157,238, 39, 11,250,201, 0,120, 5,128,190, +119,239,222,133, 65, 65, 65,218,173, 91,183,106,117, 58,157, 31, 0, 30,128, 56, 75, 7,123, 66, 8, 35,145, 72, 94,238,208,161, +131,115,116,116,180, 48, 56, 56, 24, 2,129, 0, 55,110,220, 64,102,102, 38,174, 95,191,142,196,196, 68,109,126,126,126,169, 74, +165,250,197,204,245, 60,189,176,176, 16, 78, 78, 78,208,106,181, 80,171,213,208,104, 52,208,106,181,198, 71,253,181,120,233,210, + 37,204,156, 57,179, 89,202,182,238, 59, 28,167, 76,153, 50,106, 89, 76, 12,250, 15, 24, 64,111,220,184,113, 13,192,109,115,158, +138,206,157, 59, 15, 56,113,226, 68, 43, 87, 87, 87,134, 16,130,203,151, 47, 63,116,239,215, 63,119,119,119,111, 86,155, 2, 3, + 3,251,159, 56,113,194,199,219,219,155, 89,190,124, 57,164, 82, 41,156,157,157,225,232,232, 8,153, 76, 6,129, 64, 0,189, 94, +143,158, 61,123, 66, 44, 22, 55,203, 0,168,155,113,251, 19, 66, 86,143, 31, 63,254,133, 33, 67,134,192,217,217, 25, 14, 14, 14, +184,124,249, 50,102,207,158,125, 78,167,211, 13,108,204, 8, 32,132,208, 54,109,218,232, 46, 93,186, 36, 56,117,234, 20, 38, 76, +152,240,179, 86,171,125,229, 73,140, 0, 66,200,215,203,151, 47,255,231,210,165, 75, 49,121,242,100,236,220,185,115, 31,128,177, + 13, 13, 0,145, 72,164,138,140,140,148, 12, 29, 58, 20,125,250,244,193,252,249,243,113,236,216,177, 87,205,101,243, 35,132,140, +232,219,183,239,231,235,214,173,251, 62, 44, 44,236,115, 60, 92, 15,134,212,165, 69, 78,130,161,238,136,217, 26, 42,132,144, 17, +179,102,205,250,247,204,153, 51,153,107,215,174,129, 16, 2, 39, 39, 39,227,131,199,227,161,123,247,238,108,110,110,110,151,166, +234,186,252,221,105, 52, 6,160,111, 43,223, 13,239, 45,234, 61,152, 15,189, 30, 84, 15,232, 57, 64,207, 66,171,213,212,136, 24, + 42, 95, 56,180,211, 11,225,190,118, 63, 60,239, 37,122, 63, 49, 95,115,176,217,223,202,106,160, 97,245,198,231,198, 71, 11, 32, +132,248,193, 80,222,118,124,221,161,255, 3,176,147, 82,122,175, 25, 50,140,133, 61, 76, 41,127, 75,234,178,203,229,242,173, 19, + 38, 76,112,219,188,121,179,184,177,247,107,106,106, 96, 99, 99,131,173, 91,183,202,166, 79,159,222,249,194,133, 11,239, 3, 88, + 97, 66,100,151,109,219,182, 33, 52, 52, 20,237,219,183,111,244, 4,134, 97,208,183,111, 95,120,122,122,162, 99,199,142,100,225, +194,133,166,138, 51, 25,251,169, 82,169, 16, 20, 20,132,211,167, 79, 35, 53, 53,213, 88,242, 84, 36, 18, 25,159,155,244, 16,113, +124, 1,213,170,237,159,255, 78,235, 62,239,195,149,252, 19,211,167,195,193,193,193,248,118, 80, 80, 16,166, 78,157,138,138,138, + 10,209,202,149, 43, 69, 61, 55,175,179,125, 48,187,150, 37, 28,175,209,223,166, 30, 15, 15, 15, 33, 0,188,244,210, 75, 56,124, +248,143, 10,194, 65, 65, 65,152, 62,125, 58, 6, 14, 28, 72,218,180,105, 67, 96, 72, 63,219,108, 40,165,122,142,227, 8, 12, 6, +238,112, 66, 72, 25,128,196,230,186,178, 9, 33,158,124, 62,223, 71, 34,145,116,252,253,247,223,249,109,219,182, 5, 0, 12, 29, + 58, 20, 91,183,110,229,207,152, 49,163, 11,204, 84,173,100, 89,214,101,220,184,113,215, 53, 26, 13,245,246,246,214, 29, 56,112, +192, 94, 32, 16,208,193,131, 7,151, 95,184,112, 65,150,146,146, 34, 29, 57,114,100,165, 84, 42,173,242,243,243, 83,164,167,167, +119,180,176,121,207, 1,160, 85, 85, 85,182,132, 16,187,248,248,248,252,224,224,224,202,143, 62,250,232, 82, 73, 73, 73, 87, 0, +161, 0,146, 45, 17, 36, 18,137,186,247,237,219,215,109,221,186,117,188,246,237,219,131,199,227, 33, 63, 63, 31, 0,224,234,234, +138,208,208, 80, 8, 4, 2,225,213,171, 87, 93,111,220,184,209, 13,102, 10,179,184,185,185, 97,249,242,229,198,194, 58, 2,129, + 0,197,197,197,216,185,115, 39, 42, 43, 43,209,191,127,127,140, 25, 51, 6, 46, 46, 46, 22,118,245, 49,106,110,223,190,173,103, + 24,134,233,215,175, 31,185,113,227, 70,165, 37,255,219,212,212, 84, 95, 55, 55, 67,136,146,135,135,135,177,109,245,247,126,253, +243,230,210,179,103,207,214,187,119,239, 6, 0, 92,187,118, 13,115,231,206,133, 84, 42, 5, 0,232,116, 58,163, 17,222, 28, 8, + 33, 78, 0, 62,107,215,174,221,107,189,123,247, 22, 10, 4, 2,120,121,121,225,220,185,115, 72, 75, 75,195,168, 81,163, 48,102, +204, 24,232,245,250,158,239,188,243,206,135, 0,162, 31,149, 65, 41, 37, 60, 30,111,207,252,249,243,199,175, 90,181, 10,187,119, +239, 30, 58,126,252,120,174, 49,175,140, 72, 36, 42, 82,171,213,150,196,102,173,140,137,137, 25,213,171, 87, 47,167,175,191,254, + 26, 42,149,106,108,113,113, 49,134, 12, 25, 2,123,123,123,108,217,178, 5,253,251,247,151, 72,165, 82,148,151,151,227,216,177, + 99,184,122,245,170, 22,134,226,109,166,250, 59,122,200,144, 33,177,235,214,173,219, 24, 16, 16,240, 21, 33, 68, 15, 67, 97,179, + 1, 0,206, 0,136,161,148,102, 19, 66, 22, 0,136, 1, 96,178, 88, 24, 33,100,244,186, 89,179,246,245, 28, 61,154,196,197,197, +129,207,231, 35, 62, 62, 30,215,174, 93, 67,187,118,237,176,124,249,114, 4, 7, 7, 99,198,140, 25,252, 37, 75,150,172, 3,208, +223,130,190,255,237,104,212, 0,224, 1, 58, 78,167,213,243,121, 0, 15,148,215,202, 89,234, 5, 61, 11,112, 44,192,151, 2,170, + 10,244, 11,116,105,239,248,230,115,159, 5,187,145, 7,105, 69,212,100, 96, 77,157,101, 54,202,120,128,213,160, 54,182,135, 97, +230,207,170,192, 44,205,132,126,177,229,197,172,234,228,141, 6, 48,217,201,201,169, 87, 80, 80, 16,121,240,224, 1,246,239,223, +143, 29, 59,118,124,184,103,207,158, 15, 8, 33,103, 97,168, 26,120,128, 82, 90, 99, 78,166, 64, 32, 48, 86, 1,107, 74,249,215, +159, 99,162, 93, 3, 60, 61, 61,135,172, 93,187,182, 81, 5, 87, 93, 93,141,234,234,106,212,212,212, 64,161, 80, 96,222,188,121, + 54, 19, 39, 78, 92, 66, 8,217,111, 42, 38,192,215,215, 23,229,229,229,248,233,167,159,224,229,229,133,231,158,123,238,161,247, + 19, 19, 19,113,234,212, 41, 40,149, 74,139,140, 20, 0, 80,171,213, 8, 10, 10, 66, 72, 72, 8, 50, 50, 50,144,145,145,241,152, +242, 55, 59,216, 49, 20, 32, 20,142, 18,112,145,145,145,252,212,212, 84, 84, 84, 84, 32, 48, 48, 16, 1, 1, 1,184,121,243, 38, + 78,156, 56,129,130,130, 2,136, 68, 34, 56, 73,192, 1,148, 0,122, 83, 30, 30,173, 84, 42, 69,100,100, 36, 88,150, 69, 92, 92, + 28, 66, 67, 67,225,227,227,131,156,156, 28,252,242,203, 47,200,205,205, 69,120,120, 56,210,211,211,129, 63,114,209, 91, 74, 13, +195, 48,198, 37, 0, 24,170, 64,118, 4, 48,148, 16,242,163,185,107,133, 16, 66,132, 66, 97,168, 80, 40, 12,110,215,174, 29,127, +212,168, 81,188, 9, 19, 38, 48,245,202,191,158,206,157, 59, 67,173, 86, 63,238,254,105,132, 13, 27, 54,148,168,213,106, 12, 30, + 60,216,223,221,221,189,122,218,180,105, 21, 99,199,142, 85,239,217,179, 71, 27, 27, 27,235,176,127,255,254,214,125,251,246,189, +237,232,232,200,212,245,217, 18,218, 68, 68, 68,228, 18, 66,228, 42,149,138,102,100,100,168,243,242,242,212,117, 75, 93, 55, 96, +168,224,105,214, 0, 32,132, 56, 58, 57, 57,181, 91,184,112, 33,175,117,235,214,208,233,116, 72, 72, 72, 64, 85, 85,149,241,122, +214,104, 52,176,183,183, 71,199,142, 29,249, 89, 89, 89,237, 9, 33, 25,166,106, 2,104, 52, 26,176, 44,139,221,187,119, 35, 34, + 34, 2, 93,186,116,193,169, 83,167, 80, 80, 96,152,208,197,197,197, 97,204,152, 49, 45, 82,182, 0, 64, 41,213, 18, 66,210, 78, +158, 60, 25, 18, 53,111, 30, 82, 83, 83, 95, 32,132,168, 40,165,185,230, 62,123,254,252,249,135,220,254,129,129,129,184,127,255, +254, 67, 30,128,230,178,125,251,118,253,233,211,167,153,115,231,206, 97,238,220,185, 16,139, 13,195, 67, 84, 84, 20, 18, 18, 18, + 16, 30, 30,142,101,203,150, 89, 44,143, 16,226, 34,149, 74, 79,237,218,181, 43,248,213, 87, 95,173,239, 51,142, 31, 63,142,225, +195,135,215,104,181,218,233,231,206,157,155,109, 99, 99, 19, 49,109,218, 52,172, 92,185,242,159,132,144,143, 26,139, 9,208,235, +245, 19,119,237,218, 53,158, 97, 24,196,196,196,224,192,129, 3, 80, 40, 20,240,244,244,132, 86,171,133, 94,175,135, 72, 36, 66, +255,254,253,221,234,235, 36,212,215, 88,104,172,109,148,210, 28, 66,200,216,209,163, 71,255,122,229,202, 21,222,247,223,127,111, +172,106,201,178, 44, 42, 43, 43,113,248,240, 97, 28, 58,116, 8, 9, 9, 9, 42,173, 86,123, 20,134, 98, 97, 23, 77,244,247,181, + 49, 99,198,172, 27, 56,112,160,236,171,175,190,146,127,254,249,231, 66, 0,191, 2, 56, 1,195,117,220, 15,192, 6, 24, 60, 94, +191, 1,136, 53,243,251,189,246, 99, 84,212,158,142,129,129,100,211,168, 81, 32,253,250,225,224,217,179,250,252,252,252, 79, 0, +108,202,205,205, 29, 30, 29, 29,189,245,208,161, 67,232,209,163, 7,108,108,108, 34,136, 37, 1,108,127, 67, 26, 53, 0,182,158, +205,153,123,254,122,206,183, 62,110,242,185, 95,189,221,239, 37,112,124,168,108,219,212,168, 66, 39,192,201, 39, 64, 86,154,147, + 94, 35,189,188, 21, 97,222, 42,223,249,253,218,126,209,166, 13,233,145,149,213,120,192, 9, 33,100, 31,159,207, 31, 21, 30, 30, +206, 92,188, 88,247, 63,102,213, 16, 67, 11, 64, 11,176,117, 31,107,224, 1, 32,132, 28,161,148, 14,126, 92,218,195,242, 0, 32, + 57, 57, 25,103,206,156, 1, 96, 24,116,215,175, 95,143, 53,107,214,144, 95,126,249,229,133, 29, 59,118,188,112,228,200,145, 45, +132,144,227, 77,201,171,167,126,176,105,168,236, 31,125,152, 27,144,236,236,236,198,189,255,254,251,210,122,235,190, 33,245,138, +191,186,186, 26, 10,133, 2, 74,165, 18,132, 16, 12, 27, 54,140,191,103,207,158, 65, 0, 76, 6, 5, 18, 66,224,225,225, 1,189, + 94,143, 35, 71,142, 64, 42,149,162,166,166, 6,167, 79,159,134, 90,173,182, 76, 97, 55, 64,163,209, 32, 33, 33, 1, 25, 25, 25, +168,170,170,130, 88, 44,110,212, 3, 96, 9, 34, 62, 40, 0, 99, 21,182,170,170, 42,196,196,196, 32, 55, 55, 23, 18,137,196, 56, +224,213,159,103,134, 51, 42,149,170, 93, 84, 84,148,177, 13, 5, 5, 5,216,181,107,151,177, 12,111,255,254,253,193,231,243,113, +245,234, 85,192, 96,253, 91, 76, 19,107,254,105,132, 16, 62,128,238, 0, 26, 45,129,221, 0,159, 54,109,218,132,237,222,189,155, +223,165,203,227,171, 44,153,153,153,200,204,204,196,143, 63,254, 8,145, 72,100,113, 97, 28,177, 88,140,240,240,240,202,181,107, +215, 22,175, 94,189,218,254,227,143, 63,118,101, 24, 70,225,239,239, 95, 88, 81, 81,193, 49, 12,211,220, 89,162,173,159,159,159, +250,232,209,163,121,119,239,222,213,100,102,102, 86, 39, 38, 38, 42,238,223,191,175,133,161,142,188, 69,198,137, 68, 34,233, 48, +116,232, 80,177,139,139, 11, 68, 34, 17,146,147,147, 31, 82,254, 13,141, 0,134, 97, 16, 26, 26, 42, 78, 76, 76,244, 7,208,100, + 92,134, 90,173,134, 74,165,194,157, 59,119,224,236,236,140,136,136, 8,248,251,251,227,194,133, 11, 0,128,158, 61,123, 66, 42, +149, 54, 75,217, 18, 66, 92,229,114,121,119,141, 70, 83,169, 86,171,207, 0,184, 50,231,221,119, 91,237,219,187,215, 97,235,150, + 45,204,192, 65,131,250, 18, 66, 14, 80, 74,107, 77,201,105,168,232, 3, 3, 3,141,199,158,196, 3, 0, 24, 92,223,182,182,182, + 16, 8, 4,168,255, 95, 38, 38, 26, 10,228, 37, 39, 39,163,182,182, 22, 28,103,222,235, 79, 8,113,148, 74,165,167, 14, 30, 60, + 24, 60, 96,192, 0,163,215,164,109,219,182,232,212,169, 19,162,163,163,101,203,151, 47,239,205,113,220,234, 67,135, 14, 29,154, + 60,121, 50,254,241,143,127,216,229,230,230,186, 3,200,126, 84, 30,165, 84, 79, 8,193,240,225,195,177,120,241, 98,196,196,196, + 96,211,166, 77, 16, 8, 4,144, 72, 36,120,229,232, 8,156,157,112, 6,173, 91,183,198,145, 35, 71, 96, 99, 99,131,214,173, 91, +155,220,201, 69, 41,253,141, 16,242,118, 72, 72, 72,108, 72, 72,136,140, 82,138,224,224, 96, 44, 95,190, 28,227,199,143,199,249, +243,231,127, 5,176, 29,134,128, 64,147, 6, 55,143,199,123, 99,220,184,113,159,190,240,194, 11,178, 75,151, 46,201, 89,150,157, + 42,145, 72,134,171, 84,170,117,148,210,157,117,191,201,207, 0, 54, 18, 66,132,117,198, 31,211,148,194, 22, 10,133,111, 28,154, + 63,127,199,243, 46, 46,164,100,209, 34, 68,232,245,216, 24, 23, 71,243,107,107,167, 80, 74,119,212,201,219,113,243,230,205,175, + 88,150,229,203,100, 50,120,121,121,201,110,223,190,237, 6,160,217, 85, 52,255,234, 52,154, 7,160,157, 12,142,253,194,124,163, + 15, 68,191, 60,220,215, 73,236, 1, 78, 7, 85,232, 4,236, 76,202,151,121,189,186, 4,187,126, 47,144,169,158,155, 6,112, 58, + 68,250,219,187, 74, 42, 96,202, 45, 57,186,119,239,222, 76, 70, 70,198, 31, 71,116, 26, 48, 81,151, 16,115,188, 16, 96, 53,208, +191,103, 11,189, 78,141,163, 71,143,162, 79,159, 62, 32,132,188,108,137,188,139, 23, 47, 54, 90,127, 93, 32, 16, 96,232,208,161, +152, 62,125, 58,162,162,162,248,102,228, 25,151, 0, 30, 85,246,205, 93, 2, 96, 24,166,103, 88, 88,216, 99,199, 21, 10,133, 81, +241, 43, 20, 10,163, 7, 64,161, 80,160, 85,171, 86, 2, 7, 7,135,190, 38, 5, 63,130,139,139, 11,108,108,108,240,239,127,255, + 27, 10, 69,203,150,175,181, 90, 45,174, 95,191,142, 51,103,206, 32, 61, 61, 29, 66,161, 16,197,197,197,184,119,239, 30, 82, 82, + 82,192,178,172,197, 6, 64, 99, 52,246,127,177,132,250, 8,237,134,193, 81, 12,195, 64,163,249,195, 64,228,243,249, 70,163,226, + 41,110,217,185, 11,192,195,220, 73, 14, 14, 14, 97, 49, 49, 49,143, 41,127,189, 94,143,210,210, 82,100,101,101, 33, 53, 53, 21, +199,142, 29,211,151,151,151,103, 52, 33,230, 33, 22, 46, 92,232, 90, 91, 91,107,244,138, 68, 71, 71, 87, 58, 59, 59,215,180,110, +221,218,232,182,230, 56,142, 92,187,118,205,213,242,238,160,122,223,190,125,108,118,118,118,229,189,123,247,202,143, 31, 63, 94, +158,158,158, 94, 11,131,199,196, 6,128, 69,193,132,132, 16,247,128,128, 0, 84, 87, 87, 35, 33, 33, 1,247,239,223, 55, 94,207, +245,143,250,107,154, 82, 90,191,118,106,210, 85,172,209,104,224,225,225,129, 5, 11, 22, 96,204,152, 49, 16, 8, 4,120,241,197, + 23,241,217,103,159, 97,229,202,149,136,138,138, 50,222,135, 22,182,209,198,207,207,111,224,141,180, 52,247,119,222,121,167, 3, + 33,196,141, 82,170,171,168,168,248,249,173, 41, 83,148, 44,203, 98,125,108,172, 8,134, 50,213, 38, 17, 8, 4,184,122,245, 42, + 58,118,252, 99, 72,115,119,119,135,147,147,147, 81,129,183, 4,153, 76,102, 52,106,234, 99,110,186,118,237, 10, 0,232,212,169, + 83,115, 68,173,216,186,117,107,240,128, 1, 3,176, 98,197, 10,124,246,217,103, 40, 43, 43,195,210,165, 75,177,103,207, 30,132, +132,132,192,209,209,241, 53, 66,200,123, 35, 71,142, 4,203,178, 56,115,230, 76, 21,204, 40,175,182,109,219, 66,169, 84,226,157, +119,222,129, 88, 44,134, 86,171,133,171,171, 43,206,188,158, 0,177, 88,140,201,147, 39, 35, 57, 57, 25, 87,174, 92,177,168,145, +148,210,173,149,149,149,173,206,156, 57, 19,121,246,236,217,149,169,169,169,208,233,116,208,235,245, 0,176, 30,192, 79, 0,190, + 32,132,220, 37,132,124,220,152, 12, 66, 72,199,224,224,224, 13, 17, 17, 17,182,169,169,169,114,150,101, 31, 28, 60,120,176, 74, +165, 82,173,174, 87,254,117,188, 51,104,208,160,251,148,210, 54,132, 16, 57, 0,117, 99,202,159, 16, 18,246,207,158, 61,119,116, +227,243, 73,201,167,159,130,170,213,136,231, 56,125, 82,109,237,164,122,229, 95,199,219, 75,151, 46,229, 51, 12,131,242,242,114, +220,187,119,175,152,182,160,132,246,223,129,199, 60, 0, 29, 29, 73,240,236,161, 33, 95,191, 51, 40,248, 31,181, 42, 77,141,158, +128,101,132, 50,190,147, 79,128,236,179,185,187, 80, 80, 90,133,207,246,253,134,168,177, 43,100, 84, 40,133,167,173,210,153,242, +208, 6, 77,187, 19,201,201,147, 39,113,233,210, 37, 44, 91,182, 12,223,126,251, 45, 94, 83,169,160,255,212, 31,208, 42,161, 81, + 41,241,127,247,236,144,172,237, 4,230,232, 81,244,234,213, 11,167, 79,159, 54,213,230,135,228, 93,185,114, 5,133,133,134, 66, + 88,251,247,239,199,144, 33, 67,176,119,239, 94, 36, 39, 39,131, 97, 24,216,219,219,155, 92,199,174,119,233,215, 91,230,230,130, + 0, 77,161, 80, 40, 90, 7, 4, 4, 24, 95, 83, 74, 31,114,249,215,212,212, 24,159,215, 15,158, 82,169, 20,148,210,102,141, 0, + 79, 3,157, 78, 7,177, 88,108, 84,178,217,217,217,152, 54,109, 26, 2, 2, 2, 80, 94, 94,142,213,171, 87,163,123,247,238,207, +186, 89,127, 38, 66, 0,102,141, 9,141, 70, 99, 31, 28, 28,108,124, 93, 81, 81,129,188,188, 60, 72, 36, 18,180,109,219, 22,174, +174,174,240,244,244,132, 66,161,160, 0, 42, 44,249,226,105,211,166,149, 47, 92,184,208, 61, 55, 55, 87, 10,195,174, 7, 35, 28, +199,161,186,186,218,246,210,165, 75,188,128,128,128,178,123,247, 44, 14,109,201,100, 89,182,245,170, 85,171, 46,170,213,106,170, + 82,169,116, 64,189,219, 13,157, 96, 48,120,204,162,215,235,165,245,215,113, 67,101,255,232,223,250,217,107,221, 18,195,227, 46, +176, 6,104,181, 90, 8, 4, 2,180,109,219,246, 33,163,219,199,199,231, 49, 3,220, 28,132, 16,158,141,141, 77,255,253,251,246, +137,133, 66, 33,142, 28, 57,162, 5, 80, 94,231,209, 17,231,229,229,101, 31, 56,112, 32,104,210,164, 73, 0,224, 96, 90, 26, 90, +236,230, 55,135,173,173, 45,100, 50, 25, 94,127,253,117, 76,156, 56, 17,221,186,117,195, 7, 31,124, 0,157, 78, 7,181, 90,109, +145,119,135, 16, 98,227,238,238,254,198,152, 49, 99,240,239,127,255, 27, 31,124,240,193,175,114,185,252, 57,111,111,111,167,151, + 95,126, 25,167, 78,157,130, 88, 44,134,187,187,187,124,206,156, 57,221,199,142, 29,139,109,219,182,161,164,164,100,155,185, 45, +129,106,181, 26,222,222,222,112,113,113,129,171,171, 43,236,237,237,225,224,224,128,234,234,106,136,197, 98,108,219,182, 13,163, + 70,141, 66, 99,222,205,166,160,148, 86, 18, 66,138, 5, 2,193,140,119,222,121, 7, 58,157, 14,253,250,245,195,197,139, 23,247, +114, 28,151,241,210, 75, 47,117, 91,176, 96, 1,222,120,227,141, 15, 8, 33, 59, 40,165,217,143,124,254, 38, 33,100,229, 15, 63, +252,240,114,251,246,237, 59, 28, 60,120,176,166,162,162, 34,166,161, 23,143, 16, 50,162,119,239,222, 81,219,183,111,223, 15,195, +189, 51, 26, 77,120,159, 40,165, 87, 9, 33, 43,237, 47, 95, 94, 60,142,101,177, 30,208,127, 83, 83, 51,241, 17,121,175,204,153, + 51,103,253,244,233,211,145,149,149,133, 35, 71,142,128,101,217, 83, 22,119,250,111,198, 67, 6, 0, 33,132,124,254, 90,167,237, +179, 95, 14,126,238,110, 65, 89,193,236,109,231,127,252,118,198,243, 35, 60,228,106,207,210,156,244,154,249, 99,251,201, 62,219, +247, 27,230,143,237,135,210,236,155, 53, 78, 53, 37,178,178,234,218, 10,134, 32,207,220, 23,117,237,218, 21, 63,255,252, 51,238, +223,191,143,141,155, 47, 66, 94,114, 21,229,165, 90,220,210,180,131,208, 59, 4,118,118,118,205,114,175,213,203,203,201,201, 65, + 76, 76, 12, 46, 93,186,132,249,243,231, 35, 54, 54, 22, 65, 65, 65,205,150, 39, 20, 10, 65, 8,121,162, 32, 64,153, 76, 86,152, +149,149,213,202,217,217, 25,148, 82,163,203,191,161, 17,208,112,224,172,174,174,198,131, 7, 15,192, 48,204, 51,223,195,207,113, + 28,248,124, 62, 52, 26, 13, 8, 33, 88,189,122, 53,212,106, 53,202,203,203,161,209,104, 48,107,214, 44,172, 93,251,151, 47, 9, +254, 52,233, 8, 32,199,220, 73,148,210, 91,155, 55,111,238,180,121,243,102,166,162,162, 2, 23, 46, 92, 64, 69, 69, 5,124,124, +124,208,174, 93, 59,132,132,132,160, 85,171, 86, 24, 61,122, 52,179,123,247,110,127, 60,162,208, 27,195,223,223,159,221,188,121, +115,225,212,169, 83,189,222,126,251,109,207,206,157, 59,215, 0, 64, 86, 86,150,188,186,186,218, 70, 36, 18,169,187,119,239, 94, +168,211,233,154,147,185, 51, 25,128,119, 69, 69,197,115, 0,210, 96,216, 82, 41, 7, 16, 2, 64, 0,192,162,168,102,134, 97,148, + 89, 89, 89,210, 14, 29, 58,152, 85,254, 0, 80, 91, 91, 11, 0, 77,110, 59, 3, 12, 6, 64, 94, 94, 30, 46, 95,190,140, 54,109, +218,160,119,239,222, 15,221, 99,124, 62, 31, 89, 89, 89,240,247,247,183,164,137,221,254,245,175,127,185,132,133,133, 33,102,217, + 50,216,218,218,242,195,194,194, 38,218,217,217,241,189,188,188,208, 33, 32, 0, 83,166, 76,193,157, 59,119, 0,195, 54, 72,147, + 8, 4, 2,244,236,217, 19,133,133,133,240,240, 48, 56,132,212,106,181,217,248, 31,115,200,100, 50,240,120, 60,164,167,167,227, +246,237,219, 8, 15, 15,127, 72,249, 91,184,188,227,210,173, 91, 55, 41,143,199,195,145, 35, 71, 0,224,107,133, 66,209,235,246, +237,219, 81,131, 7, 15, 70,199,142, 29,145,155,155,139,153, 51,103, 98,194,132, 9, 56,112,224, 0,230,204,153,115, 17,134,160, + 56,147,104, 52, 26,216,218,218, 66, 46,151,195,206,206, 14,114,185, 28,182,182,182,198,137, 66, 94, 94, 30, 54,108,216, 0,192, +144,172,205,146,198, 18, 66, 60, 9, 33,199, 98, 99, 99, 29,122,246,236,137, 51,103,206, 96,226,196,137,232,220,185,179,253,207, + 63,255,220,109,214,172, 89, 72, 73, 73, 65, 89, 89, 89, 41,208,184, 14,161,148,174, 37,132, 8,146,146,146, 58,105,181,218,165, +148,210,125, 13,228,143,238,213,171,215,186,237,219,183,127,235,230,230,246, 69, 93,108,216,123, 0,122, 54,213, 38, 74,233, 18, + 66,136,224,132, 64, 16,117, 65,167,123,253, 17,121,163,198,253,243,195,253,179,231, 78, 33, 25, 25, 25,184,122,245, 42,182,111, +223, 94, 3,224,125, 75,250,251,119,228, 33, 3, 32, 8, 16, 20, 87,212, 40,190, 59,117,227,250, 23, 71,211,162,107, 88,238,220, +111,215,114, 35, 38, 60,223,202, 83,122,241, 75, 58,169,219,219, 53, 81, 99, 87,200, 74,179,111,214, 72,207,127, 70,193,105, 17, +127,171,188,152, 35,184,105,233, 23,250,248,248, 96,209,234,175, 81, 94, 94,142,153, 51,103, 66,230, 38,123, 34, 87,179,175,175, + 47,190,253,246,219, 63,228,201, 90, 38,143,207,231,131,199,227, 61, 22,244,247,232,195, 20, 12,195,252,158,146,146,210,170, 75, +151, 46, 15, 41,255,134,179,167,134,179,168,186,227, 92,101,101,229, 51,183, 48, 53, 26, 13,108,108,108,208,183,111, 95, 4, 5, + 5, 25, 7,114,189, 94, 15,189, 94, 15,150,101,241,214, 91,111,225,135, 31,126, 48, 33,133,114,148,240,116,237, 29, 24,221,182, +109,219,196,175,189,246, 26,108,108,108, 30, 59, 75,171,213,226,226,197,139,104,239,192,232, 0,162, 55,189,181, 0, 0, 80,115, +242,228, 73, 89,191,126,253, 80, 94, 94,142,175,190,250, 10,217,217,217,208,104, 52,245, 91,165,112,243,230, 77,192, 16,196,103, + 17, 77,237,255, 39,132,184,194,224, 26,182, 1,112,220,156, 28,149, 74,149,182, 99,199,142,192,244,244,116,210,171, 87, 47, 1, +165,180,126,214,101, 60,167,206,165, 77,246,236,217,227, 99,105,251, 0,192,193,193, 65,183,118,237,218,226,125,251,246,217,100, +103,103,187, 57, 59, 59,231,183,107,215,174, 48, 45, 45,173, 57,174,127, 0,198,181,221, 19, 35, 71,142, 28,213,169, 83,167,254, + 37, 37, 37,216,188,121, 51,120, 60, 94, 45,199,113, 63, 90,186,213,139, 82, 90,120,231,206, 29,151,128,128, 0,136,197,226, 38, +149, 63,143,199, 3,199,113, 40, 43, 43,131, 94,175, 55, 89,155,190,188,188, 28,155, 54,109,170, 55, 22,192,178, 44, 94,125,245, + 85,227, 61,246,201, 39,159, 32, 33, 33, 1,209,209,143, 5,174, 63, 70, 80, 80,144,223,235,175,191, 14, 0,248,240,131, 15,176, +116,201, 18, 70,175,215, 51,245,215,178, 90,173,198,193,131, 7,241,193,135, 31, 42, 96, 65,208, 99,195,123, 95,161, 80, 64, 46, +151, 63,177,242,175,135, 97, 24,180,109,219, 22,222,222,222, 70,229,255,254,251,239, 67,167,211, 97,201,146, 37,150,136,200, 63, +119,238, 92,137, 74,165,114,121,227,141, 55,176,111,223,190, 79,212,106,245,166, 47,190,248,162,230,185,231,158,147,245,238,221, + 27, 98,177, 24, 54, 54, 54,216,185,115, 39,222,125,247,221,139, 44,203,246,167,148, 86,155, 19, 92, 91, 91,139,240,240,112,227, +246, 68, 59, 59, 59, 72,165, 82,212,214,214, 54, 92,110,107,238,143, 48,101,206,156, 57,173,134, 14, 29,138,213,171, 87,227,203, + 47,191,212, 68, 70, 70,138,150, 44, 89,130, 57,115,230,224,202,149, 43,152, 59,119,174,134,101,217, 73,166,150,242, 40,165,159, + 18, 66, 14, 81, 74,141,122,134, 16,242, 90,175, 94,189, 86, 79,157, 58,213,254,235,175,191, 22,175, 89,179,134, 1,240, 35,128, + 5,230,242,160, 80, 74, 23, 17, 66,254,143, 82,154,210, 80,222,184,232, 31,246,140,124,185, 7,121,249,237, 13,248,231,176, 64, +108,219,248,153, 94,161, 80,188,245,168,103,226,191,137,135, 12,128, 52, 67, 0,197,139,237, 0,225, 29, 74, 53, 0,208,197,131, +191,248, 31,190, 54, 91,253,117, 41,173, 36, 63, 77, 1, 21,201,224,164, 44,149, 65,207, 33,179, 68, 89,176,238,116,241,210,244, + 18,147, 23,152,190,170,170,138,121,116, 63,188,163,163, 99,163, 51,244,186,181, 94, 83,131,211,211,150,103,116, 73,214, 27, 0, + 77,197, 1,212,111, 21,108,138,138,138,138, 67,155, 54,109,122,121,212,168, 81, 54, 74,165,242,161,160,191,134,127,235, 7,208, +202,202, 74,156, 60,121, 82,171,215,235, 77, 5,158,177, 74,165,146,223,152, 98,173,167,225,224, 84,215, 95,179,174,236,119,223, +125, 23, 42,149, 10, 42,149, 10,106,181,218,168,248, 27, 26, 1,102, 61, 40,122,166, 22, 18,251,226,221, 67, 57,225,198, 43, 59, + 52,111,191,190,223, 62,114,248,107,252,177, 99,199, 26, 26,206,178,184,124,249, 50,138,238, 94, 99,103,135,176,149, 51,135, 10, +107,169,141, 91, 30, 1, 76, 6, 98, 1, 56,190,100,201,146,136,237,219,183,123, 12, 27, 54, 12, 51,103,206,196,243,207, 63,143, +184,184, 56,108,217,178, 5,183,110,221, 66, 73, 73, 73, 33,204,108, 55,123, 4, 89,131,253,255, 50, 66,200, 64, 0, 78, 48,184, +196,239, 1,248,205, 18,165, 72, 41, 85, 18, 66,190,139,143,143,247,187,114,229, 74,168, 90,173,182,123,225,133, 23,200,139, 47, +190, 72, 88,150, 69, 78, 78, 14,114,114,114, 80, 88, 88, 8,181, 90,109, 54,217, 18,159,207, 47, 11, 12, 12, 12,159, 49, 99,134, +209,183, 63,118,236, 88,229,129, 3, 7,202,228,114,185,241,119, 74, 79, 79,183, 75, 79, 79,247, 35,132,148, 54,163,207, 62,126, +126,126,130, 37, 75,150,160,176,176, 16, 29, 58,116,192,178,101,203, 68, 37, 37, 37, 62, 0,204,238,147, 6, 0,149, 74,149,126, +245,234, 85,255,214,173, 91,139,125,125,125,161,211,233, 30, 83,254,182,182,182,112,115,115,195,237,219,183,145,156,156,172, 86, +171,213,183, 77,201,100, 24,230,161,107, 86,165, 82, 25,239,185,154,154, 26, 36, 36, 36, 0, 0,156,157,157,205,182,239,214,173, + 91,121,113,113,113,254,195,134, 13,195,154, 53,107,112, 62, 49, 17,132, 16, 20, 23, 23,235,243,243,243,149, 5, 5, 5,213,148, +210,124, 0,169,150,236,173,127,116,207, 63,199,113, 79, 69,249,215,179,105,211,166,135,102,254, 26,141, 6, 28,199, 65,173, 54, +159,180,143, 82,170, 35,132,124,177,106,213,170,229, 49, 49, 49, 56,116,232, 80,208,151, 95,126,249, 85, 88, 88, 24,110,223,190, +141,189,123,247, 66,175,215,227,214,173, 91, 21,153,153,153, 91, 0,124, 98,225, 14,168,162,254,253,251,155, 12,236, 19,139,197, + 22,205,250, 31, 33, 36, 40, 40, 8,217,217,217,248,242,203, 47, 43, 0,116,140,143,143,159,125,229,202,149,232,231,158,123,142, +151,148,148,164, 81,169, 84,175, 88,146,199,227, 17,229, 63,177,107,215,174,203, 94,123,237, 53,187,203,151, 47,219,170,213,234, + 55, 37, 18,201,144,186,192, 64,179, 57, 50,234,228, 53, 84,254, 19,135,204,222,187,179,103,191, 17,100,205, 73,128,120, 14,195, +167, 27, 22,211,242, 59,233,111, 81, 74, 15,180,160,223,127, 27, 30,211,104,117,193, 19,198,136,171, 43,133,236,175, 93, 60,248, +211,222,237,227,253,233,139, 1,114, 15,103, 73,173, 99, 89,181,170, 60,254,118, 85,241,186,132,210,165,201, 69,236,225, 71,101, + 60,194,134,224,224,224,119,151, 47, 95,206, 27, 49, 98, 4, 26, 75,140, 3, 24, 20, 87,113,113, 49,126,253,245, 87, 14,192,231, +207, 80, 30,206,156, 57, 3,119,119,247,250, 36, 68,208,235, 13,147, 84,142,227,140, 51, 27, 66,136, 37,129,109,223,103,103,103, +207,220,180,105,211, 63, 70,143, 30,205,111,204,229,223,240,121,126,126,190,182,166,166,102, 15,165,212, 84,100,205, 7,175,190, +250,234, 39,111,190,249, 38,111,228,200,145, 77,122, 33, 56,142,195,229,203,151,145,148,148,196, 1,248,192, 92, 67,181, 90,173, + 49,225,207,163,138,191,225,107,147, 8,170,106, 25, 39,255, 7, 66, 73,129,122, 94,247, 7,110,179,187,104,106, 55, 94,249, 70, + 58,117,252, 62, 7,103, 31,127, 94,254,237,107,220,252,112,174, 98,214,155,252, 90, 70, 96, 83,205,216,187, 23,193,214,189, 28, + 51,226, 77,186, 98, 41,165,165, 0,126, 38,132,120,197,198,198,118,239,218,181,171, 83, 93, 6, 49,156, 57,115,166, 12,192,239, +117,131,122,179,160,148,234,235,250,196, 0,184, 9,160,194,146,217, 81, 35,114, 56, 24,118,109,220, 33,132,216,156, 59,119,110, +116, 82, 82,146,144,101, 89,100,103,103, 35, 39, 39, 7,167, 78,157, 2,195, 48,102,119, 1,176, 44,251, 67, 69, 69, 69,192,154, + 53,107,158,179,179,179,211,118,239,222,189,102,228,200,145, 70,197, 95, 80, 80, 32,205,207,207,247,214,233,116, 2, 74,233, 37, +152,217, 45,242, 8, 69,105,105,105,204,138, 21, 43, 80, 86, 86,134,141, 27, 55, 2,134, 36, 64, 22, 15,230,148,210, 74,137, 68, +114,243,194,133, 11, 33,122,189,158, 95,159, 60,170,222,152,114,118,118,134,135,135, 7,178,179,179,145,156,156,204,106,181,218, +155,230,246,220,243,249,124,188,255,254,251,136,143,143,135,135,135, 7, 94,121,229, 21,163,226,117,113,113, 65,175, 94,189,224, +227,227,131, 1, 3, 6, 96,225,194,133, 38,219,167,215,235,207,189,249,230,155,174, 73, 73, 73,246,111,190,245, 22, 54,109,222, +172, 42, 40, 40,248,161,177,196, 55,150,240,168,247,239,105, 42,127, 30,143,103,116,247,215, 63, 62,250,232,163,230,230, 1, 88, +189,124,249,242,240,170,170,170, 17,139, 23, 47,198,146, 37, 75,112,243,230, 77,124,247,221,119, 56,117,234,212, 65, 0,115, 1, + 20, 83, 74, 45,222, 30,171,213,106,240, 82,227,167, 0, 0, 32, 0, 73, 68, 65, 84,255, 83,181, 87,178,238,221,187,135,110,221, +186,129, 97, 24,137, 94,175, 47,170,115,193,239, 58,117,234, 84, 87, 24, 50, 82, 90,236, 61, 6, 12,129,129,118,118,118,235,199, +142, 29, 43,184,121,243,166, 92,163,209, 60, 56,120,240,160,162, 46, 48,112,119,115, 27, 72, 8, 9,243, 10, 29,179, 51,244,133, +177,228,155, 4, 64,161, 2,180, 89,199,244,229,119,226, 39, 83, 74,155,149,238,249,239,136, 69,169,128, 1,160,131, 11,177,229, + 81,116,212, 83,120, 51, 4,121, 28,193, 77, 51, 51,255, 63,190,196,144,191,126,105,171, 86,173, 38, 44, 91,182,204,168,184, 39, + 77,154, 4, 66, 8,106,107,107, 17, 31, 31,207,149,150,150,238,134,193,106, 53,185, 38,254, 52,229,201,229,242,203,181,181,181, +102,163,131,235, 17, 10,133,165, 42,149,170, 77, 83, 65, 53,132, 16,111,169, 84,122, 61, 42, 42,202,246,133, 23, 94,224, 53,182, + 20, 80, 85, 85,133,162,162, 34,246,216,177, 99,249, 53, 53, 53, 29,205,109, 77, 34,132,116, 0,240,169,167,167,231,136, 25, 51, +102,160,127,255,254, 32,132, 96,243,230,205, 16, 10,133,200,201,201,193,197,139, 23, 81, 85, 85,117, 8,192, 98,115, 89,176, 4, + 2,193, 68,150,101, 45, 74, 5, 44, 18,137, 84,106,181,218,244,141,176,237, 69, 9,180,144,161, 58,223, 78,175,120,224,198,234, + 52,182,123,111,178,226,241, 29,249,106, 70, 32,170,102,228,238, 69,176,245,170,130, 16, 53,152,122,178, 89,133,148, 8, 33,182, + 78, 78, 78, 47,137, 68, 34,185, 70,163, 81,148,149,149,157,104,137,210,110,106, 9,224,105, 64, 8,113, 19,137, 68,131, 71,142, + 28,201,151, 72, 36,184,126,253, 58,174, 92,185,194,114, 28,247,139,165,209,195,132, 16, 30,195, 48,193,132,144,208,246,237,219, +151, 50, 12,163,188,127,255,190, 84,169, 84, 58,215,205, 86,110, 88,154, 29,174,129,204,192,249,243,231,247, 88,181,106, 21,243, +224,193, 3,252,244,211, 79,136,137,137,225, 74, 74, 74, 18, 45,201,148,214, 64, 14,145, 72, 36, 47, 57, 59, 59,123, 60,255,252, +243,162,134,158,161,250,132, 82,103,207,158,213,148,150,150, 22,170, 84,170, 19,166,246, 75,147,186, 44,148,245,187,110, 76, 45, +183, 9, 4, 2,248,251,251,155,205,186, 71, 8,177, 11, 14, 14,126, 53, 41, 41, 73,176,114,229, 74,124,250,233,167,135, 40,165, +102, 99, 47, 30, 69, 34,145, 76,180,196,107, 35,145, 72, 84,181,181,181, 22, 43, 7, 62,159, 63, 85,161, 80, 48,150, 4,208, 89, +146, 10,152, 16,194, 3, 48,215,217,217,121,118,219,182,109,125,211,211,211,179,171,170,170, 62, 7,176,177,185,215,200,127, 18, + 66,200,180, 49, 99,198,108, 89,188,120, 49, 6, 13, 26,132,194,194, 66, 31, 75,114, 49, 88, 32,119, 97,239,222,189, 27, 6, 6, +126,244, 36,247, 51, 33,100, 69,240,216,221,139, 85, 94,175, 67,117,105,169,190,224,236,138,137, 79,115,124,248, 43, 99,177, 1, +240, 84,190,236, 17,197,253,227,143, 63,226,252,249,243, 92, 89, 89,153, 69,138,255, 63, 45,239,105, 65, 8,241,150,203,229,251, +218,180,105, 19, 58,124,248,112,105,253,210, 65,101,101, 37,148, 74, 37,126,253,245, 87,117,121,121,249, 79, 10,133, 98, 58,109, + 70, 26, 90, 98,200,147,191, 42, 32, 32,160,247,172, 89,179, 16, 23, 23,135,228,228,100,148,149,149,157, 3, 16, 77, 41, 77,252, + 15,117,201, 50,234, 13, 1,101,161, 45, 88, 13, 31,124, 17, 11, 27,143,234,150, 40,254,134, 16, 66, 4, 48,204,218,245,148,210, +230,165, 76,123, 70, 16, 66,188, 68, 34, 81,152, 78,167,115, 37,132, 84,112, 28,151, 66, 41,181,168, 22,192, 35,114,132, 12,195, +132, 2, 8,212,235,245,183, 0,164, 52,103, 54,247,136, 44,137,157,157,221,203, 85, 85, 85, 78,245,199, 4, 2, 65,153, 78,167, +251,133,182,160,162, 37,159,207,111, 45, 16, 8,122,200,100, 50,198,205,205,141, 15, 0, 69, 69, 69,108, 77, 77,141, 94,167,211, +157,103, 89, 54,219,156, 12,161, 80, 56, 81,167,211, 89, 92,125,211,210,194, 59,132, 16, 79,111,111,239,158,101,101,101,149, 42, +149,234,164,165, 49, 14,207, 2,153, 76, 54, 94,169, 84,202,204,159,217,188, 98, 64,196,224,158, 16,193, 80,161,244, 47,151,164, +134, 16,210,171, 83,167, 78,103,190,253,246, 91,140, 31, 63, 30,119,238,220, 9,165,148, 94,123, 74,178, 23, 11,133,194, 40,173, + 86, 59,179, 97, 32,223, 19,200, 91, 99,215,182,127, 84, 85,230,241,215,159,134,188,191, 11,207,212, 0, 48,126,169, 65,113,111, +135,193, 29,249,198,147, 42,234,167, 45,239,105, 80,119,115,190,230,224,224,240, 10,199,113,221,149, 74,165,135, 92, 46,207,214, +235,245,231,170,170,170,246, 82, 74,127,125, 2,217, 47,195,208, 95, 1,128, 73,148,210,159,159, 86,187,159, 10,223,246, 20,128, +202, 24,104,149,192,219,103, 91,150,227,217,202, 83,131, 16,210, 5, 64, 23, 0, 87,204, 44, 55, 89, 42, 79, 10,192, 25, 0, 5, + 80,218, 18, 99,194,202,255, 6,132,144,120, 15, 15,143, 62,133,133,133,191, 0,120,149,214,197,150, 61, 37,217, 29,155,187,132, + 96, 70, 94,104,195,216,128,255, 5,254, 20, 3,192,138, 21, 43, 86,172,252,247, 67, 12, 69,169,220, 0,148, 60,197,164, 93, 86, +158, 18, 86, 3,192,138, 21, 43, 86,172, 88,249, 31,164, 57,137, 69,172, 88,177, 98,197,138, 21, 43,255, 37, 88, 13, 0, 43, 86, +172, 88,177, 98,229,127, 16,171, 1, 96,197,138, 21, 43, 86,172,252, 15, 98, 58,181,157, 21, 43,205, 97,221, 0, 27, 72,213,142, +224,241, 28,161, 7, 31, 12, 88,112, 92, 57,106,197,229, 88,240,107,139, 18,179, 88,177,210, 82,234, 10, 2, 13,100, 24,230,141, +118,237,218, 13,188,123,247,238, 78,142,227,102,255,201,109, 18, 1, 48,149, 93,136,181, 6,203, 89,121, 86, 60, 22, 4, 40, 20, + 10, 31,232,116, 58,147,105, 33, 27, 34, 18,137,138,212,106,117,147,153,164, 4, 2,193, 3,150,101, 31,147,199,231,243,245, 44, +203, 62,230,129, 48, 39,207,202,147, 83, 55, 48, 90,106,252,153, 30,144, 98, 34,249,112, 65,107, 80,226,196,169,170, 92,121,181, +197,126, 80,215,248,233, 41,103,207, 16, 94, 37,196,178,123,156,212,245, 30, 79, 98, 87, 12, 66,203, 32, 69, 30, 38,199,155,207, +123,250, 55,131, 16,242,162,131,131, 67,108, 77, 77, 77,128,173,173,237,173,170,170,170,101, 44,203,154, 42,164,208,152, 12, 6, + 64, 95,161, 80, 56,133,227,184, 72, 30,143,119, 82,171,213,126, 3,224,116, 75,246,121,215,253,159,151, 1, 24, 9,160, 53,128, + 44, 0,251, 1, 44,107,137,146, 33,132,136,248,124,254,187, 34,145,104, 0,165,212, 31, 0, 37,132,220,209,104, 52,199, 88,150, +253,226,105,110,241,122, 82, 8, 33,207,123,121,121,253, 48,114,228, 72,183, 87, 71,140,128,167,167, 39,102,188,253, 54, 78,157, + 58, 37,253, 51,182, 45, 18, 66,132, 33, 33, 33,191,132,135,135,247,251,238,187,239,184, 71,222, 51, 62,231,243,249, 10,181, 90, +237,250, 36, 70, 0, 33,164,171,141,141,205, 78,177, 88,236, 94, 86, 86,182,152, 82,250,245, 19, 52,221,202,127, 49,143, 25, 0, +132, 16, 90, 93, 93, 13,153,204,124,222,138,178,178, 50,212, 85,190,107,210,162, 37,132, 80,133, 66,129,250, 84,174, 0, 80, 92, + 92, 12, 55, 55, 55, 52,117,188, 5, 69, 39,254,171, 97,120,252, 7, 84,207, 89,100,148, 49, 60,126, 17,199,234, 76, 26, 80, 60, + 30,175,152, 82,234,216,212,251, 13, 7, 36,134, 97,202,117, 58, 93,227,197,104,214, 13,176,129, 72,219, 9,229,183,123, 66, 93, + 29, 8,202,186,164,151,235, 37,219,174,113,158,191,231,235,157,186,123, 49,101, 83, 59,243, 10, 58, 56, 50, 42, 16,126, 9,196, +210, 59,112,240,187, 4, 25,115, 17,111,157,107, 52,155, 31, 33,100, 29, 12,219,134, 0,160, 28,134,210,158,175, 3,136,128, 33, +247,255, 30, 0,221, 1,212,183,191,136, 82,186,192, 84,127, 31,145,159, 13,192,183,238,101, 14,165,180,181,165,159,109, 10,161, + 80, 56, 69, 46,151,127,190,125,251,118,155,174, 93,187,226,226,197,139,152, 52,105, 82,109,117,117,245, 24,150,101,143, 88,208, +166, 14,124, 62,255, 77, 0,111,136, 68, 34,109,255,254,253, 79,143, 29, 59,246,218,247,223,127,223,249,228,201,147,145, 26,141, +134, 7, 96, 39,203,178,219, 41,165, 22,165, 2,174, 75,158,244, 59, 0,109,239,222,189,207, 6, 5, 5, 85,109,221,186,181, 82, +167,211,141,129, 33,121, 76,175,230, 36, 85, 34,132,116,145, 72, 36,251,123,245,234,229, 21, 17, 17, 33,114,119,119, 71,113,113, + 49,110,221,186,133,187,119,239,170,111,220,184, 81,160, 82,169,198,152,203, 51, 32, 18,137,174,235,245,122,159, 6,114, 27,251, + 46,227,115,134, 97,238,171, 84,170,102,149,203, 38,132,240,125,125,125,243,143, 29, 61,234, 42, 18,137,144,152,152,136, 31,126, +252, 17, 63,253,244,211, 38,150,101,159,185, 7,128, 16, 34,236,212,169,211, 47, 39, 78,156,232,179,101,203, 22, 94,191,126,253, +224,236,236, 12, 59, 59, 59,216,217,217, 25,211,123, 51, 12, 3,161, 80,200,177, 44, 43,107, 42,211,168, 5,223,213,118,248,176, + 97,215, 59,118,236, 40, 57,122,244, 40, 82,174, 93, 83, 1,112,108,169, 60, 43,255,221, 52,106, 0, 80, 74,113,240,224,193, 70, + 75,226, 62,122,204,207,207,207,172, 1, 64, 41,197,177, 99,199, 96,103,103, 7,123,123,123,216,217,217,193,203,203, 11, 38,142, +255, 41, 6,128, 80, 40,252, 77,167,211,173,160,148,254,165,234, 63, 19, 66,232,142, 31, 78, 66,192, 99,160, 84,105, 80,171, 82, + 63,244, 87,173,209, 66,195,234,161,213,177,248,191,207, 22, 64,175,215,155,252,253, 8, 33,116,239,222,189,168,207,235,222, 48, + 55,121,125, 37,192,250,122, 0,243,231,207,111, 90,222,215,189,195,244,249,105,175,229,148,212,118,254, 87, 10,231,117,170, 80, +228,233, 25,214,207, 97,200,144, 33,136,136,136, 64, 82, 82, 18, 14, 31, 62,140,130,171,191, 85,244,241,208, 20, 78, 15,229,229, +183,115,147,253, 14,175,224,255,195,244,248,244, 38,218,246,115, 65, 65,193, 11,106,181, 90,220,174, 93, 59,222,160, 65,131,120, +195,134, 13, 67,143, 30, 61,112,254,252,121,196,197,197,225,232,209,163,220,221,187,119, 57,177, 88,172,246,244,244, 60, 67, 41, + 29,218,156,223,178, 65, 81, 32, 0,104,223,146,196, 81,117,137,158, 34,249,124,254, 96,137, 68,242,118,114,114,178,164,109,219, +182,198,247, 15, 30, 60,136, 25, 51,102, 92, 46, 45, 45,237,106, 74,142, 64, 32,184,200, 48,140, 95,151, 46, 93, 18,103,204,152, +113, 86,165, 82,241,227,227,227,219,150,151,151,203, 29, 29, 29, 21,145,145,145,153, 66,161,144,219,178,101, 75,175,228,228,228, + 30,122,189,254,150, 78,167,235, 97, 65,251, 86, 2,120,177,170,170,170, 21, 33, 68, 24, 31, 31,127, 50, 63, 63, 63,227,163,143, + 62, 58, 94, 82, 82,178, 28,134,226, 71,203, 45,236,107, 23, 59, 59,187, 95, 87,172, 88,225, 52,114,228, 72, 56, 58, 58, 66,169, + 84, 34, 41, 41, 9,149,149,149,184,126,253, 58,110,223,190,141,147, 39, 79,150, 41, 20,138, 1,166,140, 0, 66, 8, 45, 44, 44, +132,147,147, 19,180, 90, 45,212,106, 53, 52, 26, 13,180, 90,173,241,161,211,233,192,178, 44, 46, 93,186,132,153, 51,103, 54,123, + 60, 32,132,116,154, 50,101, 74,234,178,152, 24,244, 31, 48, 64,127,227,198,141,181, 0,118, 90,146,254,152, 16,194, 15, 11, 11, +139,235,220,185,243,160, 29, 59,118, 52,122,142, 88, 44, 46, 82,169, 84, 22,123, 41, 67, 66, 66,142,158, 56,113,226, 69, 55, 55, + 55,254,242,229,203, 33,149, 74,225,226,226, 2,123,123,123,200,100, 50, 8, 4, 2, 80, 74,209,163, 71, 15,136,197,226,102, 27, + 0,132, 16, 49,128, 40, 0,255, 14, 14, 14, 62, 49,228,229,151, 91,157, 57,123,150, 36, 38, 37, 1,192, 3, 0,173,158,213,178, + 2, 33,196, 1,192, 98, 24,234,201,124, 73, 41, 45,104,240,158, 55, 12,165,117,171, 0,172,178, 36, 11,170,155,155,219, 21, 62, +159,239,165,211,233,114,139,139,139, 77,222, 75, 86,154, 79,147,110,224, 71,115,114, 55,149,179,219, 82, 28, 29, 29, 97,111,111, +111, 84,244,230,142,255, 25,232,116,186,190, 66,161,176, 27, 33,100,216, 95,205, 8,224, 49, 4,133,197, 21, 8, 13,242,195,190, +195,103,112, 57,205, 48, 17,228,243,249, 16, 10,235,140, 51,129,208,130, 74,187, 6,234,115,184, 7, 5, 5,225,244,233,211, 72, + 77, 77,133, 80, 40,132, 72, 36,130, 72, 36, 50, 62, 55, 41,143,227,219, 18,173, 58, 32,226, 59, 77,175,121, 31,174,148,252, 58, +125, 58, 28, 28, 28,140,111, 7, 5, 5, 97,234,212,169,168,168,168,112, 88,185,114,165, 67,143,205,235,218, 20,205,102,106,192, +241, 92, 0, 52,106, 0, 0,128,135,135,135, 28, 0, 94,122,233, 37, 28, 62,124,248, 33,121,211,167, 79,199,192,129, 3,121,109, +218,180,225, 1, 48, 83,174,176,113, 40,165, 90,142,227,120, 48,100,142, 60, 71, 8, 73, 1, 48,207, 66, 5,193, 8,133,194,247, +101, 50,217, 28,119,119,119,201,168, 81,163,196, 19, 38, 76, 16, 52, 84,254, 0, 16, 18, 18, 2,149, 74,213,222,156, 60,150,101, +187,142, 27, 55,110,189, 70,163,161,222,222,222, 53, 7, 14, 28, 8, 16, 8, 4,220,224,193,131, 83, 47, 92,184,224,147,146,146, +226, 54,114,228,200, 12,169, 84,122,199,207,207, 47, 43, 61, 61,253,159, 22,118,115,100, 68, 68,196, 47,132,144,137, 42,149,138, +205,200,200, 40,205,203,203, 43,149, 72, 36, 20,192, 38, 0, 31, 2, 48,107, 0, 16, 66, 4, 98,177,120,223,178,101,203,156,198, +141, 27, 7, 71, 71, 71,148,150,150,226,198,141, 27, 80, 40, 20, 80, 42,149,112,113,113, 65, 77, 77, 13,250,246,237,235,116,236, +216,177,189,117, 25,218,154,244, 46,184,185,185, 97,249,242,229,198,122, 0, 2,129, 0,197,197,197,216,185,115, 39, 42, 43, 43, +209,191,127,127,140, 25, 51, 6, 46, 46, 46, 22,118,245, 49,114,111,223,190,205, 50, 12,195,239,215,175, 31,115,227,198,141,116, + 75,149,127, 72, 72, 72,220,209,163, 71,251,127,253,245,215, 72, 76, 76, 52, 78,122, 26, 78,124, 90,181,106,101,241, 18, 41, 0, +116,233,210,101,192,150, 45, 91, 8,165, 20,215,175, 95,199,187,239,190, 11,169, 84, 10, 74, 41,148, 74, 37, 56,142,179,164,208, +152, 41,166, 0, 88, 1, 96, 25, 1,216, 31, 15, 29, 34, 25,183,111,115, 48, 84,221, 28,251,140, 99, 10, 22, 77,155, 54,109,129, +163,163, 35, 86,175, 94, 61,129, 16,210,135, 82,154, 77, 8,105, 13,224,244,226,197,139,125, 75, 74, 74,176,117,235, 86, 30, 0, +179,245,158,165, 82,169,123, 86, 86,150,155,135,135,135, 35, 33,228, 23, 0, 5,141, 60, 10, 1, 60,112,113,113,249, 93, 32, 16, +180, 98, 89, 54,191,168,168,168,203,127,172,135,255, 69, 88,108, 0, 52,245,176,132,122,139,191, 94,201,243,120, 60,147,199, 91, +130,131,131,195,201,202,202,202, 53,148, 82,179, 53,221, 77,177,115,231, 78,155,201,147, 39,199,253,213,140,128,106,165, 10,161, + 65,126,232, 23, 17,138,223, 18, 13,217, 42, 5, 2, 62,132,130,250, 1, 74, 0,129,185,242,189, 13, 80,171,213, 8, 10, 10, 66, + 72, 72, 8, 50, 50, 50,144,145,145,241,152,242, 55, 91, 14,152,161,132, 16, 74, 28, 37,208, 68, 70, 70, 74, 82, 83, 83, 81, 81, + 81,129,192,192, 64, 4, 4, 4,224,230,205,155, 56,113,226, 4, 10, 10, 10, 32, 18,137,224, 44,129, 26,160,124, 64,111,106,247, + 73,149, 84, 42, 69,100,100, 36, 88,150, 69, 92, 92, 28, 66, 67, 67,225,227,227,131,156,156, 28,252,242,203, 47,200,205,205, 69, +120,120, 56,210,211,211, 1,195,108,162, 57,228, 48, 12, 99, 92, 2, 0,208, 30,192, 59, 0, 78, 19, 66,186, 82, 74,239,155,249, +252,224, 54,109,218,188,191,123,247,110,155, 46, 93, 30, 31, 99, 50, 51, 51,145,153,153,137, 31,126,248, 1, 34,145, 40,205,146, + 6,109,216,176,225,146, 90,173,102, 6, 15, 30, 60,201,221,221,253,222,180,105,211,210,198,142, 29, 91,186,103,207,158,170,216, +216,216,160,253,251,247,143,232,219,183,239, 78, 71, 71, 71, 94, 51, 12, 0, 95, 63, 63,191,242,163, 71,143, 30,191,123,247,110, +121,102,102,102,118, 98, 98, 98,230,253,251,247, 21, 0,202,234,250,109, 22,129, 64, 48,229, 31,255,248,135,247, 75, 47,189, 4, +123,123,123,228,230,230,226,250,245,235,143, 21,184, 18, 10,133,144,203,229, 8, 8, 8,240, 72, 75, 75,155, 4, 96, 91, 83, 50, + 53, 26, 13, 88,150,197,238,221,187, 17, 17, 17,129, 46, 93,186,224,212,169, 83, 40, 40, 48, 76, 22,227,226,226, 48,102,204, 24, +243,215, 95, 19, 80, 74, 43, 9, 33,159,159, 60,121,114,126,212,188,121, 72, 77, 77,221, 74, 8, 41,162,148, 30, 53,245,185,144, +144,144, 31, 78,156, 56,241,146,171,171, 43, 15,192, 67,138,191,225, 36,168,185,236,218,181,139, 75, 72, 72,224,159, 63,127, 30, +239,190,251, 46, 36, 18, 67, 41,132, 57,115,230, 32, 49, 49, 17,193,193,193, 88,189,122,117, 75,186, 90,207,110,134, 97,150,233, +245,122,199,235,105,105, 60, 24, 20,127, 1,128,129,148,210,204, 39, 17,220, 2,228, 46, 46, 46, 88,177, 98, 5,220,221,221,125, +231,205,155,119,154, 16, 50, 25,192,142,245,235,215,251,206,157, 59, 23,239,189,247, 30, 0, 88,180,252,164, 84, 42,203,189,188, +188,236,125,124,124,164,201,201,201,131, 42, 43, 43, 81, 86, 86,134,226,226, 98, 20, 20, 20, 32, 39, 39, 7,153,153,153,184,117, +235,150,190,170,170, 10,249,249,249, 76,155, 54,109,254, 50, 5,145,254,234,252,199, 13, 0, 62,159,175,247,241,241, 97,234, 11, +226, 0,134, 58,241,124, 62, 31, 62, 62, 62,120,244,184, 72, 36,106, 81, 17,143,192,192,192,126, 66,161,176,251,147, 42,238,113, +227,198, 33, 55, 55,215,230,195, 15, 63,108,177, 17, 32, 22,139,127,213,104, 52,253,205,157, 39,151,203,143, 87, 85, 85, 13,176, + 68,102,181, 82,133,125,135,207,224,183,196, 20,148,150, 43, 32, 20, 24, 20,190,113,246, 47, 20, 64, 40,176,124,192,212,104, 52, + 72, 72, 72, 64, 70, 70, 6,170,170,170, 32, 22,139, 27,245, 0, 88,130,136, 15, 14, 0, 36, 18, 9, 36, 18, 9,170,170,170, 16, + 19, 19,131,220,220, 92, 72, 36, 18,136,197, 98, 0,128,144, 15, 75,254,183,211, 84, 42,213,235, 81, 81, 81,198, 54, 20, 20, 20, + 96,215,174, 93,200,206,206,134, 68, 34, 65,255,254,253,193,231,243,113,245,234, 85, 0,152,102,113,167, 1, 52,177,230,255,121, + 93,126,251,207, 0,140, 54,245,121, 7, 7,135,197, 49, 49, 49,143, 41,127,189, 94,143,242,242,114,100,101,101, 33, 53, 53, 21, +199,142, 29,211, 86, 84, 84,124, 99,105,187,196, 98,177, 62, 60, 60, 60,125,237,218,181, 73,171, 87,175,238,248,241,199, 31,119, + 99, 24, 38,211,223,223, 63,161,162,162, 66,203, 48,140, 94,167,211, 53,199, 66,206,222,183,111, 95, 77, 72, 72, 72,250,189,123, +247, 74,142, 31, 63,158,149,151,151, 87, 12,131,193,212, 14,192,109, 75,132, 8, 4,130,151,187,117,235, 38, 82,171,213, 80, 40, + 20,200,200,200,120, 76,249,215,151,185,166,148,194,219,219,219,230,206,157, 59,131, 96,194, 0, 80,171,213, 80,169, 84,184,115, +231, 14,156,157,157, 17, 17, 17, 1,127,127,127, 92,184,112, 1, 0,208,179,103, 79, 72,165,210,102, 41, 91, 66,200, 63,228,114, +121,172, 70,163,185,165,209,104,166, 3,136,153,243,238,187, 3,247,237,221, 27,180,117,203, 22,254,192, 65,131,246, 16, 66,130, + 40,165,133, 77,201, 8, 15, 15, 31,250,213, 87, 95, 1, 0,174, 95,191,142, 17, 35, 70, 60,230,253,108,137, 81, 66, 8,129, 76, + 38,131,141,141, 13,132, 66, 33, 24,134,129, 86,171,197,165, 75,151, 0, 0,105,105,105, 80, 42,149, 22,123,239, 30,197,209,201, + 37,230,243, 47,191,178, 89, 48,247, 93, 20, 21,230, 3,134, 24,143,193,127,130,242, 7,128, 79, 62,253,244,211, 1, 46, 46, 46, +109,231,206,157, 11, 0,190, 81, 81, 81,241,177,177,177,152, 59,119, 46, 54,108,216,128,213,171, 87,231, 0,248,210, 18, 97,197, +197,197,157, 8, 33,246, 44,203,102,156, 61,123,214,213,221,221, 29,114,185, 28,238,238,238,136,136,136,128, 88, 44,134, 72, 36, +130, 64, 32, 96,186,116,233, 2, 79, 79,207, 90,142,227, 44,170,192,105,229, 25, 24, 0, 44,203, 50,213,213,213,104, 88, 10,179, +164,164, 4,238,238,238,104,226,120,139,114, 19, 72, 36, 18, 12, 30, 60,216, 70, 38,147,253, 68, 8, 25, 76, 41, 61,211, 18, 57, + 0,208,189,123,119,108,218,180,201,102,246,236,217, 45, 50, 2, 52, 26,205,114,161, 80,216,227,155,111,190,177,153, 48, 97,194, + 99,239, 95,186,116, 9,145,145,145, 74,133, 66, 97,209, 26, 44, 96, 48, 0,234,221,254,245, 10,159,212,230, 67,172,173, 65,181, + 82, 15, 81,155,231, 32, 18, 89, 84,112, 12, 0,160,213,106,141,107,183,245, 10,191,184,184, 24, 58,157, 14, 90,173, 22, 97, 97, + 97,144,203,229, 22,203,123,148,150,186, 52, 41,165, 42, 66,200, 67,193,161, 12,195, 64,163,249, 35,192,156,207,231, 27,141,138, +167, 24,209,189, 7,192,187,230, 78,210,104, 52, 29,131,131,131,141,175, 43, 42, 42,144,151,151, 7,137, 68,130,182,109,219,194, +213,213, 21,158,158,158, 80, 40, 20,122, 0, 55, 44,249,226,133, 11, 23, 70,196,196,196, 92,172,127, 29, 29, 29,125,243,210,165, + 75, 2,185, 92,110, 92, 38,225, 56,142,119,237,218,181,110, 48,189,133,172, 33,251, 89,150, 29,177,106,213,170,247,213,106, 53, +167, 82,169,106, 0, 40, 0, 84, 0,152, 7, 96,175, 37, 66,244,122,125,103, 15, 15, 15, 84, 87, 87, 35, 49, 49,177, 81,229, 95, + 93, 93, 13,149,202,240,111,176,183,183, 7,165, 52,212,148, 76,141, 70, 3, 15, 15, 15, 44, 88,176, 0, 94, 94, 94, 16, 8, 4, +120,241,197, 23, 17, 26, 26, 10,173, 86,139,192,192,192,102,121, 24, 9, 33, 94,126,126,126, 71, 18, 78,159,118,142, 93,191,190, +199,250,245,235,191,165,148, 38, 17, 66, 34,223,154, 50, 37,249,196,241,227,222,235, 99, 99, 29,134, 13, 31,190,168,174,239,141, +178, 99,199, 14,156, 63,127, 30, 66,161, 16, 35, 70,140,128, 80, 40, 68, 96, 96, 32,238,223,191,255,144, 55,160, 37,200,229,114, +216,216,216, 24,149,191, 86,171, 53,198,181,132,132,132,180, 88,249,187,184,120,172,217,190,115,215,140, 82, 21, 35,178,117,112, + 41, 43,126, 80,160,166,148,122,193,176,243, 99,101,139,132, 62, 1,148,210, 66, 66, 72,228,188,121,243, 18, 0,180,153, 59,119, + 46,250,244,233,131,208,208, 80,108,216,176, 1,243,230,205,203, 1,208,167, 97,108,128, 5, 50, 43, 9, 33, 51,182,110,221,250, +195,188,121,243,160,211,233,160, 84, 42,141,202, 95, 44, 22, 35, 46, 46, 14,215,175, 95, 79, 0, 48,224,175,180, 27,229,175, 78, +147,202,246,105, 46, 1,200,100, 50, 28, 63,126, 28, 23, 46, 92, 64, 70, 70, 6, 56,142, 51,121,188, 37,136,197, 98, 56, 56, 56, + 96,194,132, 9,178,240,240,240,237, 45, 22, 4,192,214,214, 22,189,122,245, 66,116,116,180,141,173,173,237,214,230,126,158, 82, +122, 78,171,213, 14,156, 58,117,170,114,229,202,149, 56,123,246, 44, 82, 82, 82,140,174,225,200,200, 72,165, 82,169, 28, 72, 41, + 61,103,169,204,234,154, 90, 16, 66, 32, 18, 9, 33,228, 1,114, 77, 6,162,254,217, 15, 31, 44, 27,137, 37, 75, 7, 67, 95,116, + 30,132,179, 92, 23,234,116, 58,136,197, 98,136,197, 98, 48, 12,131,156,156, 28, 76,152, 48, 1, 43, 87,174,196,135, 31,126,136, +212,212, 84,212,214,214, 54,183,235,127,103,236, 96,112,157,154,132, 82,250,245,230,205,155,181,128, 65,249, 95,184,112, 1,105, +105,105, 40, 42, 42, 2, 33, 4, 33, 33, 33, 24, 52,104, 16, 70,143, 30, 45,144, 72, 36,147, 45,249,226,105,211,166,165, 46, 92, +184,176, 87, 70, 70, 70,235, 71,223,227, 56, 14,213,213,213,190,151, 46, 93,234,213,182,109,219,235, 48, 84,224,179,132, 24, 0, +252,138,138,138,101,117, 1,107, 90, 0,126, 0,254, 15,128, 45,128,181,150, 8, 33,132,232,139,138,138,154, 84,252, 13,149, 63, +128,122, 69,102,242, 70,214,106,181, 16, 8, 4,104,219,182, 45,108,109,109,141, 99,137,143,143,143, 81,249,215, 43, 92, 11,218, + 39,178,177,177, 57,180,127,223, 62,103,161, 80,136, 35, 71,142, 84, 1,184, 78, 8,145, 0,112,204,203,203,251,233,192,129, 3, +232,220,185, 51, 0, 4,154,147,215, 80,209, 7, 6, 6, 26,143, 61,137, 7, 0,128,209, 3,240,218,107,175,225,248,241,227,208, +106,181, 88,180,104, 17, 14, 28, 56,128,247,222,123,175, 69, 6,179,187,187,231, 39, 59,118,237,156,195, 9,229,162,207, 87,199, +148, 22,229,223,143,166,148, 6, 1,152, 5, 32,182, 69, 13,125, 10, 80, 74,115, 1,188, 25, 21, 21,133,148,148, 20,132,134,134, + 34, 37, 37, 5, 81, 81, 81, 0, 48,153, 82,154,221, 2,153, 63,254,246,219,111, 63,220,184,113, 3, 2,129, 0,124, 62,223, 24, + 67,114,250,244,105, 68, 71, 71,167, 1, 24,110, 85,254,205,227,153, 24, 0,128, 33,216,207,201,201,201,248, 48,119,188,185, 72, + 36, 18,216,219,219,227,212,169, 83,181,201,201,201,150,174,147, 54,138,173,173, 45,110,220,184,129,117,235,214,213, 84, 87, 87, + 79,106,137, 12, 74,233, 57,141, 70, 51,112,217,178,101,202, 27, 55,110, 64, 42,149, 34, 57, 57, 25,111,188,241, 70,179,149, 63, + 0,212,170,213, 16,242,121,112, 17, 41,208,193,177, 28,139, 63, 30, 11,149, 40, 5,233, 89,231,144, 93,124, 17,195, 38,116,192, +253,235,113, 22,203,227, 56, 14, 2,129,192, 24,132,180,106,213, 42,120,121,121,161,188,188, 28,181,181,181,152, 53,107, 22,226, +227,227,155,221,239,191, 49,111, 3, 48, 91, 86, 89,165, 82,125,177, 99,199, 14, 85,191,126,253,170, 63,255,252,115, 36, 37, 37, + 33, 59, 59, 27, 90,173,214,120,142, 64, 32,192, 75, 47,189,196, 99, 24,230,101, 75,190,216,223,223, 95,185,121,243,230,211,174, +174,174,165,111,191,253,118,223,175,191,254,186, 61, 0,100,101,101,181,187,122,245,106, 31,145, 72, 84,214,189,123,247,211, 50, +153,204, 98,139,172, 46,240,107,212,200,145, 35, 59,127,252,241,199, 63,204,156, 57, 51, 29,192, 41, 30,143, 23, 14, 96,188,165, +129, 97,132,144,171, 25, 25, 25, 40, 47, 47, 55,171,252, 1,160,178,178, 18, 12,195, 92, 53, 37, 83,171,213, 34, 47, 47, 15, 7, + 14, 28, 64, 82, 82, 18, 8, 33,143,237, 50,202,202,202,178,180,171,171,255,245,175,127, 61, 23, 22, 22,134,205, 95,126, 9, 91, + 91, 91,155,176,176,176, 7,125,250,244,169,125,253,245,215,211,151, 47, 91, 54,115,234,212,169,200,206,206, 6, 0,179, 46,113, +129, 64,128,171, 87,175,162, 99,199,142,198, 99,238,238,238,112,114,114, 50, 26, 43, 45,193,214,214, 22, 12,195,224,238,221,187, +184,123,247,238, 67, 59,111,234, 61, 2,205,193,203,171,213, 71,219,119,238, 92, 96,227,232, 46, 90, 29,179,180, 44, 39,243,246, + 7,138,202,178,111, 40,165, 85,148,210,205,127,166, 34,172, 11,248,219,185, 97,195, 6,132,134,134,226,234,213,171, 8, 13, 13, + 69,108,108, 44, 0,236,168,123,191,217, 80, 74,103,125,241,197, 23,213,245, 99, 87,253, 50,224,236,217,179,115, 89,150, 29, 64, + 41,109,110, 60,208,255, 60,102, 13,128,166,162,255, 5, 2, 1, 24,198, 50,111,125,126,126,190, 81,193, 59, 58, 58, 26,173,232, +166,142,183, 4,177, 88,140, 19, 39, 78,212,110,221,186,245, 85, 74,233,201, 22, 11,130, 97,253,111,226,196,137,202,154,154,154, + 65,205, 85,212, 13,161,148,158, 83,171,213, 3,163,162,162,148, 59,118,236,192,228,201,147, 91,164,252, 1,192, 91, 90,142, 30, +237,244,120,115, 92, 4,198, 77,235,132,236,162, 68,168,213, 26,104,181, 44,180, 26, 22, 85,213,165,232, 55,196,211, 98,121, 90, +173, 22, 54, 54, 54, 24, 61,122, 52, 22, 45, 90, 4,150,101,193,113, 28,244,122,189,113, 11,224,180,105,230,150,215,169, 70, 79, +120, 10,127, 7,166,122,219,182,109, 80, 42, 27, 79,246,167,213,106,113,230,204, 25,248, 59, 48,213, 0,209,130, 82,115,174,158, +220,147, 39, 79,130, 82,138,178,178, 50,124,242,201, 39,248,233,167,159,112,246,236, 89,163, 87,226,230,205,155, 0,144,107,105, +127, 9, 33,217,132, 16, 90,247,200,174, 59, 70, 8, 33,255, 32,132,252, 27, 64, 56, 44,112,153, 82, 74,243, 85, 42,149, 91,124, +124,252,204, 13, 27, 54,220, 88,189,122,181, 46, 62, 62,158,147,201,100, 96, 89, 22,153,153,153,184,120,241, 34, 10, 11, 11,161, + 86,171,155, 21, 45,238,224,224, 80,243,213, 87, 95,157,114,112,112, 80,103,103,103,135,136, 68, 34, 85, 88, 88,216,105,161, 80, + 88,211, 28, 57, 13, 24,236,231,231, 39, 91,178,100, 9,162,163,163,177,113,227, 70, 56, 58, 58, 58, 0, 24,108,169, 0,141, 70, +243,243,157, 59,119,106,175, 93,187,214,164,242,231,243,249,112,117, 53,164,138,200,201,201,169, 81,171,213, 38,115, 31,148,151, +151, 99,211,166, 77, 56,117,234, 20,190,249,230, 27,252,246,219,111, 15,141, 51, 43, 86,172,192,244,233,211,113,244,168,201,152, + 61, 0, 64, 80, 80,208,232,215, 95,127, 29, 12,143,135, 15, 63,248, 0, 73,137,137,252,164,196, 68,155, 35,135, 15,227,235,175, +190,194,140, 25, 51, 16, 23, 23,135, 81,163, 71,223,133, 5,187, 30,158,196,205,111, 14, 30,143, 7,127,127,127,180,110,221,218, +168,244,163,162,162,176, 96,193,130,135,150,184,204,225,229,229,179,224,139, 77, 27,163, 61,125,218,138,150, 45, 93, 84,118, 59, + 61,237,227,202,242,146,191, 68,178, 31, 66,136, 39, 33,228,244,166, 77,155,124,231,204,153,131,216,216, 88,132,135,135, 99,195, +134, 13,152, 59,119, 46,214,175, 95,239, 11, 67,192,173,119,115,101, 83, 74, 11,243,242,242,162,182,111,223, 14, 62,159,143,204, +204, 76,252,243,159,255,172, 84,171,213, 47, 53,103, 73,193,202, 31, 52, 26, 3,240,224,193, 3,179, 51,127, 75,149,191, 80, 40, +212,123,123,123, 55,150,241, 15,222,222,143, 95, 3, 98,177,184, 69, 65,128, 23, 46, 92, 72,188,123,247,238,167,148,210, 95, 91, +242,249,122, 46, 93,186,132, 9, 19, 38,180, 88, 81, 63, 10,165,244, 28, 33,100,224,166, 77,155,118,214,214,214, 78,106,169,204, + 17,175, 7,161,168,252, 14, 20, 53,105, 40, 42,211, 25, 21,191, 86,203, 25,159,235,137,229, 75, 40,115,230,204,129, 74,165,130, + 74,165,130, 70,163,121, 72,241,215, 63, 55,107,144,233,153, 66, 70, 98,127, 97,207, 80,206,238,139, 43, 59, 42,222,153,176, 63, +160,207,176,215,164, 99,199,142, 5, 96,136, 3,184,124,249, 50,138,238, 94,171,157, 29,194,166,207, 30, 42, 44,128,141,219,113, + 24,246, 38,155,226,149, 37, 75,150,172,223,190,125,251, 11,195,134, 13,195,204,153, 51,241,252,243,207, 35, 46, 46, 14, 91,182, +108,193,173, 91,183, 80, 82, 82,114, 6, 38,214,115, 27,193,183,193,254,127, 95, 66,200, 97, 0,161, 0, 42, 1, 28,128, 97, 86, +108,209, 52,172,110,118,245, 29,128,239, 8, 33,222,231,207,159,191,145,152,152, 40,103, 89, 22,217,217,217,200,201,201,193,169, + 83,167,192, 48,140,217, 93, 0,124, 62,255, 90, 96, 96,224, 71, 51,102,204,216, 87,127,108,236,216,177,185, 7, 14, 28, 72,149, +203,229,249,245,199,210,211,211, 3,210,211,211, 71,215,109, 89,180,148,223,211,210,210,132, 43, 86,172, 64, 89, 89, 25, 54,110, +220, 8, 0, 98, 24, 18, 4, 89, 4,199,113,187, 50, 51, 51, 23,221,186,117,171,131, 74,165,130, 72, 36,130, 82,169, 52, 42,127, +145, 72, 4, 79, 79, 79,104,181, 90,148,149,149, 33, 51, 51, 51,151,227,184, 61,166,100, 50, 12,243, 80,178, 31,149, 74,101, 28, + 87,106,106,106,144,144,144, 0, 0,112,118,118, 54,219,190, 91,183,110, 29,143,139,139,155, 60,108,216, 48,172, 89,179, 6,231, + 19, 19, 65, 8, 65,113,113,177, 54, 63, 63,191,160,160,160, 32,139, 82,250, 27,128,207, 44,217, 91, 47, 16, 8,208,179,103, 79, + 20, 22, 22,194,195,195, 3,128, 33,104, 81, 32, 16, 52,154,180,168, 57, 48, 12,131,207, 63,255,252,161,124, 7,245, 65,208, 90, +173,214,162, 56, 0, 66, 72, 80,239, 62,145, 11,130, 58,119,145, 44,152, 59,167,236,122, 74,202, 39,229,165,197,155,158,168, 97, + 79,151,153, 75,150, 44,241,157, 57,115, 38,214,174, 93,139, 69,139, 22,221, 5, 48,113,222,188,121,123, 0,248,205,157, 59, 23, + 37, 37, 37,190,159,126,250,233,251, 0,102,154, 19, 70, 8, 25, 6,192, 6,134,229,185, 56, 74,233, 54,103,103,231,216,223,127, +255,221,182,170,170, 74,175, 80, 40, 6, 82, 74, 51,154, 56,215, 90,235,222, 12,143, 25, 0, 12,195, 24, 47,124, 75, 48,103, 8, +104,181, 90,134, 30,142,198, 79,108,132,113,224,200,207,207,199, 71, 31,125,132, 38,142,183, 40, 8,240,206,157, 59,102,147,163, + 88, 66, 75,214,231,205, 81, 39,171,173,217, 19, 77,144, 95,154, 10,101,173,178, 78,233,179,198,191,154, 58, 35, 64, 83,119,204, + 82,180, 90,173, 49,225,207,163,138,191,225,107,147, 8,170, 10,224,228,127,158, 47, 44, 40,141,234,254,160,199,156, 46,154,252, + 47,174,124,227, 53,117,252,190, 64,103, 31,127,113,193,157,107,234,249, 97,220,205, 89,111,242, 11,120, 2,155, 28,216,186,159, +135,189,251,117,204, 56,109,210, 21, 75, 41, 77, 6,208,155, 16,210, 47, 54, 54,118, 93,215,174, 93, 67,235,131, 2,207,156, 57, +147, 2, 96, 65,221,160,222, 44, 40,165, 90,189, 94,207,192,112,221,127, 9,224, 22,165,212, 98, 95,115, 19, 50,243, 8, 33, 3, +223,123,239,189,223, 70,142, 28, 41,145, 72, 36,184,126,253, 58,174, 92,185, 82,203,113, 92,148,185,207,179, 44,219,165,162,162, + 98,242,154, 53,107,150,219,217,217, 85,117,239,222,253,254,200,145, 35,141,138,191,160,160,192, 43, 63, 63,255, 69,157, 78, 39, +167,148, 46,129,193,240,176,148,136,142, 29, 59,106,151, 44, 89, 34,124,240,224, 1, 2, 2, 2, 16, 19, 19,163, 46, 41, 41,137, + 0,144,106, 97,255, 56, 66,200,168,132,132,132, 4, 30,143,231,228,224,224,240,144,162,178,181,181,133, 90,173,198,237,219,183, +145,144,144, 80,166, 86,171, 71, 83, 51, 30, 30, 62,159,143,247,223,127, 31,241,241,241,240,240,240,192, 43,175,188, 98,244, 54, +186,184,184,160, 87,175, 94,240,241,241,193,128, 1, 3,176,112,225, 66,147,237,211,235,245,179,222,124,243,205,110, 73, 73, 73, +129,111,190,245, 22, 54,109,222, 92, 84, 80, 80,208, 5, 64, 65, 75, 20, 64, 67, 79,132, 66,161,128, 92, 46,127, 42,202, 31, 48, +120, 0, 56,142,123,232,177,116,233, 82,163, 65, 96,238, 59, 8, 33,164,181,159,223,190,101,203, 63,113,155, 54,105, 66,209,157, +204, 59,171, 74, 74, 30,108,120,226,134, 61,101,242,242,242,176,104,209, 34,172, 93,187,246, 46,128,200,186,123, 36,114,222,188, +121, 9, 15, 30, 60,104, 93, 94, 94, 14, 88,190,125,215,134, 82,250, 61, 33,100, 28,128,113,132, 16,120,120,120,224,246,237,219, +240,245,245,173, 5,224, 71, 8,241,171, 63,185,238,220,177, 48,120,183,173,219, 1,205,208,120, 38,192,195,209, 88,146,200, 3, + 33, 4, 12,195, 24, 31, 13, 95,215, 63,143,142,142, 54,155, 9,112,227,198,141,200,202,202,122,104,157,239,131, 15, 62, 64, 83, +199,255,172, 76,128,118,118,118,191, 42, 20,138,229, 79, 83,249, 63, 13,120,124,193, 3, 61,247,120, 61,133,198,224, 11, 68, 69, + 58,173,233, 90, 10,130, 38,234, 51, 52,134,249,218, 12,132, 96, 91, 63, 87,104,225,131,234,252,246, 80, 60,120,158,213,105,124, +191, 79,103, 93,198,119,224,151,240, 4,162, 28,200,221, 19, 97,235,117, 7, 66,220,199,212,223,138, 1,203, 7,102, 66, 72,107, + 39, 39,167,131, 34,145,200, 79,163,209,100,150,149,149,141,106, 73, 16,209,127, 34, 5,240, 35,242, 95, 20,137, 68,239,235,116, +186, 8, 66, 72, 26,199,113,171, 40,165, 22,215, 2, 32,132,136, 25,134,153, 77, 8,121,175,125,251,246,201, 12,195,228,221,191, +127,223, 75,169, 84,134, 81, 74, 87, 1,216,212,220,117, 93, 66,136,155,157,157,221,175, 85, 85, 85, 33, 48,236, 30,160, 2,129, + 32, 85,167,211, 13,160,148, 22, 53, 83, 86,128, 88, 44,254,161, 93,187,118,190,173, 90,181,178,169, 79,248, 84, 81, 81,129,220, +220, 92,229,221,187,119,115,212,106,245,171,245,179, 49, 19,114,232,222,189,123,141, 1, 92,166,150, 24, 5, 2, 1,252,253,253, +205,142, 7,132,144,246,193,193,193, 87,146,146,146,108, 87,174, 92,137, 79, 63,253,180, 59,165,244, 66,115,250, 87,223,182,130, +130,130,199, 18,255, 60,170,152, 25,134,105,214, 24,197,231,243,117,165,165,165,124, 75,182,213,202,229,114,147,153, 0,125,125, +125, 47,240,249,124,233,189,123,247,198, 81, 74, 45,218,101,242, 44, 33,132,200, 0,141,246,174,216, 0, 0, 32, 0, 73, 68, 65, + 84, 44,132, 33, 85,247, 10, 74,233,131, 6,239,121,194,144,115, 67, 80,247,158,217, 76,128, 13,102,245, 58, 0,135, 40,165,172, +171,171,235,165, 71, 19,254,212, 5,125, 14,174,147,109,245, 0, 88, 72, 99,197,128, 56,157, 78,103,241, 44, 92, 40, 20,234,235, +114,149, 55, 74, 83,202,166,169, 98, 64, 2,129,160, 72,171,213, 90,139, 1,253,237,104, 96, 8, 40, 11, 91,131,213, 72,193, 23, +213,194,198, 35,187, 37,138,255, 97,201,196, 22,134, 89, 59, 75, 41,109,180,134,192,127, 11,132, 16, 59,134, 97,222, 7, 48, 77, +175,215,255, 11, 22,166, 76, 53, 35,243, 99, 0, 31, 1,136,161,148,126,252, 4,114,120, 60, 30,239, 13,145, 72,244, 50,165, 52, +172, 46,158,226,170, 90,173,254,133,227,184,239,204,205,252,129,230, 23, 27,179, 52,237, 46, 33, 36,210,219,219,251,171,178,178, +178,116,149, 74, 53,170, 37,217,239, 8, 33,180,180,180,244, 33,195,164, 49, 15,103,115, 13, 0, 91, 91,219,219, 42,149,170,141, + 37,231,138, 68,162,162,218,218, 90, 95, 83,191, 37,105,152,207,250,127, 0, 98, 40,106,213, 13,134,221, 43,231, 40,165, 53,143, +188,223, 30, 64, 39, 0,119, 0,220,160,148,182,104, 25,249,127,145,199, 12, 0, 43, 86,158, 12, 66,240,109, 15, 25,168, 76, 0, +173,146,226,237,115,149, 45, 85,252, 86,172, 60, 75, 36, 18,201, 3, 75, 2, 55, 37, 18, 73, 81,109,109,173,117,146,242,140, 33, +132, 4, 0,168,223,158, 33, 6,160, 6, 80, 3,195,214,216, 75,214, 93, 0,205,199,106, 0, 88,177, 98,197,138,149,191, 5,132, + 16, 23, 0, 47, 54,136, 11, 72,166,148, 90,148,213,210,202,227,180, 40,224,206,138, 21, 43, 86,172, 88,121,214, 80, 74, 75, 0, + 40, 9, 33,175, 1, 80,193,224,246,183,210, 66,172, 30, 0, 43, 86,172, 88,177, 98,229,127, 16,171, 7,192,138, 21, 43, 86,172, + 88,249, 31,164,201, 98, 64,255, 81,142,182, 23, 65,168,176, 7,129, 12, 20, 53,208,202, 43, 49,232,142, 53,135,179, 21, 43, 86, +172, 52,131,186, 8,121, 87, 0,229,150, 36, 58,178, 64,158, 11,128, 14, 0,210,235,220,237, 86,254,139,121,182, 6,192,129, 96, + 33,236,203, 67,192,231, 90,113, 26,165, 61, 15,172, 45, 7,126, 53, 79,128, 74,156,240,204, 69,165, 99, 42, 70,167, 53, 47, 41, +246,223,140,186, 27,118, 32,195, 48,111,184,184,184, 12, 44, 41, 41,217,201,113,220,236, 63,187, 93, 86, 12, 16, 66,150,201,229, +114,125, 85, 85,213,199,127, 98, 27, 14,227,143,116,189, 71, 40,165, 67,254,172,182, 88,249,107, 66, 8,113, 2, 16,232,226,226, +210,254,185,231,158, 19,100,102,102,130, 16,242, 0,192,233,150,108, 27,173, 75,166,179,179, 99,199,142, 61,219,181,107,135,244, +244,116, 16, 66,206, 1,152, 68, 41,189,247,180,219,255, 36, 16, 66, 28, 0,136, 26,230, 24,176,210, 50,158, 93, 12,192,105, 87, + 25,116,130,231,149,181, 21, 65, 31,252,159,221,140, 31,207,215,186,230, 23, 41,109,189,221,100, 53,175,244,148, 22,175,120,189, +242, 75,137,216,225, 38, 4,186, 68,244, 41,182, 40,247, 57, 33,132, 39, 21, 11, 38,185,136, 5, 67, 53, 28, 23, 70, 1, 8, 9, + 82,202, 84,236,225, 90, 29,183,221,146,125,201, 0, 96, 35, 36, 57, 26, 22,127, 36,210,127,108,135,239,195, 7, 68, 2,166, 64, +169,102,125, 31, 61,203,130,246,190,224,226,226,114,160,123,247,238,174,245,229,118,191,249,230, 27,220,186,117, 75,106, 73, 89, + 91, 66, 8, 95, 32, 16, 79, 22,203,100,195, 56,142,237, 12, 16,202,240,120, 87, 53,170,154,159,117,106,245, 46, 75,247, 62,135, +184,144,222, 66, 6,111,114, 20,251,175, 22,211, 95,120, 60, 94,180, 94,175, 95,245,232,121,124, 62,127,129, 78,167,251,172, 73, + 65, 81,196, 11, 20,173, 65,234, 12, 73, 6, 28,244,200, 66, 44,205, 39,132, 8, 41,165, 90, 68, 17, 47, 24,170,208,137,234,206, +209, 66,143, 76,196,210,252, 38,229, 62,220,231, 46, 98,177,120, 33, 33,164,155, 70,163,241, 22,139,197,121,148,210, 11, 42,149, +106, 45,165,244,138, 37, 50, 44,133, 16,242,150, 76, 38,251, 40, 45, 45,109,167,175,175,239,135, 22,156, 47,227, 51,204, 28,123, + 57,243,146, 90, 75, 59, 3,128, 88,200,191, 86, 89,163, 59,193,178,250,207, 41,165,141, 23, 71,120, 92,142, 59,128,175, 1, 8, + 1,204, 6,112, 55, 43, 43, 11, 44,203,162,125,251,246, 0,208, 14,192, 70, 7, 7, 7, 90, 81, 81, 49,197, 58,240, 61, 91, 54, +255,152, 56, 14, 60, 18, 5, 16, 59, 0, 26, 66,233,230,119,134, 71,252,235,207,106, 15, 33, 68, 36, 22,139,199,239,223,191, 95, +208,175, 95, 63,212,214,214,162,166,166, 6,113,113,113, 88,186,116,169,174,186,186,250, 96,115,140, 0, 66,136,159,189,189,253, +181, 29, 59,118,200,134, 15, 31,142,154,154, 26, 84, 87, 87,227,208,161, 67,136,142,142,174,169,174,174,238,252, 87, 50, 2, 8, + 33,135,218,182,109, 59, 52, 51, 51,243,123, 0,107, 41,165,215,254,236, 54,253, 93,121, 70, 30, 0, 66,192,122,134,170,149,165, +207,247,136,182,153,173, 35,226,178, 21, 49,139,142,245,232,209, 21,231,207,196, 99,221,198,157,207,247, 88,168,253, 40,113, 85, +241, 6,177,204,181, 22, 32,231,205,237, 29, 39,132, 4,120,200,197, 63,190,221,167, 99,235,225,221,131, 37, 1, 94, 78,160,101, +121,184,118,227,150,239,207,105, 15, 94,250, 54,173, 50,138, 16, 50,194, 92,102, 50, 0,168,213,193,135, 43,188, 1, 34,117, 0, + 52, 53,134,135,214,240,151,173,173, 4,163, 85,129, 97, 13,175,213,119,147, 32,125,251,176, 79,243,127, 1,194,119,115,115, 59, +176, 98,197, 10, 87,134, 97,112,245,234, 85, 28, 57,114, 4, 25, 25, 25, 27, 45, 84,254,157, 37,182,118,251, 59,246,248,127,246, +206, 59, 60,138,234,235,227,223, 59,179,187, 51,219,201,166, 16, 2, 33,161,165,208, 67,145,132, 14, 82, 84,164,189, 32,168, 88, + 64, 64, 17, 21, 80,192, 14, 82, 68,252,129, 32,160, 8, 8, 10, 2, 74,137, 40,160, 64, 0,105, 82,162,212, 16, 32, 1, 82, 32, + 33, 1, 66,250,246, 50,187,247,253, 99,179,107, 2, 41,155,208, 44,251,121,158,121,118, 51, 59,115,246,220,201,236,156,115,207, +189,247,156,190,245,106,251, 23,200, 24, 82, 8,223, 58,237,225, 16, 69,132, 36,157, 60,218, 39, 41,254,183,169,132,144,167, 40, +165, 85,230,159,151, 48, 24,126,120, 56, 94,236,249, 35, 68, 0,118,138, 68,162,103, 86,173, 90,133,231,159,127,222,125,204, 79, + 63,253,132,231,159,127,126, 20,128,138, 29, 0, 6, 13,224,192,123,148,194, 7, 0,244,102,152, 30,219,130, 11,199, 62, 39, 29, + 1,180, 37,132,156,234, 24,132, 99,113,131,209, 92,193,137, 36, 0, 64,168,160, 3,197,199, 0, 42,117, 0, 8, 33, 34,137, 68, + 50,167, 94,189,122, 19,150, 47, 95,206, 71, 68, 68, 64,161, 80, 32, 59, 59, 59,244,212,169, 83, 33,211,166, 77, 27, 32,147,201, +190, 48,153, 76, 31,212, 36,233, 75, 57,223,215,139,227,184,185,137,137,137,138,144,144,144, 42, 19,137, 16, 66,122, 40,229,236, +134, 69,159, 76,244,233, 55, 96,176, 68, 19,208, 0,118,107, 17, 50, 83, 19,186,255,248,243,238,152, 79, 23,111,158, 64, 8,121, +134, 82,234, 73, 73,197,229, 91,182,108, 25,168, 84, 42, 49,116,232,208,139,205,155, 55,135, 92, 46,199,198,141, 27, 17, 20, 20, + 4,157, 78,119,113,205,154, 53, 34,171,213,138,215, 94,123,237, 27, 84,163,152, 79,137,174,143,170, 84,170,183,139,139,139,251, + 2, 0,190,232, 81, 15, 34,212,131,128, 44,188,113, 32,203, 83, 57, 95,109,139,127,133, 18,242, 26, 0, 14,160,197,176,211,133, +175, 13,238,184,177, 58,186,220,111,120,158,191,105,177, 88, 42, 92,203,239,105, 98, 33, 94, 68,110, 90,236,168,221,174, 71, 63, +116,234, 55, 12,163,250,119, 67,171,176, 16,156,189,156,129,213,191, 28, 90, 30,221,119,222,242, 63,247,108, 5,199,146, 28,179, +224,120,208, 57, 1, 90, 45, 92,184, 80,220,191,127,127,196,197,197, 97,251,246,237,232,208,161, 3,122,244,232,129, 81,163, 70, +137,151, 44, 89, 18, 14,224, 68, 53,228,189,244,225,135, 31, 42, 6, 14, 28,232,150,215,185,115,103,244,234,213, 11, 99,198,140, + 81,124,254,249,231, 47, 1,248,240, 62,181,165, 38,212,122,246,217,103,153,252,252,252, 17,199,142, 29, 27, 33, 18,137,246,149, +100,222,188,171, 34,112,255, 69, 30, 76, 4, 32,174, 78, 40,136,174,203, 91,223, 42,166,239, 73,224,113,254, 98,154, 15, 64, 57, +152,115,146, 32, 20,235, 97,201,185,249, 72,239, 87,122,116,141, 52,153, 62,123,177,112, 6,168,242, 48, 30,187,113,181, 66,165, + 9,105,222,192, 87,190,255,192,220, 87,253, 67,186, 13, 6,124,130, 0, 85, 0,232,145,245,192,173, 52, 32,249,119, 36, 37, 39, +163,127,156, 54,247,138,158,246,172,202, 40, 18, 66,168,163, 40, 27,248,164, 49, 32,226, 1,177, 20, 16, 75,113,252, 38,240,204, + 15, 89,200, 44,178, 98, 92,215,122,248,226,249, 54,128,136, 7,243,226,166,106,167, 43, 38,132,180, 24, 48, 96, 64,226,168, 81, +163, 48,113,226, 68, 71,102,102,230,124, 0,223, 81, 74,147, 61, 57, 87,169, 9,216, 63,240,165,225,126,207, 62, 53, 6,188, 88, +132,236, 27,215, 32, 85, 4,192,108,103,144,152,120, 12,191,255, 22,139,243, 71, 19, 11,244,133,249,221, 42,107, 47,203,178, 25, + 82,214, 81,223, 95, 10, 20,152, 1,173, 21,144, 72, 36,150, 17, 35, 70,112,114,185, 28, 28,199,129,227, 56,176, 44,139,133, 11, + 23, 90, 12, 6, 3, 39, 18,137,114, 5, 65, 8,186,195,208,190, 69,186, 81,138,185,228,115, 26, 3, 0,123,134,243,216,172,124, + 14, 3, 6, 12, 64,167, 78,157,112,244,232, 81,108,223,190, 29,195,116,235,209,103,147,115,120,146,190, 73,226, 9,193,123, 88, + 72, 15, 85,214,102,142,227,254, 55,104,208,160,137,223,124,243, 13,119,249,242,101,228,228,228, 96,255,254,253,168, 83,167, 14, +234,213,171,135, 22, 45, 90,224,233,167,159, 54,165,164,164,124, 97, 52, 26,223,241,224, 95, 80,217,245,109, 38, 18,137, 14, 28, + 58,116, 72,212,177, 99, 71,159,188,188,188,153,126,126,126, 51, 42, 57,190,103, 68, 88,253, 95,143,236,219, 44,149,242, 18,172, +254,230, 43,124,255,227,239,112, 56, 28, 24,208,183, 13, 70, 62,219, 23, 57,183, 10,241,196, 51,115,140, 55,111, 21,246,167,148, +238,175,226,251,119,126,244,209, 71,143,199,196,196,160, 65,131, 6, 96, 89, 22,233,233,233,200,204,204,132, 84, 42, 69, 72, 72, + 8,212,106, 53,126,248,225, 7,204,157, 59,119, 23,165,212,163, 50,195, 37,178,123,203,100,178,173, 70,163, 81,230,190,103, 87, +244,138,161, 41,135,214, 56,252, 26,207, 96,253, 67,118, 99,116, 92, 65, 69,231,243, 34,230,166,197, 78,107,119,232, 51, 8,209, +125, 6,223,110, 8,113,116,199,102,156, 60,176,163, 90,134,240, 94, 25,233,242, 32,132,208,196,196, 68,176, 44, 91,238, 86,175, + 94, 61,143,126,187,132, 16,106,202,205,196,247, 39,110,224,209,168,198, 8, 13,212,184, 63,187,114, 61, 23, 91,118,237,195, 0, +243, 14,132,191,190,254,129,167, 46, 39,132,116,239,214,173, 91,216,203, 47,191,140, 23, 94,120, 65,111,183,219, 19, 0,180,220, +181,107,151, 10, 0, 6, 14, 28,104,180, 90,173,223,123,146, 45,144, 16,194, 74, 36,146,204,107,215,174, 5,233,116, 58, 52,105, +210, 36,149, 82, 58,147, 16,242,209,222,189,123, 27, 3,192, 99,143, 61,118, 93, 16,132,250,158, 70, 84,239, 37,132,144, 79, 1, +116, 3,240,129,235,119, 68, 8, 57,248,238,187,239,118,115,101,108,212,235,245,136,143,143,199,137, 19, 39,206,153, 76,166,151, + 41,165, 30, 23,187,250,175,227,113, 4,160, 93,187, 87,196, 39, 79,174,176,213,232, 91,196,240,135,201,210,244,231,163,172,223, +220,217,239,238, 5,165, 79,192, 94, 40,135,246,240, 35,176, 21, 2,108,208,111,211,222, 28,150,246,214,135, 95,181,254,236, 89, + 75, 83, 72,149, 23, 1, 92, 45, 79, 20, 33, 68,228,175,144,196,238,159, 61,198, 63,164,215,211, 64,112,115,224,218,121,208,115, +123,156,198, 95,151, 15,168, 3,208,212,239, 42,126,234, 92,236,223,231, 0,126, 36,132, 52,175,178,151,104,209,193, 0, 30,125, +215, 25,240, 74, 7, 9,158,127, 68,134,101,127,222,192,149, 2,231,220,196, 21,191,103,225,179, 23, 98,192, 73,100, 53,186, 4, + 0, 50, 51, 51, 51,173, 50,153, 76, 18, 29, 29,205,100,102,102,166,121,104,252,197, 82,149,250,231,222, 67, 59,248,153,180,199, +145,150,210, 2,141,194,186,129, 87,214,133,222,108,197,153,211,113, 56,245,231, 54, 20,229, 95,131,127,136, 92, 99, 23,108,191, + 16, 66,154, 84,212, 94, 74,105,208,172, 79, 23,224,194,133, 11, 56,127,254, 60, 34, 34, 34,192, 57,113, 27,127,158,231,193,113, + 28,230,204,153,195,113, 28,135,215, 94,123, 77, 3,128, 5, 80,233, 53,236,209,163, 7,250,140, 91,229,254,123,192,128, 1, 24, + 48, 96, 0,172,203, 60,238,100,186,218,220,182, 94,189,122, 19, 86,174, 92,201, 29, 60,120, 16, 6,131, 1,114,185, 28, 26,141, + 6,147, 39, 79,118,181, 3,107,215,174,149,118,233,210,229, 13, 66,200,230,154, 14, 7, 16, 66, 2, 89,150,221,185,110,221, 58, + 71,199,142, 29,125, 50, 51, 51,113,245,234, 85,116,237,218,181,162,227, 85, 10, 25,187,241,216,254, 88,169,143, 56, 29, 69,151, +215,227,227,207,246,225,102,158,211,193,201,184,118, 3,227,135,213, 71, 84,120, 19,252,188,102,146,172,215,208, 79, 54, 18, 66, + 26, 87, 17,146,125, 99,246,236,217, 23,151, 45, 91, 38, 58,123,246, 44,164, 82, 41,100, 50,153,251,213,104, 52,226,214,173, 91, +152, 63,127,190, 0,231, 16, 65,133,104, 52,154, 57, 90,173,246,109, 66, 8,196, 98,113,172, 76, 38, 27, 24, 23, 23, 39,235,218, +181, 43,240,117,215, 58, 16,152,122, 96, 24,134, 74,228, 7,152,252,180,169, 80,214,190,138,216, 97,199,241,212,230,114, 31,238, + 22, 59,173,109,202,203,196,215,191,103, 96, 64, 76, 83,183, 33,108, 21, 22,130,137,207, 60,142, 38, 62, 12, 54, 12,213,160,201, +107,235, 60, 78,239,107,177, 88,106, 95,186,116, 9, 12,195,148,107,164, 3, 2, 2,170, 85, 70,249,118, 74,215, 47,185,125,171, + 14, 44, 47,131,228,183,143,176, 42,241, 49,216, 88, 41, 0,231, 96, 32,235,176,160,105,225, 65, 56,124,238,122,206, 93,141,160, +148, 30, 36,132,156, 59,116,232, 80, 59, 0,169,148,210, 52, 66,136,104,235,214,173,209,163, 70,141, 66,171, 86,173,100, 39, 78, +156,240, 7,112,203, 3,113,237,187,119,239, 30, 20, 16, 16,128, 37, 75,150,128, 82,186,156, 82,186,158, 16, 82,123,203,150, 45, +159,141, 29, 59, 22, 81, 81, 81, 65, 39, 78,156,104,143,106, 84,145,188,135,140,249,249,231,159,125,191,254,250,235,125, 12,195, +100, 80, 74, 63, 4, 64,172,214,191,166,138, 41, 20, 10, 60,241,196, 19,232,219,183,111,139, 15, 62,248, 96, 22,128, 62, 15, 65, +207,127, 36,149, 58, 0,132,144,158, 62, 62, 62, 83, 65,152,142,218,226, 98,149, 88,178,154,202,100,242, 2,234,176,239,212,233, +116,159, 81, 74, 61,170, 40, 6, 48,106, 7, 21,234,102,231, 24,148,157, 98,218,179,176,220, 74,133,254, 88, 43, 16,191,243, 96, + 40,129,144, 31,208,174,105, 29, 75,230, 77,173,204, 65,237,117, 25, 48,234,138, 36,137, 89,246,185,113, 49, 13,131, 67, 59,244, + 4, 52,245,128, 75, 71, 65, 83,254, 0,244,249,128, 46, 23, 40,206, 5,213,230,194,204,240, 8,150, 19, 12,171, 79,131,191, 73, +199, 11, 0,190,173, 84, 69,139, 14,185, 86, 14,199,174, 21,162,101, 93, 27,158,239, 36, 69,159,102,254,248,238, 68, 30, 0, 96, +116,183, 70,224,164, 10, 64,204,123,214,228,219,160,148, 22, 19, 66, 22,157, 56,113,226,237,145, 35, 71, 34, 53, 53,117, 57, 33, +228, 58,165,180,210,218,233, 98, 49,247,114, 88,139,144, 80,130, 91,224, 36,106,112,242,218, 40, 50,152, 97, 48, 91, 97, 48, 91, +113,250,207, 95, 32,230,124,161,244,229,160,187,122, 30, 10, 95,117,125,193,108, 29, 9, 96, 85,101,114, 93,184,140,126, 97, 97, + 33,206,157, 59,135,212,212, 84, 68, 70, 70,162,107,215,174, 8, 11, 11, 67,169, 2, 38,119,246, 38, 40, 4, 66, 80,248,203, 32, +130,206,157, 59,195, 42, 86, 35,126,235, 86,132,135,135, 35, 50, 50, 18,231,207,159,199,238,221,187,209,245,250,117, 40,167,134, + 33, 37, 37, 5,253, 27,162, 16, 76,229, 85,186,120,158,159,186,116,233, 82,254,242,229,203,110,227, 47,147,201, 80,187,118, 89, +187,208,176, 97, 67, 76,155, 54,141,159, 51,103,206, 84, 0, 79,123,210,222,210, 16, 66,100, 34,145,104,231,244,233,211,217, 1, + 3, 6,212, 78, 78, 78, 70,102,102, 38, 50, 50, 50, 42,116, 0,120, 9, 51,105,241,167, 19,125,124,212, 60,112, 37, 22,181,212, + 42, 44,122, 63, 6, 79,191,229,140,244, 47,154,214, 23,181,124, 52,128,195,136,232,214, 33, 24,242, 68, 59,213,230,237, 39, 38, + 1,152, 85,129, 14,191, 2,232,215,161, 67, 7,244,236,217, 19,187,118,237,194,132, 9, 19,220,159, 63,254,248,227,152, 55,111, + 30,172, 86, 43, 66, 66, 66, 68,105,105,105,169,132,144, 10, 39, 6,106,181,218,183, 79,156, 56, 33, 18, 4, 1, 99,198,140, 25, +176,116,233, 82, 89,235,214,173,157, 31, 10,226, 6,142,172,211,207, 48,117,194,226,152,250, 81, 27,145,118,164, 43,110,158,239, + 7,182, 85, 38, 42, 25,146, 97, 57, 57,212,241, 11,176, 50,165, 7,236,140,235,254, 39,144, 80, 19, 90, 21,236,133, 67, 83,253, +212,235, 46,227,127,183, 70,154, 16, 82, 4,160,204,243, 98,218,180,105, 96, 89, 22, 34,145, 8, 81, 81, 81,120,230,153,103, 60, +150, 77, 8, 49, 2,144, 2, 64,143, 71,251,194,148,149, 8, 17,217, 15, 17, 11,136, 24, 2, 63, 25,139,247,186,169,193, 16, 64, + 64, 64,181,116,189,151, 80, 74,243, 1,148, 46,125,158,151,153,153, 9,192,105, 16,225,121,231,142,215,104,156, 78, 93, 90, 90, + 26, 0,184, 28,233, 83, 46,121, 42,149, 10,112,166,222,125, 40,180,108,217, 18, 43, 87,174, 68,102,102,102,200,138, 21, 43,214, +109,220,184, 81,208,106,181, 80,171,157,255,118, 87,177,166,146,242,229, 85,212, 48,247, 82,154,114,111, 18, 66,136, 68,165, 82, +173,171, 91,183,110,191, 9,147,222,148,189,244,210, 24, 82, 88,172,195,178,181, 91,201,205, 91,121,190, 17,181,217,103, 22, 46, + 92, 48, 68, 46,151,127,110, 48, 24, 60, 24, 27,162, 34, 0, 92,112,160,194,112,236,232,126, 58, 60,120,184, 25, 54, 45, 0,155, + 4,150, 91, 42, 0, 72, 74,201, 48,135, 4,169,205, 64, 1, 87,114,124,185, 4,200,217,199,135, 69,135,201, 97,210, 3,183,210, + 65,211,254, 4,138,111, 0,218, 60, 64,123, 11, 86,109, 33,204,186, 34,152,181, 69, 48,218, 40,186, 5, 64,246, 99, 22,158,132, + 7, 14, 64,168,191, 18,231, 39,171,208, 48, 80, 13,136,101,120, 38, 70,131, 46, 45, 66, 96,176,139, 16, 94, 63, 0, 16, 57,135, + 6, 60,133, 16,242,136, 82,169, 92, 96,181, 90, 47, 90, 44,150,151, 1,124, 60,111,222,188,126,139, 22, 45,106,246,241,199, 31, + 51,175,188,242,202, 58, 66, 72, 51, 74,233,141,138,100, 40,124,148, 79,107,252,236,108,131,134, 29,241, 72,204, 72,152,172,118, + 20,233, 77, 48, 90,108,208,155,173,104,223,103, 42,114,114, 50, 33,146, 40,160, 43,254, 10, 86,222,193,152,138, 77, 79,194, 67, + 7,128,231,121, 20, 20, 20, 96,251,246,237,152, 49, 99, 6, 66, 67, 67,177, 99,199, 14,172, 94,189, 26,175,191,254, 58, 34, 35, + 35,129,146, 74,114,119, 54, 16, 87,193, 96,238,128,109,120,226,207,247,157, 83, 5,130, 0,232,116, 58,204,152, 49, 3, 89, 89, + 89,144, 74,165,184,201,247, 5,207,243,248,120,219,199,160,147,240, 9, 28,229, 71,119, 74, 93,183, 14,141, 26, 53, 66,102,102, + 38,228,114,185,219, 1,232,220,185,115,153, 82,180, 50,153, 12, 29, 59,118, 36,132,144, 14,158,180,245,182,239, 96, 88,150,221, + 56,108,216, 48,191,113,227,198,213, 77, 74, 74, 66,102,102, 38,210,210,210, 80, 92, 92, 92,161, 69, 83,200,216,222, 79, 60, 57, + 72,132,252, 29, 0, 43, 5, 24, 41,134,247,107,142,238, 29,155, 2,140, 20,181, 3,252,220,251, 65, 88, 12,126,178, 19,183,115, +255,185,222,168,192, 1, 0,208, 47, 61, 61, 29,114,185, 28, 9, 9, 9,144,201,220, 17, 38, 49, 0,145, 68, 34, 49,185,140,215, +206,157, 59, 33,147,201, 16, 28, 28, 92,225, 28, 0,187,221, 46,170, 93,187, 54, 8, 33,120,231,157,119,228, 17, 17, 17, 48,155, + 75,122,170, 44, 53, 16,193,220,212,113,243,178,157, 9,110,243, 3,120,245, 79,176,232, 59,194, 78, 55,160, 18, 7,192,146,127, + 13, 97, 69,199, 16, 81, 28,143,121, 71,116,200, 55, 57, 96,119, 80,216, 29,192,110, 10, 56, 24,177,235,154, 82, 0, 38, 74,105, +149, 97, 50, 87,155, 88,150, 69,108,108, 44,206,156, 57, 3,135,195,225,254,255,150,200,114, 81, 76, 41,173, 85,129, 40,245,177, + 99,199,192,243, 60,164, 82,169,251,213,245,126,228,200,145, 24, 49, 98, 68,117,156, 11,105,101,242, 30, 13, 83,129,101, 8, 24, + 66, 64, 13,121,158,200,187,167, 72,165,210,231,205,102,115,149, 15, 33,177, 88,220, 11,192,218,170,142,227,121, 62,246,182, 93, + 7,202, 43, 75, 44, 22,139, 99, 1,248,123,170,231,189,196,106,181, 98,201,146, 37, 96, 89, 22, 11, 22, 44,192,244,233,211, 69, +171, 86,173,194,185,115,231, 16, 30, 30,254, 48, 84,250,215, 80,174,161, 85, 42,149, 43,186,119,239,222,127,227,198,141,210, 35, +167, 46,161,176, 88,135,109, 91, 54, 98,249,252, 89,232, 55,242, 3, 12, 30,254,180,232,213, 87,199,137,122,244,232, 49,145,101, +217, 44,187,221,190,188,242,175, 97,138, 25,194,100, 13,238,162,202,155,191,100,109,135,225, 3, 59,158,130, 45, 15,160, 42, 2, +123,113, 32, 8,167,251,228,203, 29,234, 65,157, 21,121, 12, 41,202, 2,152,138,139, 58, 56,104,155, 48,127, 5,160,189, 5,154, +157,228, 12,249,107,111, 65,208, 21,194,162, 43,132, 89, 91, 8,147,182, 8, 70, 93, 49,204, 14,160,142, 20,176, 58,208,166,202, + 43, 97,214, 1, 18, 25,154, 6,243,127, 25,122,177, 20,245, 2,254,154, 19,224,220, 60,115,132, 9, 33,117, 27, 53,106,180, 99, +255,254,253,126,243,231,207,239,252,229,151, 95,126, 75, 41,141, 39,132,244,120,247,221,119, 79,175, 95,191,190,222,123,239,189, +231, 51,126,252,248,183, 1,188, 89,145, 28,155,213,218,180, 78,131, 86,104,211,225, 5,104, 77, 86, 24,204, 54, 24, 75,122,255, +251,183,126,138,155,215,146, 96, 49,219, 96,179, 3,109, 31, 29,139,128,160, 8,108,158, 59,177,210,246,150,254,129,115, 28,135, +115,231,206, 97,226,196,137,152, 48, 97, 2,142, 31, 63,142,231,158,123, 14, 1, 1, 1, 56,124,248, 48, 90,183,110,237,122, 40, +223,233, 0, 56,103,242,103, 99,193,157, 15, 12,187,189,130, 78,254,231,244,104,101,186, 1,128,197, 98,169, 39,151,203,193, 48, + 12,120,158,119, 59, 0, 35, 71,142, 52,196,199,199,203,111, 63, 94, 38,147,121, 60,145,229,139, 47,190,224, 10, 11, 11,251,180, +107,215,238, 3, 74,105,227,217,179,103,251, 38, 39, 39, 35, 35, 35, 3,187,119,239, 46,142,141,141, 21, 4, 65, 40,254,248,227, +143,203, 61,223, 96,114,180,210,248,214, 1,110,222, 4, 88, 57,192,240, 0, 35, 69, 96,244,255, 0, 0,244,218, 18,167,241,103, +164, 0, 43, 69,235,150,145, 48, 24, 45,173, 42,211, 73, 16, 4,108,218,180, 9, 50,153,204,237, 0,240, 60,127, 93, 16, 4,205, +206,157, 59, 17, 23, 23, 87,230,248,170,202,202,234,116, 58, 16, 66,112,244,232, 81,180,105,211, 6, 90,109,201,232,131, 85,184, + 78, 20,126, 91, 81,124,227, 45, 80,250,179, 93,234,119,145, 53, 22,190, 2, 17,163,170, 76,158,181, 32, 11, 44,195,128, 33,192, + 45,131, 29,243, 54, 28,168,208, 64,114, 28,231,145,135, 92,186,199,127,250,244,105,140, 31, 63,222, 45,107,206,156, 57,183,203, +172, 48, 34,232,186, 30,109,218,220,121,203, 83, 74, 33, 8,130,123,104,193,211,232, 66,101,242,108, 14,184, 29, 0,230, 33, 20, + 45, 55,155,205,210,242,134,246,141, 70, 35,140, 70, 35, 44, 22, 11, 86,172, 88,129,176,176, 48,143, 30, 84,102,179,217,239,135, + 31,126, 0,165, 20, 63,252,240, 3,126,248,225, 7,215,126,152, 76, 38,152,205,102,172, 88,177, 2,141, 27, 55,246,187,183, 45, +241, 28,171,213,138,197,139, 23, 3, 0,166, 76,153,130, 90,181,106,225,131, 15, 62, 64,247,238,221,209,176, 97, 67, 0,101,159, +105, 94, 60,231, 14, 7,128, 56,107,126,142,120,247,221,119,197, 82,169, 20, 18,177, 8, 95,173,221,142, 21,243,103, 65,194, 59, +159,189, 50, 41, 7,127,127,127, 76,158, 60, 89, 49,105,210,164, 55,224, 92,194, 84, 49,118, 90,232, 96,196,233,115,134, 93,191, +216,241,125, 77,167,232, 62,175, 70, 47,120,175, 19, 26, 53,108,105, 75, 75,207,196, 71,139, 15,139,117,186, 98,251,236, 33,183, + 18, 29,140, 36,157,177,211,194,138,133, 57, 8,114,210, 64,253,130, 1, 93, 46, 28,186, 2, 88,180,133,176,232,139, 96,210, 22, +194, 84, 92, 8,163, 94, 7,179, 3, 48,219, 1,131, 13,229,153,174, 59,177,232,176,239,138, 21, 27,206,220, 66,139,250, 62, 24, +219, 51, 12, 50,137,212,237, 12,216, 24, 9,142, 36,229, 32,186, 69,227, 42, 69, 17, 66, 56,185, 92,254,243,143, 63,254,232,167, + 84, 42,177,107,215,174, 66, 0,137,132, 16, 57, 0,191, 91,183,110,253,242,219,111,191,189, 58,104,208, 32,192,153,116,163,226, +214,218, 97,118, 64,130,171,153,151,145,153,113, 1,188, 50, 24,156, 42, 24, 6,179, 21, 22,171, 13,102,179, 13, 86,171, 0,171, + 69,192,181,148, 51,168,219,160,181, 7,141,253, 11,142,227,144,154,154,138,198,141, 27,227,204,153, 51,208,235,245,208,104, 52, + 24, 58,116, 40,190,250,234, 43,240, 60, 15,148,179, 48,242,126,194,243,124, 86,122,122,122,168, 74,165, 2,203,178,144,201,100, +144,203,229, 24, 61,122,180, 44, 49, 49,241,134,193, 96,104, 70,105,101,247, 72,249,204,156, 57, 51,200,102,179, 29,207,205,205, + 85,154,205,102,229,181,107,215,240,231,159,127,210,115,231,206, 57, 86,173, 90,117, 51, 47, 47,175,144, 82,250, 6,165,244, 96, +101,114, 4, 75, 17,186, 60,189, 19,199,207,164, 2, 0, 46,236,249,107, 88, 62, 41,173, 24,205,186, 59, 67,248, 13, 67,234, 96, +223,246, 69, 85,169,181, 35, 44, 44,172, 95, 80, 80, 16, 62,251,236, 51,200,100, 50,244,233,211, 7,123,246,236,241,175,104, 14, + 87, 85, 15,187, 67,135, 14,185, 13,107,124,124,252,157,199, 19, 16,128,113,128,101,173, 20, 84, 76,236,149, 79, 98,179, 21, 94, + 7,203, 16, 16, 2,216, 28,149, 27, 72, 79, 41,237, 0,216,108,182,187,146,201,243, 60,210,210,210,202, 56, 36, 37,247, 45,236, +118,123,153,104,131, 39, 84, 38,207,102,167, 15,213, 1,248, 47, 98,179,217,144,152,152, 8,142,227, 96,181, 90, 65, 8, 1, 33, + 4, 22,139, 5,165,231, 2,120,169, 62,119, 56, 0,148, 82, 42,145, 72,198, 15, 25, 50,100,113, 66, 66,130,172,125,203, 38,248, + 54,118, 47,250,141,252, 0, 0, 80,219,175, 22, 26,213, 15, 68, 66, 66, 2,222,120,227, 13,131,193, 96,120,185,202,111,241,189, +158,198, 20, 5, 5,115,142,155, 97, 27, 38, 21,112,179, 14,116,234,246,235,233, 64, 20,252,118,177,233,215, 95,127,131, 58,190, + 60,115,240, 19,203, 17, 78, 76,210,192,249, 94, 70,173,235,105, 21,137, 98,224, 56,123,225,194,133, 70,173, 2, 27,193,106,212, +195,170, 43,114,246,250,117,133, 48,106,139, 96,212,235, 97,182, 3,150, 18, 7, 32,169, 24, 96, 8,170, 92, 39, 90,152,151,131, + 33,223,166, 64,107, 22,128,248, 27, 48,131,195, 59,255,215,206,217,227, 23, 75, 49,228,227,173,248,245,207,203, 88, 52,225,255, +170,108, 46,128, 79, 87,172, 88,209,190,117,235,214,152, 53,107, 22,252,253,253,213,254,254,254,133,181,106,213, 18, 7, 6, 6, +162,113,227,198, 24, 58,116, 40, 46, 93,186, 4, 0, 21,182, 21, 0, 8, 43, 62, 13,174, 69,208,201, 63,182, 34, 35,229, 56,172, + 86, 1,173,122,189, 13, 69,173,186,104,213,253, 21,136,226,183, 32,249,212, 30, 88,172, 2, 26,183,232,134,188,172, 43, 96,197, +226,211,158, 40, 9, 56, 31,230,145,145,145,136,139,139,131, 82,169,132,143,143, 15,124,125,125, 17, 27, 27,139, 14, 29, 58, 84, + 62, 7,224, 62, 65, 8,249,243,244,233,211, 33,125,250,244, 33,165, 29,128,225,195,135,147,139, 23, 47,106,190,254,250,235,109, +132,144,238,213,169,251, 61,115,230, 76, 63,189, 94,255,231,181,107,215, 2, 3, 2, 2,216,150, 45, 91,226,250,245,235,120,233, +165,151, 28, 86,171,181,200,225,112,204, 2,176,170, 42,153,114,153,248,236,149,212,196,206, 3,250, 68,185, 29,128, 21, 27,206, +160, 48,233, 51,128,225,241,209,103,191,186,143,237,221,179, 61, 18,206,103, 66,174,144, 85,120,255, 81, 74,159, 36,132, 52,210, +233,116, 23,131,131,131, 69,102,179, 25, 11, 22, 44, 64,139, 22, 45, 0, 0,159,126,250, 41,222,123,239, 61, 0,192, 71, 31,125, +132, 25, 51,102, 84,217,214, 27, 55,110,128, 97, 24, 92,190,124,217,253, 30, 0, 32, 17, 5, 81,125,222, 32, 34, 81,110,131, 96, +181, 16,125, 94, 56, 24,113, 18, 28,130,174, 50,121,182,130,172, 18, 7,128,192,106,167,149, 26, 72, 79, 41,221, 43,183,219,237, +119, 37,147,227, 56, 52,106,212,232,142,253,174, 8, 64,117,231, 23, 84, 38,207,106, 47, 29, 1,240,122, 0, 15, 2,171,213,138, +118,237,218, 97,245,234,213,232,220,185, 51, 66, 67, 67,113,243,230, 77,156, 63,127, 94,176, 90,173,162, 54,109,218,192,223,223, +223, 27, 5,168, 1,229,254, 34,172, 86,235, 42,157, 78,183,176, 69,139, 22,134, 47,191, 88,236,120,246,241,182,104, 25, 22,140, +152, 86,141, 48,184,123, 83,124,240,193, 7,150,206,157, 59, 27, 12, 6,195,115,148, 86, 29,210, 69, 91,106, 3,132, 68, 72,252, + 14, 44,223,229,176, 7,135, 52,102,103,205,154,133,233,211,167, 99,201,146, 37, 32, 98,133,104,249, 46, 56, 32,241, 59, 0, 8, +137,206,227,203,231,166,137,238,218,146,162, 55,234, 46, 28,133,161,168, 0,186,162, 2, 20, 23, 21,160,168,160, 0, 69, 90, 61, +180, 54, 64, 15, 9, 4,191, 6,208,218,128, 35,121, 48,235,109,216, 89,149,138, 50, 98, 1, 39,254,235,114, 88, 28, 76, 73,200, + 95,134, 28,189, 3,191,254,233,172, 56, 25,232, 95,117, 36,172, 89,179,102,195, 71,140, 24, 1, 0,152, 62,125, 58,226,227,227, +153,248,248,120,241,174, 93,187,176,108,217, 50,140, 29, 59, 22,251,246,237,195,232,209,163, 47,162,226,177, 97, 0,128,213,160, +143, 75, 73,248,195,232, 27, 28, 3,139,213, 6,155, 64, 32, 87, 59,115, 22, 73,120, 5,154,119, 26, 6,171,213, 14,177, 68,129, +218,245, 35,145,121,225,148,201,162,215,255, 90,153,204,210,112, 28,135,174, 93,187, 98,199,142, 29,248,245,215, 95, 97, 52, 26, +241,253,247,223,227,127,255,251, 31, 6, 12, 24,224,169, 3,112,121,211,166, 77,176, 90,173, 80,229,156, 64,147,223, 39, 99,132, +121, 19,222,144,237, 69, 56,147, 5,187,221,142, 19, 39, 78, 0,128, 71,101, 59, 13, 6,195,252, 25, 51,102,152, 11, 10, 10,202, +204, 1,144,203,229,248,244,211, 79,185, 54,109,218,180, 81, 42,149,243, 61,109, 35, 33,132,100,101,101,109,209,233,116,181, 39, + 78,156,200, 54,108,216, 16,153,153,153, 48, 24, 12, 32,132,232, 28, 14, 71, 35, 74,233,215,158, 56, 20,122,131,176,119,203,214, +189,214,126,143,117,114, 63,112, 58,182, 15, 71,173, 90,126,168,229,227,143,142, 29, 90,184,190, 19,131, 7,244,193,207,191, 30, +182,232,245,134,189, 85,136,253, 98,213,170, 85,162, 90,181,106, 65,175,215,151,233,213,188,251,238,187,160,148,130, 82,234,145, +241, 39,132, 8,233,233,233, 72, 73, 73,129, 94,175,183,159, 62,125, 26, 55,110,148, 76, 49, 33,224,169,136, 79, 66,157,176, 61, + 96,196, 60, 49, 23, 14,162,156, 34, 30, 18, 73,165,117,212,133,162,108,176, 12, 1,203, 16,216,236,127, 25,200,160,160, 32,104, + 52, 26, 72,165,210,106, 63,124, 75,247,202, 5, 65,184, 43,153, 28,199, 33, 47, 47, 15,122,189, 30,118,187,221,125,189, 0, 96, +251,246,237,240,247,247,135, 70,163,129, 90,173,134, 84, 42,205,185, 27,121,174, 8,128,107,243,114,255,177, 90,173, 88,186,116, + 41, 26, 54,108,232,254,109,216,108, 54, 80, 74,139, 47, 93,186,212,105,195,134, 13, 91,127,249,229, 23,234,154,180,232,197,115, + 42,156,108,167,211,233,166, 17, 66,118,125,242,201, 39,147, 9, 33, 29, 12, 6,131, 63,203,178,130, 76, 38,203,178, 88, 44,187, + 12, 6,195, 98, 74,233, 21,143,191,233,209,156, 28,236,171,119,184, 78,128,202,239, 64,226,133, 62,159,124,242, 9,242,243,243, +241,197, 23, 95, 0, 0, 83, 39, 64, 29, 11, 86,124, 24,143,102,229, 87, 38,198,102,199,119, 43, 82,241, 78,183,128,140,198, 13, +106,235, 96,101, 57, 24,180, 69, 48, 26, 77, 48,219, 1, 43,195,129, 11,110, 10,179, 85,192, 69, 45,176, 63, 7,217, 22, 71, 21, + 19, 0, 1,112, 14, 19,246,191,219, 29, 43,127,207, 68,131, 58, 26,140,237, 27,229, 30,247, 15,240,231,241, 92,159,246,168, 95, +199, 31, 67,250,118, 2,166,125, 93,169,172,228,228,228,221,219,183,111, 31, 57, 96,192, 0,204,154, 53, 11,241,241,241,160,148, +162,184,184,216,150,157,157,157,157,149,149,117,165, 36,105,197, 2, 74,105,165, 53, 16,108, 54,203,215, 73,199,246, 76,108,220, +182,107,147,134, 81, 79, 35,249,207, 88, 8, 86, 35,196,156,115, 56, 70, 44,145,162,110,163, 40,248, 6, 54, 68,193,141, 12, 36, +255,177, 47,211,102, 51,175,169, 72,222,237, 15, 85,158,231, 17, 22, 22,134,201,147, 39,227,224,193,131,120,246,217,103, 17, 19, + 19,131, 57,115,230,160, 89,179,102,224, 56,206,181,206,185, 50, 7,160,223,194,133, 11,231,172, 95,191,254,169,197, 35,163, 73, +175, 94,195, 16,209,251, 13,156, 90, 53, 5,133, 59,119, 98,213,111,251,168, 78,167,139, 5,240, 65,165, 23,174, 4, 74,233, 41, +153, 76,246,197,196,137, 19,223, 88,191,126,189,212,223,223,223, 61, 54,206, 48, 12,126,250,233, 39,121,243,230,205, 95, 17,137, + 68,199, 4, 65,216, 82,149,188, 97,195,134, 45,200,201,201,105,251,200, 35,143,136,215,173, 91,135,253,251,247, 35, 53, 53, 21, +118,187,221, 8,231,250,226, 74, 13, 96,105,204, 86, 97,209,188, 47,183,188,254,100,159, 54,254, 91, 86, 77,196,180,255,109,198, + 83, 3,187, 0,172, 12, 96,164,120,106,112, 31,204, 94,240, 35,222,157, 60, 26, 98,137, 28, 91,182,255,166, 53,155,173, 85,141, + 3, 88,247,237,219,135,147, 39, 79,226,243,207, 63, 23, 66, 66, 66,220,191,203,234, 70, 0,196, 98,241,188,117,235,214,189, 13, + 0, 12,195,196,110,221,186,117, 96,183,110,221, 74, 38,229, 9,153, 76,189, 86,107, 65, 68,188,227,218,169, 97,132, 66,204,212, +107,245, 19, 80, 88,225, 36, 84, 0,176, 23,102,187, 35, 0, 54, 59,117, 27, 72, 87, 79,189,186, 51,247,121,158,207, 9, 10, 10, + 42,179,164,227,139, 47,190,168,177, 76,158,231,225,231,119,167, 99,238, 50,218,213, 93,167, 95,153, 60,171, 29, 96, 9, 3,134, +193,223, 46, 2,224,233, 16,199, 63,140, 77, 19, 39, 78, 28,255,210, 75, 47,185,135, 0,214,172, 89,227,118, 4, 40,165,199, 0, + 12, 38,132,132, 93,185,114,229, 13, 0,103, 30,170,182,255, 48, 30,120, 57, 96,137,132,140,155, 48, 97,242,146,185,115,231,138, +115,114,114,176,117,235, 86,204,154, 53,203, 82, 84,148, 59,201,106,165, 85, 76, 38,116, 66, 8,105, 91, 87,134,221, 95,181,133, +175, 15, 79, 96, 22, 40,204,118,103,200, 95, 28,212, 24,118,177, 12,201, 23, 47,226,243,243,214,130, 2, 43,250, 84,181, 70,156, + 16, 66, 11,190, 26,228, 12,247,139,164,128,152, 43,245,190,212,190,146,191, 53,157, 95,168,244,161, 66, 8,145,107, 52,154,227, +241,241,241, 77, 21, 10, 5,218,183,111,127,227,250,245,235, 45,224, 44,216, 81,237, 11,238, 74, 4,244,196,184,105,126,140,200, + 1,131, 54, 31, 65, 13,203,142,151, 22,221,202,198,142,165, 51,243,116,133,183,122, 84,145, 8,200,182, 96,193, 2,209,185,115, +231,112,254,252,121,184,126, 88,149,109, 37, 19, 1,171,124,218,189,208,156,244,173,167,192,162, 78, 79,142,136,232,247,225,122, +108,155,241, 52,254,140,219,116, 49, 75,143, 73,107,207,211,221, 85,157,127, 91,155, 69, 82,169,116,142, 72, 36,122, 99,250,244, +233,124,116,116, 52,137,136,136, 64, 70, 70, 6,126,255,253,119, 58,115,230, 76, 51, 33,228,131,194,194,194,207, 43,146,241,202, + 43, 67,249,255, 56, 0, 0, 32, 0, 73, 68, 65, 84,175,136, 51, 50, 50,190, 47, 46, 46, 30, 92, 92, 92, 44, 42, 42, 42, 66, 65, + 65,129,205, 98,177, 24, 1, 56, 0, 76,164,148,174,171,142, 94, 37,186,245, 12, 12,168,181, 61,118,229, 4,121,235,230, 33, 80, + 40,212,127,205,252,103,164,208,155, 41,142,159, 78,193, 83, 35, 38, 26, 10, 10,139, 6,120,144, 8,232,142, 84,192, 64,197,227, +223,132, 16,143,141, 26, 33,164, 55,203,178, 91,237,118,251, 95,137,128,150,246,236, 64,175,252,254, 61,241,107, 50, 13,202,186, +123,240,218,111, 21, 58,221,132, 16,122,233,253,230,112,152,138,193, 16,130,199, 86,223,192,241,203,215,225,239,127,231,132,112, + 74,105,181,116, 43,253, 29,185,185,185, 53,146, 73, 8,161, 90,173, 22, 82,169, 20, 34,209,157,253,153,234,234,227,137,188,210, +240, 34,146, 99,178, 61,184, 76,128,132,144,151, 43,154, 4,104,177, 88,220,147, 1,195,194,194, 64, 41,173,188,167,130,146, 36, +104,142, 59, 3, 95,165, 39, 1,154, 76, 38, 52,110,220,248,129, 39, 60,114, 65, 8,105, 11, 96,101, 84, 84, 84,212, 43,175,188, +130,232,232,104,215,208,101, 62,165,244,161, 77, 78,252, 55,240,192, 29, 0, 66, 72,109,181, 90,189,187,184,184,184, 37, 74,150, +151, 73, 36,146, 68,171,213,218,151, 82, 90,101,120,174,148,156,182, 62, 18,108, 26, 92, 15,117, 91,249,128,215, 72,156, 14, 64, +166, 17, 56, 83, 8,243,161, 91,200,214,217, 48,220,147, 4, 49, 74, 94,114,217,102,183, 7, 3,228,182,233,110,229,220,239,132, + 64, 44, 22, 93,211,233,141, 97, 85,232,215,176,121,243,230,103,226,227,227, 85,115,231,206,197, 39,159,124, 18, 77, 41,253,211, +211,246,149, 35,207,153, 10,184, 99,159,122,161, 45,163,101,190, 65, 33,160, 14, 7,242,175, 95, 69,198,249, 19,198,164,248,223, + 50, 77,218,194, 42, 83, 1,115, 28,151, 97,181, 90,171,149,202,216,227,204,108, 19, 72, 61, 72,240,212, 77, 29, 70,167, 22,161, +110,152, 15,178, 2, 20,248, 22, 20, 63, 98, 1,189, 86,157,239,116, 65, 8,105,171, 86,171,167, 18, 66, 58,232,116,186,122,114, +185,252, 22,195, 48, 39,139,138,138,166, 87,149, 3,188, 99,199,142,210,162,162,162,147,197,197,197, 98,173, 86,107,210,235,245, +121, 0, 14,192,153,208,228, 24,165,212, 88, 19,157, 74,244,234, 41,151,241, 27,135,244,235,160, 26,220,191, 43,215,186,101, 83, +128,229,145,112,254, 42,126,222,126,200,178,101,251, 30,173,193, 96,124,186, 42,227, 95,129,236, 95, 1,244,163,148,150, 27, 1, +168,129, 81,123,148,101,217,183, 5, 65,112,166, 2, 94,254,104, 93, 56, 72, 16, 24,123, 46,198, 29,184, 90,217,185, 82, 17,115, +211,108,167,101,122,235,247,210,224,150,156, 83, 99, 35, 78, 8, 49, 0,168,108,217,161,142, 82, 90,233, 42,135,219,228,217, 80, +249, 26,122, 43,165,180,242,101, 24,247,145,106, 44, 3, 52, 89,173,214, 42,157, 91,153, 76,118,211,100, 50, 85,153,120,137,227, +184, 28,179,217,252,160, 83, 30,151,129, 16, 18, 13,224,219,182,109,219, 70,190,246,218,107,120,233,165,151,188, 14,192, 93,242, +192, 29, 0,247, 23, 19, 50, 3,192, 71, 0,102, 82, 74,103,212, 80, 6, 39, 23, 97, 2,199,226, 49, 7, 69, 19, 10, 16, 80, 92, + 54,217,177,219,234,192,226,170,194,235,247, 27, 66, 72,231,224,224,224,175,243,242,242, 46,155, 76,166,161,119,155,179,158,148, + 20, 3,226, 20,138, 39,237,118,161, 53,113, 22, 3, 74,168,110, 49,160,251,198, 76, 34,130, 14,173,224,128,194,189,143,162, 24, +118, 36, 99,201,195,253, 95,220, 15, 8, 33, 42, 94, 34,153,164, 80,240,189, 93, 75,253,228, 10,217, 89,189,222,176,215,108,182, + 46,170, 34,251, 95, 85,178, 43, 12, 22,213,196,200,222, 43, 8, 33, 22, 84,158,108, 69,160,148,138,171, 41, 83, 11, 64, 89,201, + 33, 70, 74,233, 29,203, 63,189,252, 55, 33,132,116, 7,176, 12,192, 33, 74,233,184,135,172,206, 63,154,135,230, 0,120,241,226, +165, 98, 56,142, 43,146, 74,165,229, 26, 90,147,201,100,181, 88, 44, 21, 37,198,241,226,197,139, 23,143,240, 58, 0, 94,188,252, + 13, 33,132, 40, 1, 84,212,235, 53, 80, 74, 43, 93,186,231,197,139, 23, 47, 85,225,117, 0,188,120,241,226,197,139,151,255, 32, +213, 91,191,227,197,139, 23, 47, 94,188,120,249, 87,224,117, 0,188,120,241,226,197,139,151,255, 32, 94, 7,192,139, 23, 47, 94, +188,120,249, 15,226,117, 0,188,120,241,226,197,139,151,255, 32,149, 37,188,240,242, 47,135, 16, 34, 18,137, 68, 35,229,114,249, + 0, 65, 16, 90, 1,160, 44,203,158, 49, 26,141,191, 8,130,240,240,243, 10,252,141,233,219,183,175,220, 98,177,188, 38, 8, 66, + 71,187,221,222, 94, 16, 4, 8,130,112,194,102,179, 29, 99, 89,118,233,217,179,103, 13, 15, 91,199,251,193, 87,219,226, 95,161, +132,188, 6,128, 3,104, 49,236,116,225,107,131, 59,110,124,216,122,121,241,226,165,250,120, 87, 1, 60, 0, 8, 33,245, 1,140, + 84, 40, 20,109,245,122,253, 41, 0,107, 40,165, 15,181,114, 5, 33,164,149, 92, 46,223,220,186,117,235,122, 17, 17, 17, 50, 87, +253,117,157, 78,135,196,196, 68,227,217,179,103, 51, 13, 6, 67,149,153, 5,255,139,244,234,213,171,139, 32, 8,107, 4, 65,104, + 88, 98,248,203,108, 50,153,236,170,175,175,239,203,123,247,238,173,170, 8,208, 63, 2, 78, 68,110, 90,237,168,221,161,207, 32, + 68,247, 25,140,145,253,187,161,117, 88, 8, 18, 46,103, 96,205, 47,135,112,116,199,102,156, 60,176, 3, 18, 22, 57, 22,129, 86, +153, 45,142,231,249,155, 22,139,165,194,236,115, 30,103,158,244,242,159,130, 16,194,116,235,214,237, 25, 65, 16,166, 21, 23, 23, +135,168, 84,170, 43, 90,173,246,131,243,231,207,111,173, 73,138,117, 47, 94, 7,224,190, 67, 8,169,223,187,119,239,243,243,231, +207, 87,182,108,217, 18,241,241,241,120,243,205, 55,181,199,143, 31,111,241,176,156, 0, 66, 72, 11,181, 90,189,127,228,200,145, +126,253,251,247,135, 68, 34, 65,110,110, 46, 68, 34, 17,172, 86, 43,146,147,147,113,236,216, 49, 28, 59,118,172, 64,171,213,118, +243, 58, 1,127,209,171, 87,175, 46, 54,155,237,160, 32, 8,140,203,224,219,237,246, 50, 14,128, 82,169, 68,104,104,168, 67,165, + 82,253,223,119,223,125,183,173,186,223, 33, 18,137,110,218,237,246,218, 0, 32, 22,139,115,172, 86,235,195, 78,193, 74, 77,185, +153,248,250,240, 85,244,143,105,134, 6,129, 26,247,103, 87,178,111, 97,199,238,221,120,204,188, 7, 77, 94, 91,239, 81,134, 66, + 66, 8, 77, 74, 74,114,151, 3,118,149, 6,118,253, 29, 20, 20,244,208, 50, 29,254, 27, 32,132,180, 6, 16, 2, 32,155, 82,122, +242, 46,101, 49, 0, 62,143,140,140,252,191,228,228,228, 79, 41,165, 75,239,137,146,213,160,107,215,174,205,164, 82,233,220,236, +236,236,158,189,123,247,150,191,248,226,139,136,136,136, 64,114,114, 50, 86,175, 94, 77,247,237,219,103, 82, 42,149, 59,147,146, +146,222,209,106,181,233, 15, 90,191,127, 50,149, 58, 0,132, 16, 51, 0, 14,128,148, 82,106,190,171, 47,114,202,114, 35, 22,139, +221,149,191,164, 82, 41,174, 94,189,250, 19,128,103, 61,149, 39, 18,137,210, 25,134,161, 0,142,216,108,182,131, 0, 54,220,173, +142,247, 3,145, 72,180, 32, 45, 45,237,173, 95,126,249, 5,107,214,172,193, 11, 47,188,128, 6, 13, 26, 96,192,128, 1, 11, 40, +165, 83, 30,180, 62,132, 16,177, 92, 46, 79,126,241,197, 23, 27,201,100, 50,180,104,209, 2,117,235,214,117, 23, 17,185,112,225, + 2,206,158, 61,139,220,220, 92,104,181, 90, 92,185,114,229,170,209,104,108,242,111, 25, 14, 32,132, 4,137,197,226,197, 74,165, +178,167,195,225,128, 78,167, 59, 96,183,219, 39, 81, 74,179,170, 58,183,111,223,190,114,147,201,148,104,183,219,221, 61,127, 0, + 8, 15, 15,135, 78,167,195,197,139, 23, 97,181, 90, 97,183,219,209,176, 97, 67,180,111,223, 62,151,231,249,200, 57,115,230, 84, + 90,225,178, 28, 29,105, 81, 81, 17, 28, 14, 7, 52, 26,205, 67, 55,134,132, 16,106,213,230,225,135, 89,163,113,201,175, 39,236, + 44,239,220, 15, 64,226, 48,163, 85,193, 30,180,240,165, 8,127,123,167,199, 14,192,197,139, 23,203, 24,253,210,239, 3, 3, 3, + 31,122,155,255,169, 16, 66, 30, 1, 0, 74,233,113, 66,200, 64, 0,191, 82, 74,237, 53,148,197, 0, 88, 53,111,222,188, 81,111, + 78,154,132,136,200,200,162,180,180, 52,205,131,236,109,199,196,196,236,243,245,245,237, 54,122,244,104,246,241,199, 31,135, 72, + 36,130, 32, 8,176,217,108, 46, 29, 65, 41, 69, 92, 92, 28, 86,173, 90,101,191,126,253,250,222,115,231,206, 61,254,160,244,251, +167,227,233, 28, 0,147, 88, 44,134, 32, 8,119,227, 8,184, 11,104,136, 68,162, 50,198,159,231,249,106, 11,179,219,237, 13,118, +236,216,129,249,243,231, 55, 76, 79, 79, 31,114,253,250,245,217,132,144,231, 40,165, 7,107,168,223,125,197,225,112,192,110,183, +195,104, 52, 66,167,123,120, 73,220, 68, 34,209,203, 81, 81, 81,161,174,107,206,178, 44,180, 90, 45, 76, 38, 19,140, 70, 35, 18, + 18, 18,192, 48, 12,120,158, 71,126,126, 62,106,213,170, 85,223,106,181,142, 4,176,234,161, 41, 93, 10, 66, 72, 61, 0, 63, 3, +184, 74, 41,125,170,154,231, 6,105, 52,154,164,208,208, 80,181,195,225,128,197, 98,129, 90,173, 30, 98,183,219,251,198,196,196, + 68,197,199,199,167, 86,118,190,201,100,122,173,116,216,191, 67,135, 14,232,210,165, 11,110,221,186,149,115,227,198, 13,129,227, +184,186,137,137,137, 40, 46, 46, 70, 82, 82, 18,218,183,111,239, 47, 22,139, 63, 3, 48,170,186,237, 84,171,213,136,141,141,173, +238,105,247, 13, 75, 65, 22,194,138,227, 17,161,253, 3,255, 59,162, 69,190,209, 1, 7, 5, 4, 7, 16,231,160,160,140, 51,253, + 63, 33,132, 2, 48, 81, 74, 43, 43,208, 3,134, 97,220,219,143, 63,254,136,196,196, 68, 56, 28, 14,184, 42,211,149,200,113, 81, + 76, 41,245,166, 62,174,130,210,198,191,100,215, 5, 0,157, 1, 28,170,129, 44, 6,192,170,185,115,231,142,122,115,210, 36,104, +181, 90, 60,251,204, 51,181,102,127,252,241, 60, 0, 83,239,153,210, 85,144,159,159,223,228,216,177, 99,172,203,217, 54,153, 76, +176,217,108,112, 56, 28, 32,132,184,203, 70,235,116, 58,100,101,101,177, 55,110,220,104,245,160,116,251, 55,224,145, 3,192,178, +172,203, 96,155, 66, 66, 66,144,145,145, 81, 19,239, 92, 10,192, 36, 18,137,202, 24,126,158,231,113,225,194,133,205,168, 70,239, +223, 69,223,190,125,145,144,144, 0,149, 74, 37, 79, 73, 73,145,127,251,237,183, 59,100, 50,217, 60,163,209, 56,179, 6,250,221, + 23,236,118,251,226,177, 99,199,142,157, 53,107,150,242,197, 23, 95,196,217,179,103,241,234,171,175,234, 1, 44,169,169, 76, 66, + 72,103, 0, 95, 1, 48, 1,152, 76, 41, 61,226,233,185, 62, 62, 62, 79,215,173, 91,151, 13, 8, 8, 64,211,166, 77, 97, 54,155, +161,211,233,220, 17,128,168,168, 40,228,229,229, 33, 52, 52, 20,133,133,133, 32,132, 48,122,189,254, 73,252, 13, 28, 0, 66, 72, + 19, 0,123,225, 12,111, 86,187,146,159, 88, 44, 94, 28, 28, 28,172,182,217,108,176, 88, 44,238,173, 89,179,102,138,134, 13, 27, +174, 5,208,177,178,243, 5, 65,232,104,179,217, 32, 8, 2, 24,134, 65,207,158, 61,145,147,147,243,246,164, 73,147, 62, 3,128, +199, 30,123,108,184,217,108,222,224,114, 16, 50, 50, 50,208,171, 87,175,104, 79,116, 43, 29,246, 87,169, 84,102, 74, 41,175,209, +104,224,235,235,107,118, 25, 67, 79,199,198, 75, 38,119, 94, 23, 4,225,206,250,186,165,144,201,100,153, 6,131, 33,196, 19,253, + 44,249, 89, 96, 25, 6, 12, 1,114,245, 14,204,219,120,192,237,196,223,238,204,115, 28, 87,101,181,186,210, 14, 64, 66, 66, 2, +198,143, 31,239,150, 51,103,206,156,219,229,169, 61,209,241,191,204,109, 61,127, 5,128, 8, 0,137,168,129, 3,224, 50,254,159, +126,250,233,168,183,222,124, 19, 71,143, 30,197,190,125,251, 48,112,192, 0, 44, 94,178,164,210,223,200,253,192,106,181, 2, 0, +244,122, 61,204,230,191,250,159, 54,155, 13,191,253,246, 27, 54,109,218, 4, 95, 95, 95,140, 31, 63, 30, 51,103,206,252,219, 69, +129, 31, 6, 23,134,145,114,163, 52,205, 54,151,141,172, 85,233, 0,176, 44,235,254, 49,186,182,168,168, 40, 42,149, 74,113,236, +216,177, 13,240,208,112, 83, 74,205, 98,177,184,140,225,119,189,103, 89,182, 70, 33, 42, 0,208,104, 52, 80, 42,149,232,213,171, + 23, 30,125,244, 81,217, 51,207, 60, 51,149, 16, 18,119, 55,165,119,239, 37,148,210, 76, 66, 72,243,189,123,247,110, 75, 73, 73, +105,109, 52, 26,145,148,148,116, 24,192,205,187, 16,187, 0, 64,139,146,247, 95, 1,104,233,233,137, 86,171,181,105, 96, 96, 32, +194,195,195, 97, 48, 24,220,134,223,104, 52, 98,223,190,125,200,206,206,134,201,100,130,213,106, 69, 76, 76, 12, 2, 3, 3,241, +205, 55,223,180,185, 11, 93,171, 77,201, 3,108, 56,128,109,148,210,188,146,125,145,112,150,242,173, 13,224, 79, 0,255, 87, 93, +185, 50,153,172,231,237,198,223, 98,177, 32, 47, 47, 15,163, 71,143,174,178,141, 54,155,205, 53,219, 31, 81, 81, 81, 40, 40, 40, +200,125,253,245,215, 63, 3, 64, 1, 32, 46, 46,110,163, 70,163,153, 46, 8, 66,164, 32, 8,184,113,227, 6, 26, 53,106, 20,234, +137,110,118,187,189,118,113,113, 49, 84, 42, 21, 28, 14, 7, 95, 92, 92, 12,141, 70,131,227,199,143,243,106,181, 26,106,181, 26, + 98,177,184,202,178,173, 37,136, 8, 33, 26,189, 94, 15,185, 92,238,126,112,186,194,166,174,146,187,117,234,212, 9,242, 80, 30, +108,133,217, 96, 25, 2, 66, 0,155,131,130,227, 56,180,105,115,231, 37,243, 52, 58, 92,218, 1, 16, 4,225,174,229,253,151,185, +205,248,251, 82, 74,243, 9, 33, 44,128,103, 0, 36, 84, 83, 22, 3, 96,213,252,249,243, 71, 77,156, 48, 1,199,142, 29, 67,253, +250,245,145,158,158,142,110, 61,122,164, 25, 12,134,217,247,161, 9, 21, 66, 41,133,217,108,134,221,110,135, 94,175,135,197, 98, +129,217,108, 70, 90, 90, 26,226,226,226,224,235,235,139,151, 94,122, 9, 34,145, 8, 22,139,197,123,191,148,112,187,161,175,136, + 74, 29, 0, 87, 40,184,162,173,186, 8,130, 32,229,121,222, 84,218, 9, 56,117,234, 84,141,122,255, 46,124,124,124,160, 82,169, +220,219,130, 5, 11,100,147, 38, 77,138, 37,132, 52,121,216,229,128, 93,148, 56, 1, 51,190,253,246,219,173, 31,126,248, 33,150, + 46, 93,250,248,228,201,147,143, 16, 66, 94,160,148, 94,172,129,200,210, 61, 44, 83,117, 78, 20, 4,193,108,179,217,144,149,149, +133,107,215,174,185,255, 15, 46, 39,192, 96, 48,192,108, 54,195,100, 50, 33, 53, 53, 21,245,235,215,175,129,122,119,205,112, 56, + 35, 14, 83, 8, 33, 61, 0,220, 2,240, 29,156,198, 63, 14,192, 80, 74,105,181,151,217,185,134, 96,110,119, 0,148, 74, 37,218, +180,105, 83,165, 51,236,234,253, 11,130, 0,163,209,136,220,220,220, 59, 28, 87,215, 49,118,187, 29, 44,203,194,223,223,159,245, + 84,191,180,180, 52,100,101,101, 65,173, 86,163, 86,173, 90,208,104, 52,112, 25,255,234,226,112, 56,144,154,154,138,140,140, 12, + 40,149, 74, 40,149, 74, 40, 20, 10, 40,149, 74,112, 28, 7,177,184, 90, 21,123, 75, 57, 0, 4, 86, 59,192,243, 60,210,210,210, +202, 68, 0,170,243, 76,184,221, 1,184, 91,121,255, 37, 8, 33, 26, 0, 29, 0,119,217,237,140, 18,227,223, 24, 64, 27, 66, 72, + 33,156,207,136, 67,148,210,171, 30,200,235,193, 48,204,228,230,205,155, 71, 49, 12, 83, 52,127,254,252,166,175,191,246, 26,230, +205,155,135,105,211,167,167, 62,243,244,211,141, 83, 83, 83,109, 6,131,161, 31,165,244,210,125,107, 88, 57, 80, 74, 97, 50,153, +220,134,223,181,241, 60,143,254,253,251,195, 53,148,231,218,239,117, 0,202,226,138, 4, 84,228, 16, 84,250,208,171,200,240,199, +199,199,111, 40, 57,100, 75,117,148,161,148,154,235,215,175, 95, 38,100,120, 55,189,127,224, 78, 7,224,217,103,159, 37, 95,125, +245,149, 42, 33, 33,161, 39,128, 93,119, 35,251, 94, 66, 41,221, 70, 8, 89, 99, 50,153, 70,190,251,238,187,104,217,178,101,251, +241,227,199,159, 32,132,180,166,148,166, 85, 83,220,120, 56,163, 0, 82, 0,147,171,115, 34,195, 48,167,109, 54, 91,208,153, 51, +103,144,158,158, 14,179,217,140,182,109,219, 66,165, 82,161,125,251,246, 96, 24, 6,103,206,156,129,217,108, 70,211,166, 77,113, +235,214, 45,136, 68,162,211,213,212,239,110,217, 10, 96, 34,156, 81,142, 3, 0,214, 3,104, 15, 32, 11,192,176,154, 24,127, 0, + 48, 26,141,251,101, 50,217,208,162,162, 34,183,241,119, 56, 28,152, 60,121, 50,178,178,178,110,132,135,135, 87,122,190, 32, 8, + 39, 4, 65, 24, 40, 8, 2,206,156, 57, 3, 63, 63,191,192, 17, 35, 70, 60,255,253,247,223,175, 5, 0,181, 90,221,207,213,251, + 23, 4, 1,109,218,180, 65,113,113,113,158, 39,186,137,197,226,156, 54,109,218,212, 6, 0, 95, 95, 95,115, 66, 66, 2,175, 86, +171,209,164, 73, 19,115, 78, 78, 14, 15, 56,135, 0, 60,108,170,192, 48, 76, 65,235,214,173,171, 26, 2,184,238,161, 60, 8,133, + 89,110, 7,192, 21, 1,104,212,168,209, 29,199,221, 77, 4,224,110,228,253, 87, 32,132,248, 1,232, 4,103, 20, 44, 7,128,154, + 82, 90, 84, 98,252, 27, 2,248, 17, 78, 71,153, 80, 74,171,252,255, 18, 66,122, 60,246,216, 99,123,151, 45, 91,198,134,134,134, + 34, 47, 47, 47, 72,165, 84, 98,254,252,249,248,112,218,180,213, 0,198,252,176, 97, 67, 27, 0,186, 7,109,252,129,191, 34, 0, +174,205,101,236, 25,134,129,213,106,117,255,237,122,245,222, 47,127,113, 97, 24,161, 46,195, 95,250,125,105, 42,205, 4, 88,186, +167,206,243, 60, 78,159, 62,189,249,143, 63,254,112,133,253,159, 69, 53, 29, 0, 0,200,204,204, 36, 46,185, 37,142, 68,141,123, +255,128,211, 1, 40,189,201,100, 50,244,235,215, 79, 33,145, 72,122,221,141,220,187,133, 16,210,149, 16,178,138, 16,226, 30, 51, +163,148,142, 90,180,104,209,148, 65,131, 6,217, 68, 34, 17,102,204,152,161, 64, 13, 38,212, 80, 74,143, 80, 74, 59, 80, 74, 91, + 86,103,252, 31, 0, 76, 38, 83,220,133, 11, 23,140, 26,141, 6, 70,163, 17,102,179, 25, 74,165, 18,128,211,225,107,223,190, 61, +140, 70, 35, 68, 34, 17,130,131,131,145,154,154,106, 50, 26,141,191, 86, 87,199,187,129, 82,154, 15,224, 81, 0,231,224, 28,203, +156, 85,242,209,107,119, 83, 6, 55, 60, 60,124,114,139, 22, 45,140,131, 6, 13, 66,203,150, 45,209,179,103, 79,236,220,185, 19, +221,187,119,167,103,206,156,169,114, 66,161, 32, 8,199,108, 54, 27,108, 54, 27,204,102, 51,142, 29, 59,134,228,228,228,239,252, +252,252,146, 21, 10, 69,146,197, 98,249,213, 21, 1, 16,137, 68, 24, 62,124, 56,242,243,243, 61, 90, 66,105,181, 90, 3, 41,165, +132, 82, 74,242,243,243,121, 31, 31, 31, 40, 20, 10,228,228,228,240,174,253,158,174,141,167,148, 10, 86,171, 53,192,117, 94, 69, +155,167,227,255, 0, 96, 47,114, 70, 0, 88,198, 25, 1,224, 56, 14,121,121,121,208,235,245,176,219,237,160,148,122,252,240,229, +121, 62,167,126,253,250,168, 91,183, 46, 2, 3, 3,177,117,235,214,187,146,247, 31,163, 13,128,147, 0, 44, 0,122, 0,144, 17, + 66, 36,112, 70, 4,126,163,148, 58, 40,165, 55, 60, 49,254, 0,192, 48,204,228,101,203,150,177, 70,163, 17, 47,191,252, 50,178, +174, 93,195,213,171, 87,241,209,140, 25, 73, 0,198,148,200, 59,249, 48,140, 63,224,140,100,153, 76, 38,183, 3, 96, 50,153,238, +248,219,229,200,155, 76, 38,239, 61, 83, 77, 42,117, 0, 56,142, 3,207,243, 72, 74, 74,218,156,152,152,184,129,101,217,225,184, + 75,131, 13,192, 29, 1,184, 91,204,102, 51, 52, 26, 13, 52, 26, 13,124,124,124,192,113,206,133, 6, 93,187,118,101,101, 50,217, + 67, 93, 10, 18, 26, 26,186,241,210,165, 75,163,195,194,194,126, 37,132,184, 87, 64, 80, 74, 23,252,241,199, 31,253,191,252,242, + 75, 68, 68, 68,160, 97,195,134, 3, 31,164, 94,130, 32,124,157,144,144,144, 93, 92, 92,140, 38, 77,154,192, 98,177,184, 39,217, + 0,128, 68, 34, 65,195,134, 13,209,182,109, 91,228,230,230, 34, 49, 49, 49, 83, 16,132, 53, 15, 82, 71, 0,160,148,230,194,233, + 4,100,193,121,159,158,166,148,110,191, 27,153, 73, 73, 73,153, 26,141,166, 93,187,118,237, 46,124,251,237,183,246,141, 27, 55, + 82,137, 68,146,181,122,245,234,142, 83,166, 76,249,163,170,243,139,138,138,150,114, 28,119, 69,161, 80, 64, 16, 4,100,103,103, + 35, 45, 45, 13, 38,147, 41,194,102,179, 69,186, 66,255, 0, 48,101,202, 20,132,134,134, 10, 57, 57, 57, 47,214, 68, 87,153,172, +210, 73,244, 15, 28,123, 97, 54, 24,183, 3, 64,193,243, 60,252,252,252,160, 80, 40,192,178, 44, 8,113, 70, 7, 60,193,100, 50, + 5,150,118, 68, 0,220,149,188,255, 24,114, 74,105, 54,128,166, 0, 26, 3,136,162,148, 90,225,236,161, 59,170, 43,172,121,243, +230, 81,161,161,161, 88,188,120, 49, 86,174, 92,153,191, 96,193, 2,176, 44,139, 70, 13, 27,170,107, 34,239, 94,227,138, 0,148, +103,248, 93, 61,127,192, 57, 81,208, 27, 1,168, 62, 85, 37, 2,250,161,228,245,174,141,126, 5,114,183,160, 6, 81, 4,160,234, +108, 98,114,185, 60, 93,175,215,223, 25, 83,124, 64,248,251,251, 95, 74, 74, 74, 10, 91,190,124, 57,166, 79,159,190, 10,192,247, +112, 78,200,105, 13, 96,196,148, 41, 83,198, 60,253,244,211,232,213,171,215,165,194,194,194,136, 7,169,155, 43, 17,208,176, 97, +195,252, 8, 33,208,106,181,104,208,160, 65,153, 99,242,243,243,177,113,227,198, 60,173, 86,219,227, 97, 38, 2, 34,132, 4, 2, +152, 9, 96, 6,165,244,198,195,210,195, 69,167, 78,157,122,171, 84,170,184,130,130, 2,230,210,165, 75,101,230, 5, 56, 28, 14, +136, 68, 34, 76,153, 50, 5,179,103,207,198,186,117,235,166,142, 26, 53,234,179,234,126,135, 84, 42,189,105, 54,155,107, 3,127, +143,172,120,188,136,220,180,216, 81,230,183,166,213,106, 33,149, 74,221, 19, 10, 75, 83,178, 54,219, 99,235, 77, 8,161,247, 82, +222,191, 25, 66, 72, 31, 56,151,247, 25, 1, 68, 1,184, 8,160, 0,192,227,148,210,159,171, 43,143,101,217, 95,211,210,210,250, + 21, 21, 22, 98,225,194,133, 24, 49, 98, 4, 4,155, 13, 3, 6, 13,218, 97,183,219,159,188,183,218, 87, 31,165, 82,185,189, 75, +151, 46, 77,198,141, 27, 23, 33, 22,139,239, 24, 10, 16,137, 68, 48, 26,141,184,126,253,186, 99,235,214,173, 23,211,211,211, 83, +173, 86,235, 3,237, 84,253, 93,241,100, 37,128, 55, 19,224,125,130, 16,242,209,151, 95,126, 57,163,127,255,254,248,253,247,223, +113,228,200, 17, 92,184,112, 1,225,225,225,104,215,174, 29,218,182,109,139, 93,187,118,225,163,143, 62,154, 65, 41,125,224,203, + 22, 93,169,128, 91,181,106, 85, 47, 44, 44, 76, 22, 16, 16, 0, 74, 41,114,114,114,144,154,154,234, 77, 5, 92, 9,195,135, 15, + 31,224,239,239,191,146, 16, 18,144,153,153,137,155, 55,111,186,103,177, 15, 27, 54, 12, 13, 26, 52, 16,226,226,226,222,171,137, +241,255, 39, 64, 8,177, 0,144, 84,114,136, 64, 41,245,120,150, 33, 33, 68, 11, 64, 89,201, 33, 70, 74,169,220, 83,121,255,102, + 74,230, 0,116, 4, 16, 79, 41,205, 37,132,168, 0, 60, 2, 32,213,147, 9,127,229,200,235,209,167, 79,159,189,159,204,153,195, +170,213,106, 92,186,120, 17,179, 62,254,216,126,252,248,241,222,148,210, 3,247, 88,253, 26, 65, 8, 25, 40,151,203,103,245,235, +215, 79,241,228,147, 79, 54, 20, 4,193,237, 4,232,245,122,236,222,189,251,242,241,227,199,205, 86,171,117,218,221, 70, 9,255, +107,120, 29,128,251, 4, 33,132, 19,139,197, 91,222,120,227,141,126, 61,122,244, 64, 72, 72, 8,236,118, 59,108, 54, 27, 82, 82, + 82,112,232,208, 33,172, 94,189,122,135,205,102, 27,242,176, 86, 43,184,138, 1,201,100,178, 39, 5, 65,104, 77, 8,161, 44,203, + 38,120,139, 1, 85,205,216,177, 99, 53,254,254,254,159,213,169, 83, 39, 58, 44, 44,172,129,159,159, 31,163,211,233,242, 10, 10, + 10, 46,228,228,228,188,248,234,171,175, 62,244,104,133,151,127, 39,132,144, 0, 56,141,190, 4,206, 37,168,103, 41,165, 53, 78, +129,235, 90, 5,208,184, 81,163,214, 41,169,169,103, 40,165, 11,255, 46,198,223, 5, 33, 68, 4,224,101,165, 82,249,198,255,253, +223,255,169, 91,182,108, 89,231,232,209,163,215,118,237,218,165, 55,153, 76, 75, 0,172,242, 62,175, 42,167,188,137,128, 94, 7, +224, 62, 82,178,166,118, 16,128,199,125,125,125,123,135,134,134,134, 92,185,114, 37,163,160,160, 96, 47,156, 43, 20,182,254, 29, +198,217,188,120,241,226,229,159, 0, 33, 68,201, 48,204,251, 28,199, 61,105, 50,153,126, 6, 48,143, 82,170,127,216,122,253, 83, +241, 58, 0, 15, 16, 66,136,164,100,194,142, 23, 47, 94,188,120,241,114,223,168,104,233, 95,105,188, 14,128, 23, 47, 94,188,120, +241,242, 47,194,211, 84,192, 94, 7,192,139, 23, 47, 94,188,120,249,151,225,141, 0,120,241,226,197,139, 23, 47, 94,202,197,211, +114,192, 94,188,120,241,226,197,139,151,127, 16, 23,134, 17,119,117,196,102,155,233, 29,197, 53,254, 49, 17,128,215, 95,127,189, +140,162, 5, 5, 5, 80,171,213, 72, 79,191,115,245, 11, 33, 4,141, 27, 55,190, 99,255,151, 95,126,233, 14,135,148,150,231,112, + 56,112,250,244,105, 68, 70, 70, 98,205,154, 53,119,156,199,178, 44,198,141, 27,231,177,188,154,242, 32,229,253,221,174,223,109, +223, 47,138,140,140, 60,216,161, 67,135, 78,229,201, 99, 24,198,110,183,219, 31,138,243, 74, 8, 97,194,194,194,134,117,236,216, + 81, 85,158,110, 18,137,132, 90, 44,150,149,213,148, 41, 10, 11, 11, 75,238,216,177, 99,227,242,100, 2,176, 83, 74,189,206,186, +151,127, 20, 37,171,160,194, 0,180, 45,217,117, 10,192,101,239,202,167, 7,195,133, 97,196, 44,151,163,150,235,111,131, 1, 69, +183, 59, 1, 21, 62, 84, 8, 33,117, 20, 74,213, 68,137, 68,210, 77,161, 80, 4, 27, 12,250,235,118,193,254,123, 81, 81,225, 23, +148,210,140,187, 85,142, 16,162,208,168,196,171, 10,180,182, 23,170, 59, 51,190,160,160, 0,157, 58,117,194,149, 43, 87,208,173, + 91, 55,176, 44, 11,134, 97,220,175,187,118,121, 94, 3,200,225,112,224,212,169, 83,216,188,121, 51,214,172, 89,131, 29, 59,118, +184, 83, 32,115, 28, 7,142,227,208,178,165,199,213,118,203, 80, 84, 84, 4,185, 92,142,171, 87,175, 86,120,140, 88, 44, 70,104, +104,168, 71,122, 38, 39, 39, 35, 48, 48, 16, 27, 55,110,172,240, 56, 31, 31, 31, 60,251,108,229,137, 27,255,206,215,175,196,248, + 31,222,181,107, 87,116, 37,242, 60,174,176,119, 47, 41, 49,254, 67,246,238,221,171, 90,189,122, 53,214,175, 95,127, 71,161,172, +206,157, 59, 87, 43, 99, 93,137,241, 79,216,179,103, 79,227, 53,107,214, 96,247,238,221,119,200, 12, 15, 15,191,167,237, 37,132, +116, 14,111, 80,247, 59,106,183, 27, 47,103,222,124,143, 82, 90,173, 90, 15, 37,213,232, 90, 3,104, 4, 32, 29, 64, 66, 73,253, +134,154,234,163, 6,208, 10, 64, 56,128, 12, 0,103, 74, 82, 65,215, 84,158, 79,137,126,141,239, 70, 63, 66, 72, 59,158,231,167, + 18, 66, 58, 88, 44,150,186, 60,207,103, 81, 74,255, 48,153, 76,255,163,148, 86,171,204,238,189, 64, 44, 22,223, 20, 4,193,211, +146,208,110, 56,142,203, 49,155,205, 30,103,147, 44,249,127,140,133, 51,215, 0, 0, 28, 7,176,146, 82, 90,236,169, 12,134, 97, + 70,114, 28,247,101,235,214,173,153, 94,189,122,193,102,179, 97,239,222,189, 72, 78, 78,118,176, 44,251,186,221,110, 95, 83,173, + 70,120,169, 17,161,171,169, 59, 2,112, 97,216,157,143,166,114, 29, 0,158,231,199,180,127,228,145, 79,191,250,106,185,111, 72, + 72, 8, 88,150,129, 78,111,168,123,241,226,197,246,211, 62,252,224, 69,149, 74,245,137, 78,167, 91, 68,239, 34,124, 80,187,150, +120, 86,144,159,108, 48, 33,166, 41, 0, 62,241,244, 60,151,241,146,203,157,137,193, 88,150,189,195,128, 17, 66,144,146,146, 82, + 97, 79,182, 52,167, 79,159,198,230,205,155, 17, 18, 18,226,106,123, 25, 99,195,113, 28, 68, 34, 17,150, 46, 93, 90, 97, 79,182, + 60,138,138,138, 16, 19, 19,131, 43, 87,174,160,119,239,222,224, 56, 14, 18,137, 4, 98,177, 24, 12,243, 87, 9,134,141, 27, 55, +130, 82, 90,105,222,115,135,195,129, 11, 23, 46, 96,227,198,141, 88,178,100, 9, 78,158, 60,233, 46, 19,171, 82,169, 32,145,252, +149,148,173,180,236,242,184,253,250, 89,173, 86, 56, 28, 14, 56, 28, 14, 80, 74, 17, 24, 24,120, 87,215, 47, 63, 63, 31,130, 32, +192, 85, 52,167, 79,159, 62,213,186,126,145,145,145, 7,119,237,218, 21,237,146,247,248,213,207, 0,171, 17,176, 25, 1,155, 9, +169, 79,237,132, 72, 36, 2, 33,132, 62,232, 72, 64, 68, 68,196,192,184,184, 56, 31, 87,137,228,123, 81, 34, 59, 34, 34,226, 88, + 92, 92, 92,179,219,239,191,187,145, 89, 25,132,144,218,237, 91,183,216,181,123,195,114,133, 33, 59, 25,157,159,122,245,135,146, +178,212, 91,203, 59, 94,169, 84, 94, 54,153, 76, 13, 0, 64, 34,145,228,153, 76,166,247, 20, 10, 5, 29, 56,112, 96, 86,147, 38, + 77,178, 83, 82, 82,176,109,219,182,254,196,121, 3, 39, 2, 56,239, 73, 98,171,146,196, 46,145, 0, 90,201,100, 50,201, 19, 79, + 60,145,213,172, 89,179,236,204,204, 76, 33, 54, 54,246,113, 66,136, 24,192,217, 18,121,230,202,165, 57,151,216, 2,104, 6,160, + 21,207,243,244,177,199, 30,203,108,221,186,117, 86,118,118, 54, 27, 27, 27,219,159, 97, 24,134, 82,234,146, 87,169,126,132, 16, +177, 68, 34,249, 95,253,250,245,199, 45, 95,190, 92, 26, 30, 30, 14,149, 74,133,236,236,236,208, 83,167, 78,133,188,243,206, 59, + 3,121,158, 95,100,177, 88,166, 63,200,228, 51,130, 32,212,214,106,181,238,226, 93, 0,112,241,226, 69,108,218,180, 9,111,191, +253,118,185,245, 85, 10, 10, 10,224,235,235,235,177,211, 64, 8,137, 81,171,213,171,134, 12, 25, 98, 14, 14, 14, 14, 85, 42,149, + 48,153, 76,141,150, 45, 91, 54,138, 16, 50,134, 82, 26, 95,197,249, 50,158,231,183, 15, 28, 56,176,227,202,149, 43,165,118,187, + 29,122,189,115,153,254,184,113,227, 80, 92, 92,140, 73,147, 38, 45, 85, 40, 20, 35, 12, 6,195, 64, 74,169,177, 42,157,196, 98, +241, 41, 65, 16,252, 74,239,147, 72, 36,121, 22,139,165,109, 69,231,120,241,140, 59,172, 5,207,243, 99,198,191,254,198,162,131, + 7, 14,250, 10, 96,176,231,192, 97,236,218,123, 8,167,206,158,131,175,127, 32,126,216,184,201,239,153, 17,207,205, 86,171,213, +239,213,244, 75, 9, 33,117, 2, 3,124,159, 63,188,184,143, 68,206, 75, 38, 18, 66,106, 85,125,150, 19,181, 90,141, 43, 87,174, +224,252,249,243, 40, 44, 44,116, 59, 0,165,157, 0,181, 90,141,199, 31,127,220,163,194, 16,174,176,245,204,153, 51,113,246,236, +217, 59, 42, 32, 74,165, 82, 52,107,214, 12,137,137,137,238, 66, 47, 85,225, 50,254, 46, 35,155,151,151,135,220,220, 92,247,107, +110,110, 46,110,221,186,229,113,225,138,164,164, 36,108,216,176, 1,117,234,212, 1, 0, 28, 57,114, 4, 71,142, 28, 65,124,124, + 60,142, 30, 61,138,163, 71,143,226,240,225,195, 30,201,186,253,250,185, 12, 63,165, 20, 14,135,227,174,174,223,233,211,167,221, +121,241, 93, 91,117,175,159, 43,236, 63,115,230, 76, 36,157, 58, 10,216,204,128, 96,118,190,218, 76,101,228, 57, 28,142, 7, 26, + 9,136,142,142,246,119,233,150,144,144,224, 50,206,204,148, 41, 83,102,175, 90,181,106, 69,187,118,237, 86, 0, 88, 65, 8,161, +174,141,227,184, 74, 13, 68,116,116,116,251,210,247, 95,233, 82,217,165, 74,102,163,180, 76,134, 97,106,108,116, 20, 18,102,250, + 23,179,223,150,214, 74,218, 0,191,227, 11, 49,163,167,143, 82, 41, 33,179, 42, 58,222,100, 50, 53,200,207,207, 23,233,245,122, +145,201,100, 10,140,143,143, 79,209,233,116,151,215,175, 95,111, 12, 15, 15,183,175, 95,191,222,168,211,233, 46,197,199,199, 95, +142,137,137,169, 35, 22,139, 95, 34,132,116,171, 72,158, 92, 46,207, 32,132, 80,158,231, 11,162,162,162, 26,237,222,189, 59,195, + 96, 48, 36,199,198,198,234, 34, 34, 34,236,223,126,251,173, 73,167,211,165,156, 56,113, 34, 57, 38, 38,166,182, 88, 44, 30, 89, +153, 60, 0, 80,169, 84, 7, 88,150,221,222,160, 65,131,166, 7, 14, 28,184,104, 50,153, 46,255,252,243,207,230,136,136, 8,251, +215, 95,127,173, 43, 44, 44,188,116,226,196,137,212,110,221,186,213,229, 56,238, 37,150,101, 43,149, 39,145, 72,230, 13, 29, 58, +116,252,133, 11, 23,164,117,234,212,193,229,203,151,177,117,235, 86, 20, 21, 21,161, 93,187,118,228,192,129, 3,210,152,152,152, + 55,121,158,175,240,186,221, 47,148, 74, 37, 8, 33,136,141,141,197,214,173, 91,221, 67,120, 82,169, 20,107,215,174,197,143, 63, +254,136,184,184, 56, 28, 62,124, 24,167, 79,159, 70,110,174,231,129, 20, 66,136,186, 86,173, 90,171, 94,127,253,245,218,239,191, +255,126,209, 59,239,188,243,205,115,207, 61, 55,178,105,211,166,155, 86,174, 92, 25, 16, 28, 28,188,170, 36, 58, 80, 33, 18,137, +228,243,169, 83,167,118, 89,187,118,173, 52, 33, 33, 1, 73, 73, 73, 72, 76, 76,196,217,179,103,145,159,159, 15,155,205,134, 85, +171, 86,201,134, 14, 29,218, 89, 42,149,126,238,137, 94,130, 32,248, 21, 21, 21,185,159, 83,122,189, 30, 86,171,213,175,234, 51, +255,219,200,229,168,117, 97, 24, 49,187,182,210,195, 1, 46,202,244,158, 8, 33,117, 90, 71,181,249,116,230,140, 25,242,189,135, +226,113,237, 90, 38,222,120,101,148,251,243, 93,123,246,129,147, 72, 48,101,234,219,242, 35,135,127,127,139, 16,178,165, 38,101, + 34,131, 52,146,197,219,190, 95,234, 43,215,216,241,241,203,249,154,183,151,253, 49, 23,192,171,158,156,155,158,158,142, 30, 61, +122,128, 97, 24, 4, 6, 6,150, 49,252,174,247, 34,145,200, 93, 81,172,170,158,172, 43,236,202,113, 28,250,246,237,235,238,245, +151,142, 2,200,100, 50,240, 60,239,113, 79, 86,165, 82, 33, 35,195, 57, 74, 82, 84, 84,132,240,240,112,119,145, 19,187,221,238, +238,113,123, 74,100,100, 36,214,173, 91, 7,192,233,241,247,239,223, 31, 28,199,129, 16, 2,171,213,234,222,170,115,253,204,102, + 51,100, 50, 25, 40,165, 56,126,252, 56, 0, 32, 42, 42, 10, 44,203,214,232,250,229,230,230, 34, 36, 36, 4, 54,155, 13, 47,191, +252, 50, 0,224,179,207, 62, 3,207,243,213,186,126, 46,121,189,211,231, 3,189,156,189,126,102,234, 89, 0,128,227, 3,223, 59, +228, 61,200, 72,192,154, 53,107,220, 97,255,118,237,218, 1, 0, 51,125,250,244,105,219,182,109, 11,168,100, 72,160, 82, 39,197, +213, 94,169, 84,138, 39,158,120,162,220, 8, 64,120,120, 56, 22, 47, 94,236,190, 47, 31,121,228,145,106, 59, 62,132,144,206,237, +162, 90,237,137,253,233,103, 73, 84,179, 64,214,176,254, 19,100,229,235,113,163,200, 8, 7,165, 30, 85, 5, 5,128,232,232,104, +247,141,235,231,231,231,118, 68,162,163,163, 29, 71,142, 28,185,113,252,248,241, 43, 93,186,116,233, 14,224, 80,121,178, 44, 22, + 75,144,201,100,130, 84, 42, 85,158, 60,121,242, 26,195, 48,146,242,228,181,107,215,142, 30, 57,114,228,230,241,227,199,175, 86, + 38, 15, 0,116, 58, 93,247,110,221,186, 89,142, 30, 61,250,232,216,177, 99,247,189,248,226,139,235, 62,252,240,195,116, 63, 63, + 63,183,199,217,182,109, 91,219,193,131, 7,111, 94,190,124, 57,173,101,203,150, 61, 43,146, 71, 8,121, 36, 56, 56,120,220,242, +229,203,185,195,135, 15, 67,167,211,225,218,181,107,152, 50,101, 10, 86,174, 92,137,200,200, 72, 40, 20, 10,124,254,249,231,124, +247,238,221, 39, 17, 66, 54,123, 50, 28, 64, 8,249, 25,128, 31,128,167, 40,165, 55, 75,237,247, 7,240, 51,128, 28, 74,233,144, +170,228, 0, 64,108,108, 44,196, 98, 49, 36, 18, 73,153,232,223,171,175,190,234,254,237,138,197, 98,136, 68, 34, 28, 61,122,212, + 19,145, 46,198, 14, 25, 50,196,252,252,243,207, 39, 52,106,212,232, 81, 0, 89, 82,169, 84, 18, 28, 28,188, 33, 47, 47, 79,190, +100,201,146,254,131, 7, 15, 30, 11,160,220, 26, 23,132,144, 46, 77,154, 52,121,126,234,212,169,146,223,126,251, 13, 86,171, 21, + 17, 17, 17, 88,182,108, 25,242,242,242,176,122,245,249, 75,248,232, 0, 0, 32, 0, 73, 68, 65, 84,106,220,184,113, 3, 6,131, + 1,111,191,253, 54,191,107,215,174,231, 8, 33,235, 41,165, 85,246, 94,212,106, 53, 54,109,218,228, 46,251,238,165,106, 74,194, +255,149,134, 16,203,252,240, 21, 74,213,164, 37, 95, 46,245, 77,186,148,134,130,130, 2,188,241,202, 40,172,254,126, 51,182,237, +216,139, 29,187,127,195,227,125, 30,133, 68, 68, 64, 8,131, 79,231,205,243, 13, 8, 8,152, 86, 93,165, 8, 33,145, 29,218, 54, +235, 21, 16,214,153, 4, 71,143,194,208, 71,195, 69,106,165,108, 8, 33,164,190,167, 50, 74, 27,252,242, 34, 0,174,205,211,158, +236,237, 15,220,219,163, 0, 50,153,172, 90, 61,217,244,244,116,248,251,251, 3, 0,194,195,195,193,178,206,231,245,233,211,167, +177,119,239, 94,156, 62,125,186, 90, 14,192,242,229,203,209,163, 71, 15,216,237,118, 76,153, 50, 5, 18,137, 4,132, 16,140, 31, + 63, 30, 49, 49, 49,152, 60,121, 50,108, 54,155,199,242, 24,134, 41,211,235,119,225,138, 0,212,228,250,149,238,245,187, 16, 4, +161, 70,215,143,231,249,178, 61,127,183, 64,115,185,242, 30,100, 36,160,244,125, 49,123,246,236,119,126,250,233,167,160,187, 29, + 18, 40,125,191,181,108,217, 18, 60,207,163,126,253,250,238,125, 74,165,210, 29, 13,168,233,144,128,146, 99,214, 44,125,119,148, +180,111, 93, 11,123,236,226, 77,252,122,149,193,187,187,114, 44, 51, 15,234,139, 13, 54, 84, 88,178,152,227,184,235, 82,169, 20, +132, 16, 40, 20,138,130,171, 87,175,234,236,118,187, 9, 0, 2, 2, 2,236, 0, 96, 54,155, 77, 91,182,108,209,189,255,254,251, +146, 95,126,249, 69, 5,103,126,250, 42, 57,121,242,164,228, 94,201,219,184,113, 35,151,156,156, 44,234,213,171, 87,207,217,179, +103,175, 9, 14, 14,254,234,155,111,190,105, 14, 0, 14,135,195,250,251,239,191,107,223,127,255,125,242,221,119,223,169, 42,187, +159,121,158,127,127,197,138, 21,124, 90, 90, 26,116, 58, 29, 56,142,115,223,175, 44,203,130,227, 56, 48, 12, 3,181, 90,141,169, + 83,167,242, 10,133,226, 29, 79,218, 10,160, 14,128,206, 0,246, 19, 66,106, 3,110,227,191, 31, 64, 39, 0, 1, 30,202,193,152, + 49, 99, 48,102,204, 24,140, 30, 61,186,140, 3,240,253,247,223,227,199, 31,127,196,175,191,254,138, 61,123,246,224,208,161, 67, +238, 18,233, 30,242, 72,131, 6, 13, 66,131,131,131,143,195, 89,189,116,103,106,106,106,250, 35,143, 60, 98,222,176, 97,195,206, + 22, 45, 90, 52,192, 95,243, 2,238,128,231,249, 87, 23, 45, 90, 36, 77, 73, 73,129,213,106,133, 68, 34,193,173, 91,183,176,104, +209, 34,172, 93,187, 22,133,133,133,238, 33, 85,169, 84,138,201,147, 39,203,148, 74,165, 71, 29, 63,192, 57,191,201, 85,254, 29, + 0, 8, 33,115, 9, 33,115,165, 82,233, 7,213,105,228,127,141, 11,195, 8,117,109,183,127, 86,166,215, 36, 22,139,123, 52, 8, + 9, 65, 98,114, 10, 52, 26, 13, 98,183,237,128,175,198, 23, 10,153, 12, 22,139, 9, 0, 32,149,242,160, 96,208,178, 69, 43, 16, + 66,218, 87, 87,153, 32, 31,241,202, 85, 95,252,207,199,146,254, 11,178,114, 13,176, 16, 21,150,190,255,132,223, 11,239,111,253, + 10,128, 71,229, 39,203, 27,247, 47,253,234,242,130, 93,175, 85,225,234,237,223, 62,246,239,218,228,114,121,153,158,167, 39,136, + 68, 34,136, 68, 34,247,156, 4,135,195,129,188,188, 60, 0, 64, 97, 97, 97, 25, 67,233, 9, 74,165, 18, 10,133, 2, 18,137, 4, + 44,203,194,106,181,226,207, 63,255, 4, 0,156, 60,121,210,227, 8, 0,224,188,126,165, 67,255,109,218,180,113, 71, 37,106,122, +253, 74, 59, 0, 11, 23, 46,116,207, 1,224,121,190,218,215,207,233, 0,152,220, 78,128, 99, 90,128,115, 14,128,213, 84, 35,121, +247,146,210,198, 61, 50, 50, 50,212, 53,107, 63, 33, 33, 1,237,218,181,171,145, 3, 80,250,248, 77,155, 54,161,126,253,250,216, +185,115,167, 59,252,175, 82,169,202,220,155, 53, 65,103,113, 76,120,105,218,146, 95,230,247, 11,100,168,185, 24, 99,191,191,108, + 19,108,182, 47, 45,118,124, 66, 41, 45,168,232, 60,131,193, 16, 34,145, 72,198, 31, 61,122,244, 12, 0,228,230,230, 42,115,115, +115,161, 86,171,141, 18,137, 68,191,120,241, 98,230,226,197,139,178,154,232, 70, 8,185,167,242, 26, 55,110,140,101,203,150,137, +231,204,153,131,165, 75,151,182,156, 49, 99,198,194,166, 77,155, 70,103,103,103,139,197, 98,177, 68, 34,145,120, 34,179,125,120, +120, 56, 82, 82, 82,144,157,157, 13,155,205,134,107,215,174, 1, 0, 50, 50, 50,224,239,239, 15, 63, 63, 63,212,173, 91, 23, 81, + 81, 81,132, 97,152,104, 15,213, 27, 4,224, 0,156,243, 30, 14, 16, 66,158, 2,176, 9,206,121, 11,201, 0,158,242,180,157,155, + 54,109, 42, 55, 2, 48,126,252,120,136,197, 98,247, 38,145, 72,112,240,224, 65, 79,197, 2,112, 70, 47,139,139,139, 15,201,100, + 50,101,114,114,114,122,211,166, 77,179, 1,168,116, 58,157, 66,165, 82, 85,122, 46,195, 48,209,141, 27, 55, 70, 70, 70,134,123, +206,147,175,175, 47,142, 28, 57, 2,135,195,129,182,109,219,194,102,179,185,159, 97,173, 90,181,130,167,215,175,184,184,216,109, +252, 93, 17, 0, 74, 41, 12, 6, 3, 20, 10,133,162, 90,141,252, 15, 81, 85, 50,160, 50, 14,128, 93, 16, 66,101, 50, 25,236,118, + 59, 56, 78, 2,149, 82, 1,169,148,131,197,100, 64,151,206, 49,184,124, 57, 5, 82,169, 12,118,135, 3,156, 68, 12,177, 88, 92, + 89, 9,207, 59, 16,139, 73,183, 55, 70, 60,218, 92, 19,218, 14, 69,191,173,118,238,172,213, 28,143,198, 40, 73,195,250,254, 29, + 8, 33,173, 61, 9,167, 85,230, 0, 16, 66,220,134,203,181, 85,133, 84, 42,189,195,232,187, 30,184,132, 16,183,161,113,245, 60, + 61,107,171,216,237, 0,184,140,171, 70,163, 65, 94, 94, 30,106,213,242,120,202,131, 27,149, 74, 5,165, 82, 9,145, 72,228, 14, +249,183,107,215, 14, 39, 79,158, 68, 84, 84, 84,181, 29, 0, 74, 41, 78,156, 56,129, 54,109,218, 64,171,213, 66,167,211,161,118, +237,218, 53,190,126,130, 32,224,213, 87, 95,197,194,133, 11,113,233,210, 37,164,164,164,160, 71,143, 30, 96, 89,182,218,215, 79, + 42,149, 2,130, 25,204,187, 73,112, 76, 15,196,193, 52, 61, 14, 94, 49, 97, 70, 52,173,145,188,123,137,235,222,224,121,254,142, + 33,129,154, 70, 0, 92, 81,167, 38, 77,154,184,247, 61,241,196, 19, 0,156, 81, 25,165, 82, 89,198, 73,173, 46,132,144,192, 39, +159,124,114,229,148, 41, 83,152,169,111, 78,112, 52,119,164, 50, 22,171,205, 96,181,211, 41,213, 22, 86, 66,113,113,177,236,242, +229,203,218,196,196, 68, 69,105, 35,244,119,144,167,209,104, 48,117,234, 84,102,250,244,233, 56,118,236, 88,173,224,224, 96,143, +138,197, 16, 66, 88, 0,117, 84, 42, 21,174, 93,187,134,183,222,122,171,204,231, 51,103,254, 85,181, 59, 57, 57, 25, 97, 97, 97, + 48, 24, 12,245, 60,145, 77, 41,189, 73, 8,233,129,191,156,128, 83, 0, 56, 56,141,127, 15, 74,105,142, 71,141,195, 95,134, 94, + 34,145, 96,237,218,181,238,253,235,215,175,135, 92, 46,135, 66,161,128, 92, 46,135, 92, 46,175,174, 19,117,220, 96, 48, 52, 58, +126,252,120, 20,203,178, 63, 60,253,244,211, 86, 0, 42, 0,202, 9, 19, 38, 12,185,121,243,230, 85, 56, 87, 4,148,139,217,108, + 14, 86,171,213,176, 90,173,110, 7,192,199,199, 7,171, 87,175, 70, 81, 81, 17,126,249,229, 23, 20, 21, 21,185, 63,139,140,140, +132, 94,175, 15,174, 74, 41,137, 68,146, 87,171, 86,173, 50, 99,254, 26,141,198,188,103,207, 30,239,112,192, 93, 82,198, 1, 16, +137, 68,153,185,121,121,254, 74,133,115,242, 26, 39,145, 64,204, 50, 24,253,242, 24,164,166,166, 65,165,174,229, 52,254,156, 4, +212,225,128, 32, 8,186,234,124,153,255,255,179,119,222,241, 77,214,219, 31,255,156, 39, 79,118,147, 14, 40, 29,236, 33,148, 77, + 89,178,151, 23,244,178, 20, 65, 20, 20, 80,188, 23,245,199, 85, 25, 87,171, 8,130,138, 32,130,162,112,189,128,122,149,161,168, + 12, 69, 68,246, 16, 25, 34,101, 86, 86,129, 66,129,210, 65, 71,246,124,146,231,251,251, 35, 73, 77, 75,211, 38,109, 1,149,188, + 95,175,188,218, 60,121,242,233,247, 73,154,156,243, 61,223,243, 61, 71, 35, 93,250,246,236,183, 35,113,105, 45, 34, 20, 28,158, + 24,220, 1,234,132, 54, 64, 65, 54,150,188, 61,186,230,128,113,139, 63, 1, 80, 97, 84, 33,144, 3, 80,250,241, 80, 35, 0,165, +163, 0, 62,124, 6,199, 55,243, 12, 6, 95, 4,224,224,193,131,104,208,160, 1,106,214,172,137, 86,173, 90, 21, 59, 3,161, 44, + 1, 0, 40, 14, 3, 63,250,232,163,248,231, 63,255,137,246,237,219,227,205, 55,223,132,211,233,132, 32, 8,149,114, 0, 0,143, +129, 49,153, 76,200,203,203, 67, 92, 92, 92,241,227,149,137, 0, 0,158,176,255,133, 11, 23,176,123,247,110,244,237,219, 23, 64, +232,175, 95,241, 18, 0, 0, 8, 54,252,116,217,142, 55,127, 97,152,229,157, 43, 84,230,253,168, 46, 74, 27,226,178,140,126,101, +151, 0,242,243,243,145,154,154,138,129, 3, 7, 98,247,238,221,232,211,167, 15,128,223,223,251, 80,102,197, 68,212, 67, 38,147, +109,149,201,100,138,254,253,251, 75, 82, 82, 82,144,146,146,114, 41,245,120,218,255,157,226,241,129, 32,226,201,202, 92, 63, 0, + 56,157, 78,210,235,245, 18,163,209, 40,113,185, 92, 36,149, 74,129, 32,195,254,183, 67,207, 31,183,219,205,185, 92, 46,146,203, +229, 21,234, 49,198,220, 74,165, 50,239,250,245,235,241, 77,155, 54,197,167,159,126, 10,158,231,145,153,153,137, 89,179,102, 97, +193,130, 5,232,208,161, 3,180, 90, 45,234,213,171,135, 67,135, 14, 33, 34, 34,226,122,176, 99,241, 58, 1, 35, 1,164,194, 99, +252, 29,240,228, 4, 4,109,252, 1, 96,213,170, 85,101, 70, 0, 94,120,225,133,226,227, 62, 35,187,109,219,182,160, 52,189,187, + 46, 14,111,216,176, 97,118,203,150, 45, 91,243, 60,175, 24, 50,100,200,118,135,195,161,158, 56,113,226,131,221,186,117,123,180, +109,219,182,185, 0, 2,214,184, 80, 40, 20,121,121,121,121,181, 35, 34, 34,224,114,185,138,195,253,190, 72,163,111, 9,197, 55, +190,140,140, 12, 68, 68, 68, 84,120,237,254,217,254, 68, 52,151, 49,134,237,219,183,163, 70,141, 26,136,140,140,244, 29,247, 69, + 18, 28,140,177,227, 65, 93,244, 95, 24,255,112,191,255,239,165,163, 1, 37, 28, 0, 81, 20,127, 58,115,230,108,251,134,141, 27, +147,205,230,128, 92, 46, 67, 76, 84, 36,118,238,218, 5,181, 90, 13,155,221, 14,133, 92, 6,185, 76,134,195,135, 15,131,136,142, + 6, 59,160, 8, 21, 63,122,206,139, 15,215, 85,198,212, 3,210, 23,130,151,171,145, 50,117, 18,164, 48, 3, 18, 30,173,146,234, +163,103,151,230,141,164, 82,233,253,130, 32,148,251, 95, 91, 86,226, 95,137,139,242, 36,135, 85,122, 9,160,244, 12, 68,165, 82, +149,152,121, 6,131, 84, 42, 5, 17, 21,207,174, 99, 98, 98, 74, 24,255, 96,119, 20,248,208,104, 52, 16, 69, 17, 23, 46, 92,192, +249,243,231,209,186,117,235,226, 48,123, 40, 73,128,192,239, 75, 0,201,201,201, 16, 69, 17,113,113,113,197,198, 31,168,220,235, +231,114,185, 48,127,254,124, 8,130,128,190,125,251, 22, 27,127, 32,244,215, 79,161, 80,120, 66,255,211,162, 1,193,138, 89, 93, +196, 98,227, 95, 25,189,234,196,103,216,125,134,184, 58, 28, 0,133, 66,129,186,117,235,194,100, 50, 97,224,192,129, 16, 69,177, + 56,114, 4,160, 68, 4, 32, 24, 7,128,136,122,196,198,198,110, 89,176, 96,129,154,231,121, 68, 71, 71, 99,210,164, 73,236,232, +209,163, 93,188,251,235,155, 7,123,189, 26,141,230,188, 40,138,141,187,118,237,202, 34, 34, 34, 10,102,204,152, 49,198,225,112, +112,141, 26, 53,178,243, 60,207, 4, 65,224, 12, 6,131, 76, 38,147,161, 86,173, 90, 66,100,100,100,208,107, 91,185,185,185,124, +122,122,186,194,233,116, 86,139, 94, 89,184, 92, 46,202,207,207, 87, 20, 21, 21, 81,108,108,172, 16, 27, 27, 91,110,178,140, 68, + 34, 57,146,150,150, 54,184, 93,187,118,104,209,162, 5,228,114,121,113, 62, 79,135, 14, 29,208,188,121,243,226,200,224,137, 19, + 39,192, 24,251, 53,216,177,120,215,254,191,193,239,198, 95, 14,224, 27, 34,234, 27, 74,221, 3,159,225,247, 25,123, 31, 43, 86, +172, 40,158,249,251,110, 21,109, 11,246,142,171, 65,114,114,242,207, 79, 63,253,116,221,188,188, 60, 76,155, 54,205,254,206, 59, +239, 12,157, 55,111,222,139, 26,141, 6, 89, 89, 89,153,109,219,182,205, 77, 79, 79,255, 71,121,181, 0,136,232,200,153, 51,103, +106, 39, 37, 37,193,108, 54, 67, 38,147, 21, 39, 63, 3, 40,225, 0,200,100, 50,156, 56,113, 2, 28,199, 29, 9,246,186,125, 24, + 12, 6,212,168, 81,163, 68, 66, 96, 97, 97, 33,120,158, 71,100,100,100,229,214,200,254, 98, 84,212, 3,192, 71, 9, 7, 64,175, +215,125,240,234, 43, 47,143,221,184,233,199, 88, 34, 2, 47,225, 65, 16,145,152, 16,143,188, 27, 55, 32,151, 41, 32,151, 75,193, + 17,225,185,231,158, 45,200,201,201,153, 29,204, 31, 33, 34,105, 98,180,116,238,255, 77,157,169,198,133, 47, 0, 34,216, 85, 45, +208,189,207,255, 33,239,234,111, 80,112, 82,128,227,177,240,173,167, 99,246, 31, 58,255, 31, 34,106, 86, 94,181,168,210,179,255, +178, 30,247,253, 12,117, 9,192, 59,251, 40,129, 74,165, 42,254, 25,170,193,137,136,136,128, 74,165, 42, 54,252, 39, 78,156,128, + 40,138,104,217,178,101, 72, 58,128,231,131, 95,191,126,125,212,169, 83, 7, 78,167, 19, 54,155, 13, 41, 41, 41,224, 56, 14,175, +190, 26,252,174, 76,137, 68,130, 70,141, 26, 85,235,235, 55,126,252,248,106,123,253,148, 74, 37,204, 83,206,222,146,247,163,170, +148, 54,238,254, 75, 2, 85,113, 0,204,102, 51,228,114,121,177,209,247,143, 16,133,226, 0, 16, 81,247,196,196,196,173,115,231, +206, 85, 95,184,112, 1, 82,169, 20, 90,173, 22,105,105,105, 66,101,138,235,120,183, 1,114,114,185, 28, 74,165, 50,142,231,121, +214,177, 99, 71,179, 74,165, 18,207,159, 63, 47, 42,149, 74,183, 90,173,182, 27,141, 70,249,153, 51,103, 34,189,245, 0,130, 74, +202, 92,183,110, 93,205,246,237,219,155, 58,117,234, 20, 80,207,235, 8, 85,168, 23,200,161,150,203,229,238,216,216, 88,187,197, + 98,145,101,100,100,104,206,157, 59,199, 51,198, 2,234, 89, 44,150,185, 41, 41, 41,253,118,237,218,165, 82,171,213,144, 72, 36, +197, 14, 64, 68, 68, 4, 20, 10, 5,100, 50, 25,140, 70, 35,102,207,158,109, 53, 26,141,243,131,185, 86, 34,138,135, 39,225,175, + 57,128,211, 0, 30, 3,176, 22,158, 28,128,221, 68,212, 47,216,247,199,103, 64,125, 78,128,143,241,227,199, 23, 31,247,125,118, +182,110,221, 90,209,184, 26, 36, 39, 39, 31,252,249,231,159, 19,206,159, 63,143,151, 94,122, 9,167, 78,157, 26, 50,120,240,224, +118, 8,177, 16,144,197, 98,249,252,221,119,223,253,219,218,181,107,213,110,183,251,166, 9,132,191, 3, 64, 68, 88,184,112,161, + 89,167,211,125, 30,204, 53,251, 80, 40, 20,230,168,168,168,136,210,199, 14, 29, 58,196, 34, 35, 35, 67, 42,194, 21,166,148, 3, +192, 24,203,210,104, 52,211, 95,159,254,218,130,183,102,191,173,225,165, 82,168, 84, 42,172, 92,185, 18, 74,165, 18, 82, 94, 10, +142, 35, 60,243,204, 51,230,130,130,130, 69,140,177, 51,193,252,145, 26, 26,110,202,212,135,234,213,228,117, 39,128,220, 3,128, + 66, 3,133,140,144,123,249, 56, 20,230,227, 0,199, 3, 18, 30,137,137, 53, 48,250,177,254,181,150,125,182,241, 41, 0,255, 43, + 75,139,227, 56,124,251,237,183,144, 72, 36, 72, 72, 72, 40,115, 7,128,111, 93,216, 55,147, 45, 15,159,135,175, 80, 40,240,192, + 3, 15,148,185, 35, 32, 49, 49, 17,192,239, 51,207, 96, 33, 34,116,236,216,177,196,204,223,255, 22,106, 29, 37,169, 84,138,255, +254,247,191,112,185, 92,112, 58,157,197, 63, 57,142, 11, 58, 2,240, 71,127,253,100, 50,153, 59, 54, 54, 86,114, 43,222,143,170, +162, 84, 42, 89,235,214,173, 75,188, 32,254,209,163,202, 56, 0, 28,199,185, 99, 99, 99,139, 47, 66,161, 80, 96,224,192,129,208, +104, 52,208,104, 52,208,106,181,168, 93,187,118,177,147, 90,209,251,161,209,104, 94,184,120,241,162,218,183,181, 80,171,213, 34, + 39, 39, 7, 68, 84, 97,193,149, 64,248, 47,121,116,235,214,205, 82,250,113,158,231, 89, 66, 66,130, 93,169, 84,178,205,155, 55, + 55, 98,140,233, 3,105, 17, 17,166, 77,155, 38, 2,224,146,147,147, 77, 21,233,253,248,227,143,141,136, 40,160, 30, 0,168,213, +234, 75, 29, 58,116,168,251,222,123,239, 73, 71,143, 30,125,211,107,196,243, 60,171, 85,171,150, 67, 34,145,208,142, 29, 59,154, + 16, 81, 65, 32, 45,198,216, 65,149, 74,181, 98,242,228,201,227,223,127,255,125,185, 90,173, 70, 98, 98, 34,206,157, 59,135,122, +245,234,129,136,160,215,235,241,240,195, 15,219,156, 78,231, 50,198, 88,176, 51,216,181,240, 24,255, 83, 0,250, 49,198,242,253, +114, 2, 90, 1,216, 0,207,110,128,114,201,203,203, 43, 81, 84,204, 23, 1,112, 58,157, 88,183,110, 93,113, 14, 64, 48,159, 13, +127,227,127,249,242,101,124,249,229,151, 56,120,240, 96, 58, 99,108, 39,128,157, 65, 94, 87, 49,140,177,239,213,106,245, 79,159, +127,254,121,255,241,227,199,203,124, 73,193,143, 63,254, 56,204,102, 51,136,168,216, 65,121,229,149, 87, 28, 55,110,220,216,203, + 24,251, 62,148,191, 97,179,217,222,246, 27,127,151,194,194, 66,248,140,191,127, 20, 51, 76,249,161,127, 31, 55,237,157, 54,153, + 76, 31, 71, 68,104,228,169,135, 15,207,120,243,173,217, 53, 59,116,236, 72, 67, 31, 28, 6,147,201,132, 19,199,143, 99,202,148, + 41, 55,110,220,184,241,129, 78,167,123, 39,216,129,240, 28,247,183,249,223, 93, 53,191,183,241,105, 19,192, 1, 68, 0,125, 7, + 96,150,247,119,239,164,129, 8,110, 81,228,212,106,229, 3, 8,224, 0, 52,110,220, 24, 0,112,225,194, 5,116,238,220, 57,168, + 72, 64,121,252,227, 31,255, 0, 0,124,244,209, 71,248,228,147, 79,130,138, 4, 4,139, 47,251,223,255,230,159, 7, 16, 42, 68, + 4,183,219, 93, 28,250,119,185, 92,120,227,141, 55, 66, 90, 2,248,163,191,126, 14,135,131, 7, 0, 34, 98,213,253,126, 84, 21, +171,213, 90, 98,253,147,136,150,249, 47, 9,248, 27,126,223,118,177,138, 40, 93,191,128,136,216, 59,239,188, 83,110, 78, 74,121, +152, 76,166,249, 19, 39, 78, 28,250,201, 39,159, 40, 34, 35, 35,177,103,207, 30,124,240,193, 7, 70,167,211,249, 64, 40,215,234, +195,187, 13,176, 30, 0, 40, 20, 10,227,196,137, 19, 27,204,152, 49, 35, 43, 62, 62,190, 56, 52,111, 50,153,248, 77,155, 54,213, +201,203,203,139, 20, 4, 97, 55, 99,236,124, 32, 61,151,203, 53,106,225,194,133, 77, 0,152,167, 77,155,214,168, 81,163, 70,142, +233,211,167,103, 54,110,220,184,248, 31,216,106,181,242,155, 55,111,174,157,147,147, 19,237,213, 43,183,214,136,197, 98,105, 98, +177, 88,254, 53, 97,194,132,217,111,191,253,182, 98,209,162, 69,178, 30, 61,122, 20, 63,110, 52, 26,165,251,247,239,111,144,159, +159,175,116,187,221, 59, 5, 65,200, 40, 79,207,102,179, 77,222,183,111, 31,122,245,234, 53,110,250,244,233,170,182,109,219,162, +105,211,166, 56,126,252, 56, 82, 83, 83, 49,115,230, 76,155,203,229, 90,102,177, 88,130,221, 2, 8, 0, 55, 0, 28, 0, 48,204, + 55,211,247, 75, 12, 92, 11, 64, 87,145, 0,207,243, 98,124,124,124,153,255, 84,179,102,205, 42,247,121,101, 29, 79, 76, 76, 92, +236, 51,254, 43, 86,172,192,210,165, 75,179,236,118,123,165,254, 79,124, 88,173,214,241, 11, 23, 46,252,229,220,185,115, 9,179, +102,205, 82, 18, 17,134, 12, 25, 82, 92, 1,213, 96, 48, 96,194,132, 9,214,221,187,119,231,154,205,230,241, 85,249, 91, 0,124, + 97,127,138,139,139, 43, 81, 33,241,110,199, 63,251,223,231, 8,148,181, 35,160,204,226, 41,102,179,105, 49, 17,125,255,194,243, + 19, 39,203,229,242, 30, 0,226, 0, 20,186, 92,174,253,249,249,249, 31, 50,198, 46,134, 50,152, 92,189,208,191,114,151, 17,152, + 80,102,178,193, 16,204, 76,214, 87,137, 47, 88,106,215,174, 29,234,101,149,203,144, 33, 67,170, 77,235,143,254,250, 5, 19, 9, + 8,245,253,184, 21,148, 54,250,190,159, 85,137, 76, 84,148,147, 82, 30,140,177, 35, 68,212,159,136,118,124,248,225,135,138,135, + 30,122,200,104,181, 90, 7,132,178, 86,237,143,197, 98,169,239,251,157,136,232,216,177, 99,237, 70,142, 28,217,189,103,207,158, +121, 15, 60,240,192,133, 61,123,246,212,201,202,202,138, 19, 69,241,128,219,237, 62, 81, 81,121,112,198,216, 58,255,251, 60,207, +183,124,234,169,167,250,116,236,216,177,232,193, 7, 31, 60,187,119,239,222,196,171, 87,175, 38,184,221,238, 95, 68, 81, 60, 22, + 76,185,113,239, 57,139,137,104,217,185,115,231,222, 28, 60,120,240,164, 78,157, 58,113, 0,164, 39, 79,158,172, 95, 80, 80, 32, +151, 72, 36, 63,219,237,246,223,130,185,102,111,169,224,255, 35,162, 47,102,205,154,245,170,219,237,238,104, 54,155,227, 52, 26, + 77, 14,199,113,169, 6,131, 97, 14, 99, 44, 96, 54,124, 0,205, 50,139,252,120,139, 2,245, 12, 70,195,229,114,113,214,141,211, +176, 86,215, 12, 28,199, 21,239,122,242,253, 94,214,141,136, 48,104,208,160, 50,157,134,232,232,232,228, 83,167, 78, 97,253,250, +245, 88,178,100, 73,150,213,106,237,201, 24,203, 12,229,186,202,184,158, 27, 68,212,124,203,150, 45,243,182,108,217,242,108,187, +118,237,156,157, 58,117, 82,115, 28,135,195,135, 15, 91,142, 31, 63, 46, 35,162,101, 22,139,229,149, 80,123,192,148,129,163,140, + 53,255, 10,203, 80,223, 77,148,181,247,223,159,128,213,211, 24, 99, 87, 1, 76,174,246, 17, 85, 19,161,204,100,131, 33,148,153, +108, 69,200,100, 50,172, 89,179, 38,168,115,125,201,130,229, 17, 29, 29, 29,244,117, 5,187, 45,230,143,252,250, 1,161, 69, 2, +238, 20, 74,165,210,221,186,117,235,114, 45,189,127, 53,186, 96,144, 74,165,238,122,245,234,149,171,169,209,104,202,213,100,140, +237, 39,162, 94,235,214,173,155, 98, 52, 26, 23,134,106,172,202,209,101, 0,142, 19,209,111,123,246,236,233,186,119,239,222,123, + 93, 46,215, 25, 81, 20,191,171,108, 77,124,151,203,117,154,136,206,254,250,235,175,157, 15, 31, 62,124,175,203,229, 74, 23, 69, +113, 35, 99, 44,248,202, 86,191,143,207, 9,224, 21, 34,154,119,248,240,225, 15,213,106,117,207,130,130,130,116,167,211,121,160, + 50, 29,232, 24, 99, 7, 1, 12, 1, 60, 91, 4,141, 70, 99,104,153,187,213,140, 92, 46,207, 83, 13,157, 19,114,156, 91,161, 80, +148,153,105,127,250,244,233,127,253,253,239,127,159, 99,177, 88,138, 4, 65,120,162,170,198,223,135,247,125,152, 76, 68,115, 14, + 30, 60,120,239,225,195,135,239, 5, 0,151,203,245, 43,128, 95,171,210,232,169,212,223,185,235,179,253, 43,162,162,100,192, 63, +125,139, 81,223, 76,182, 60, 66, 49, 26,254, 89,191,129,240,109, 61, 9,132,175, 50, 92,117, 81, 81,119,191,170,240, 71,124,253, +252,241, 69, 2,202, 59, 71,171,213,222,145, 47,102,171,213, 90,237,159, 31,167,211, 89, 45,154,140,177, 84, 0,163,170, 67,171, + 12,109, 23,128,125,222, 91,117,232,137, 0, 14,121,111,213,161,167, 3, 48,182, 58,180,252, 52,239,168,241, 7,128, 80, 58,250, + 5,131,183, 1, 84,153, 77,160,170, 73, 63, 31,192, 38,239, 45,204,109,164,229, 26, 70,165,103,255,101, 57, 3, 84,133,134,126, + 97,194,132, 9, 19, 38, 76,152, 63, 41,149,139,247,134, 9, 19, 38, 76,152, 48, 97,254,212,132, 29,128, 48, 97,194,132, 9, 19, +230, 47, 70,233, 37,128,178, 18, 2,195, 14, 64,152, 48, 97,194,132, 9,243, 23,164,162, 93, 0, 97, 7, 32, 76,152, 48, 97,194, +132,249, 11, 82, 86, 50,160, 63, 97, 7, 32, 0, 68,196, 19, 81, 34, 17, 85, 75,173, 89, 34,138, 37,162,158,222, 30,224, 97,194, +132, 9, 19, 38,204, 45,167, 60, 39,224,182,108, 3,148,201,100,185,130, 32, 4,189,127, 85,161, 80,228,217,108,182,106,221,242, + 18, 44, 68, 84, 3, 64,243,216,216,216,123, 58,118,236, 40,205,200,200, 0, 17,229, 2,248,137, 49,102,172,132, 94, 35, 0, 43, + 90,180,104,209,163, 73,147, 38, 56,119,238, 28,136,104, 63,128,113,140,177, 75,213, 61,254,191, 10, 68,196, 75,165,210, 39,165, + 82,233, 96, 81, 20,219, 17, 17, 36, 18,201,113,135,195,241,131, 32, 8, 43, 43,187,239,156,168,236, 15, 2, 99,193, 53,207, 8, + 83, 5, 94, 34, 53, 92,208,130,188, 19, 15, 6, 17, 60,140,152,207, 44, 68,196, 49,198,196,242,206,185, 73,111, 50, 53, 0, 33, + 9,228,253, 30, 19,225, 6,112, 22, 11, 89, 38, 17,201, 24, 99,206,242,206,185,245, 23,124,251, 32, 34, 25,128,186, 0,106,193, + 83,117,240, 90,101, 11,237, 16, 81, 83, 0,111, 1,232, 6,224, 32,128, 25,229, 85,119, 12,160,161, 1,240, 32, 60, 91, 81,187, +192,179,197,243, 43, 0,223, 51,198, 66,234, 34, 27,166,234, 4,114, 2,110,203, 54, 64, 34, 98, 38,147, 9, 17, 17, 17, 21,158, +107,179,217,160, 82,169,238,200, 23, 50, 17,201, 21, 10,197,232, 53,107,214, 72,239,187,239, 62, 88,173, 86,152,205,102,108,220, +184, 17,211,167, 79, 23, 76, 38,211,250, 80,156, 0, 34,106, 20, 21, 21,117,114,249,242,229, 17, 15, 62,248, 32,204,102, 51, 76, + 38, 19, 54,108,216,128,148,148, 20,179,201,100,106, 27,172, 19, 64, 68,124,114,114,242,198,182,109,219,254,125,249,242,229,101, +158, 19,138,227,228,253,128,142, 4, 96, 1,208, 49,192,105, 58,198,216,219, 1, 30,187,101, 16, 81, 43,133, 66,177, 54, 57, 57, +185,126,215,174, 93,149,117,234,212,193,141, 27, 55,112,246,236, 89, 92,186,116,201,122,225,194,133,171,118,187,253, 17,198,216, +169, 74,104,135, 29,128, 59,197,100, 74, 0,135, 36,151, 27, 50, 0,112,184,224,122,112, 35,140,187,174, 33, 6, 64, 12,128,162, +126,117,160,219,248, 32, 52,114,222, 99,176,121, 9,156, 16,113, 14, 11, 89, 78, 25,122,127, 7,135,201, 76, 68, 20, 0,152, 5, +216,134,253,128,115,187,174,162, 3,128, 14, 0,142,254,173, 30,142,125, 59, 4,205, 34,164, 80, 2, 0,113,208,131,225,125,188, +207,202,236,146,163, 82,169,134,217,108, 54, 5, 0, 40,149, 74,187,213,106,253,174,188, 75, 34,162, 24,137, 68,210,197,229,114, +109, 14,116,142, 74,165,202,181,217,108,113, 94,205, 60,171,213, 90,238,103,148,136, 58,241, 60,255,137, 32, 8,237, 42, 56, 79, + 2,160, 54,207,243,245,251,245,235, 87,123,204,152, 49,212,191,127,127,236,216,177, 3,171, 86,173, 98,187,119,239,206,118,185, + 92,153, 0,174, 87, 84,199,128,136, 98, 0,204,226, 56,238,177,251,238,187, 47,118,204,152, 49, 24, 48, 96, 0,182,111,223,142, + 85,171, 86, 97,215,174, 93, 55, 68, 81,252, 6,192, 44,198, 88, 81, 57, 58, 99, 1, 60,173, 82,169, 58,245,239,223, 95, 57,120, +240, 96,116,237,218, 21,191,252,242, 11, 54,109,218,132, 29, 59,118,216,172, 86,235, 17, 0,159, 51,198, 66,106, 4, 20,224,239, +101, 2,240, 85,171,188,194, 24,107, 80, 85,205,187,137,219,230, 0, 48,198,176,126,253,250,226, 38, 22,133,133,133,168, 95,191, +126,113, 67, 11,255,159,141, 26, 53,186, 83, 14, 64,231,255,254,247,191,237,158,123,238, 57,108,221,186, 21, 27, 55,110,196,189, +247,222,139,246,237,219,227,211, 79, 63,197,162, 69,139,142,123, 11,172, 4,171, 55,123,193,130, 5,175, 77,157, 58,181, 88,175, + 71,143, 30,232,212,169, 19,150, 44, 89,130,133, 11, 23,190,205, 24,155, 30,132, 14,223,166, 77,155,141,219,183,111, 31,176,116, +233, 82,201,128, 1, 3,110,234, 8, 38,147,201, 80,183,110,221,160, 94, 55,175,241,127, 20,192,183, 0, 58, 50,198,182, 7, 56, +111, 1, 99,236,223, 65,232, 53,209,104, 52,243, 25, 99, 29, 44, 22, 75,109, 34,130, 70,163,201, 18, 69,113,157,201,100,154,206, + 24,179, 85,164,225,167,213, 42, 34, 34, 98,207,140, 25, 51,106, 14, 31, 62, 28,145,145,145, 48, 24, 12, 72, 79, 79,135, 78,167, +195,201,147, 39,145,158,158,142,221,187,119, 23,152,205,230,190,193, 58, 1, 62,195, 31,168, 7,131,175, 2, 98,216, 17,184,133, + 76,161,218, 46, 17,173,248, 15, 88, 12, 0,236,120, 84,142, 53,218,177, 24, 58,116,104,177,145,216,184,113, 35, 70, 26, 87,162, +255, 55,158,138,174,174, 73, 84,196,115, 56,133,247,217,245,155,244,166,210, 96, 38,226,117, 90,200, 58, 1,192,246, 71, 21, 88, +163,121, 2, 67,135, 14, 69,247,238,221,113,224,192, 1,143,158,233, 11, 12,248,198, 14, 0, 96,147, 41,149, 56,188,137,247, 88, +153,197,105,136,104,148,239, 59,209, 91,161, 83, 4, 96, 0, 80,228,189, 21,122, 11, 13,129,136,212, 18,137,164,255,170, 85,171, + 44,163, 70,141,218, 17,232,178,125,223,127,126,154, 2,128,223, 0, 28, 5,144, 10,224,136,175,170, 29, 17,213,231, 56,238,151, +149, 43, 87, 94,121,252,241,199,187,150,163,217,101,232,208,161, 13,134, 12, 25, 66, 3, 7, 14, 44,110,144,229, 79,118,118, 54, +190,250,234, 43,172, 92,185,146,165,165,165,101, 50,198,202, 44,180,212,178,101,203,235, 35, 70,140, 72,108,218,180, 41,250,246, +237, 27, 80,107,245,234,213, 88,181,106, 21,210,210,210, 46, 51,198, 26, 5, 24,151,123,222,188,121,220,132, 9, 19, 16, 21, 21, +117,211,227,122,189, 30,115,231,206,197,187,239,190,235,102,140, 85, 57, 2, 93,250,181, 13,127,126, 75, 82, 81, 67,160,128,111, + 0, 17,109, 4, 16, 13,224, 17,111,189,106,223,241,120,120,170, 71, 93, 15, 84,223, 58, 16, 82,169, 20, 82,169, 20,155, 55,111, +198,226,197,139,241,237,183,223, 22, 59, 1,254,183, 59,136,234,155,111,190, 65,100,100, 36,198,142, 29,107,118,187,221, 39,150, + 44, 89,210,102,203,150, 45,218,191,255,253,239, 88,186,116,105, 51, 34, 58, 18, 76,125,114, 34,146,200,100,178,167,198,140, 25, +131,140,140, 12, 12, 28, 56,240, 34, 99,236,141,165, 75,151,206,220,177, 99, 71,147, 65,131, 6, 97,241,226,197, 79, 17,209,204, +138,188,243, 54,109,218,124,187, 99,199,142,254,181,106,213,146, 0, 37,251,129,251, 59, 78, 33,240, 8,128,111, 25, 99, 69, 21, +149, 33,174, 8, 34,106,173, 82,169,246,111,218,180, 73,211,161, 67, 7,146,201,100,112,185, 92, 56,121,242,100,189,119,222,121, +231,185,157, 59,119, 14, 34,162,214,193,148,118, 37, 34, 94,161, 80,172,157, 49, 99, 70,205,199, 31,127, 28,113,113,113,200,202, +202,194,149, 43, 87, 96, 50,153, 96,179,217,144,144,144, 0,171,213,138,126,253,250,213,220,190,125,251, 26, 34,106, 83,217,229, +128, 48,119,150,222,253,250,161,255, 51,191,247, 87, 26, 50,100, 8,134, 12, 25, 2,231,178,172, 74,233,245,237,219, 23, 3,158, +253,180,248,254,208,161, 67, 49,116,232, 80, 8, 75, 43,167,231,101, 45, 0, 6, 20,151, 66, 6,224,105,113, 46,145, 72,250,188, +253,246,219,238, 81,163, 70, 5,223,172,193,131, 26, 30,199,130,121,101,153, 87, 83,203,113,220,150, 57,115,230,216, 31,127,252, +241,138,106,122,215,156,211,217, 70,104,164, 69, 98,128, 46,120,113,113,113,104,211,166, 13, 70,141, 26, 69,105,105,105, 53, 3, + 9,217,237,246, 90,227, 26, 20, 1, 77,107, 5,236,175, 17, 31, 31,143,118,237,218, 65, 16, 4,164,165,165,213, 41,103, 92, 92, +159, 62,125,112,242,228, 73,232,116, 58,180,105,211, 6,141, 26, 53,194,133, 11, 23,176,117,235, 86,100,101,101,249,122, 91,132, +212, 44, 35, 60,211, 15,157,210,205,127,130,110, 6,228,165, 6, 60,107, 64,187,137,168, 47, 99, 44,207,107,252,247, 0, 72, 2, +176, 63,212, 1, 73,165, 82, 92,189,122, 21,203,150, 45,195,184,113,227,208,190,125,123, 24,141,198, 63,140, 3,192, 24,251,137, +136,126,219,187,119,111, 71, 0, 23, 25, 99, 25, 68,196,111,216,176,161,203, 83, 79, 61,133,182,109,219,170, 82, 83, 83, 99,225, + 89, 99,171,136, 78,125,250,244, 73,172, 85,171, 22, 22, 45, 90, 4,198,216, 82,198,216, 23, 68, 20,183,126,253,250, 5,255,252, +231, 63,145,156,156,156,152,154,154,218, 9, 21,148, 64,109,223,190,253,144, 37, 75,150, 0, 0,126,251,237, 55, 12, 27, 54,172, +132,225,247,111, 11, 26, 36, 86, 0, 29,189,198, 63, 38,148, 39,150, 70,173, 86, 79, 93,187,118,173,182, 99,199,142,200,207,207, + 7, 99, 12, 28,199,161,110,221,186, 88,186,116,169,114,232,208,161,117, 78,158, 60,249, 10, 60,107,138,229, 34,149, 74,199, 37, + 39, 39, 55, 24, 52,104, 16,180, 90, 45, 46, 94,188,136, 75,151, 46,193,100, 50,149,184, 41, 20, 10, 68, 69, 69,161, 73,147, 38, +245,206,158, 61,251, 4,128,229,129, 52, 43,154,249,139,162, 8,147,201, 84,236,100,120,207,119, 48,198,170, 37,249, 51,140, 31, + 12, 34, 47,129,243,135, 97,132, 30, 61,122,192, 41,211,226,151, 13, 27,144,148,148,132,164,164, 36,156, 62,125, 26, 91,183,110, + 69,207,156,108,104,255,221, 20, 23, 50, 46, 96, 72, 35, 56, 33,162,236, 55,143,193, 69, 28,244, 63, 60,228,209,115,200, 34,113, +104,195, 6, 52,107,214, 12,205,155, 55,199,169, 83,167,176,109,219, 54,143,222, 75, 77,113,225,194, 5, 12,105, 12,189, 55, 15, +160, 76,148, 74,165,221,151,248,235, 93, 2,184,233,111,147,231,131,211, 99,244,232,209, 92, 74, 74, 74,132,209,104, 52,106,181, +218,128,151,173, 84, 42,243,136,200,127, 9,224, 38,103,216,155,116,188,126,212,168, 81,242,148,148,148,134, 58,157, 46,189,130, +190, 30,182,150,178, 60, 13, 78,127,128,107,231, 54, 0, 93,159, 65, 98,155, 30,144, 72, 36,176,217,108,216,188,121, 51, 78,159, + 62, 93,226,252, 64, 66, 6,131,193,218, 80,184,168,197, 47,179,112,253,232,114,184, 58,141, 71,189,118,189,193, 73,248, 98,173, + 51,103,206,248,127,134,110,206,199,184,249,154,161, 84, 42, 81, 80, 80,128, 47,191,252, 18, 87,174, 92,129, 82,169, 44,209, 34, +155,136, 26,133,144, 7, 85,223,111,166, 95,223,239,248, 21,191,251, 87,130,212, 10,227,165, 60, 7,224, 33, 0,187,225,233, 85, +189,135,136, 30, 5,176, 6, 30,227,127, 22,158, 89,100, 72, 72,165, 82,204,153, 51, 7, 78,167, 19,169,169,169, 24, 62,124,120, +113,199, 42,141, 70,131,255,252,231, 63,168, 85,171, 86,101,174,163,218, 96,140, 21, 2,216,230,119,168,224,234,213,171, 0,224, +203, 97, 8, 54,108,165,136,137,241,216,214,140,140, 12,192, 19,238, 3,128,163, 62, 61,239,151, 70,133,134,102,249,242,229, 56, +112,224, 0,100, 50, 25,134, 13, 27, 6,153, 76,134,230,205,155,227,234,213,171, 37,162, 1, 33,208,177,116,104, 63,216,112,127, + 25, 12,234,212,169, 19,244,122, 61, 24, 99,197,157, 4, 37, 18, 9,120,158,199,146, 37, 75,212, 61,122,244,120, 93,169, 84,190, + 44,151,203,245, 14,135,227, 75,187,221,254, 78, 89, 61,227,165, 82,233,224, 46, 93,186, 40, 4, 65,128, 78,167, 43, 54,202,165, +111,102,179, 25,140, 49,212,174, 93, 91,125,249,242,229,129, 40,199, 1, 40, 15, 65, 16, 96, 52, 26, 97, 50,153, 96, 52, 26, 97, + 52,134,156,227, 25, 38, 20,120, 24,225,194,185,161, 27, 16,255,235,171,239, 1, 0, 18, 1, 24,141, 70,204,156, 57, 19,217,217, +217, 80, 42,149,200,145,245,135, 66,161,192,219, 27,222, 6,155,132,115,224, 81,246, 27,195,112, 14, 12, 11,135,126,143,254,191, + 78,251, 93,207,100, 50, 97,214,172, 89,200,202,202,130, 82,169, 68,174,226,126, 40, 20, 10,204,254,126, 54,216,100,188, 15,224, + 92,160, 33, 90,173,214,239,136,232, 17, 0,223, 90,173,214, 64,142, 66,167,142, 29, 59,106, 62,255,252,115,245,181,107,215,144, +153,153,137,158, 61, 3, 55,244,179, 90,173,241, 68,100, 6, 80,203,106,181, 90, 3,156,246,223, 78,157, 58,221,179,114,229,202, +250, 89, 89, 89,200,200,200, 64,239,222,189, 3,106, 2, 0,156,102,208,203,105, 0,126, 1,251, 68, 7,227,133,150,208,142, 92, +128,249,243,231,151,255,188, 82, 20, 22, 22,138, 48,223, 0, 55,245, 24,128,131, 16, 63,214,193,144,254, 45,232,254,153,248,240, +163,165,168,234, 50,113,233, 86,229, 62, 61,158,231,143, 16,209,223, 24, 99,199, 42,171, 29,142, 4, 84,141,242,186, 1,230, 19, + 81, 63,120,102,252, 45,225, 89,171,146,195, 99,252,251, 50,198,202,236, 48, 85,238, 31,227,249,226, 55, 63, 34, 34, 2,201,201, +201, 32, 34, 16, 17,172, 86,235, 29,141, 0, 40,149,202, 49,118,187,189,194,254,183, 82,169,244,111,221,225,215, 23, 0, 0, 32, + 0, 73, 68, 65, 84, 0, 86, 86,116,158, 66,161, 88, 91,234,208,158,178,194,237, 82,169,116, 45,128, 10,183, 6,250, 27,250,230, +205,155, 23, 31,171,100, 4,160, 4, 68,180,160,178,207,117, 56, 28, 90,153, 76, 6,167,211, 9,158,231,193,243,124, 9, 39,160, + 89,179,102, 40, 40, 40,224,141, 70, 99,196,181,107,215, 34,102,205,154, 53,105,255,254,253,241, 0,158, 44,173, 37,138, 98,135, + 58,117,234,192,100, 50, 33, 59, 59, 27, 70,163,177, 56,113,210,103,164,205,102, 51,124,223,161, 49, 49, 49, 16, 69, 49, 80, 2, + 99,185,216,108,182, 18,134,223,247,123,152, 91,136, 39,147,223,130, 15,110,254, 28,184,221, 1,108,109, 89,201,127,191, 63,150, + 9, 32, 51, 36,189, 0,201,127,165,208,195, 27,246, 47, 13, 17, 53, 79, 76, 76, 76,220,190,125,187,242,194,133, 11,200,204,204, +196,229,203,151,203,117, 0,188,164, 1, 40,115,169,138,136, 94,174, 93,187,246,224, 45, 91,182, 36,156, 63,127, 30,151, 47, 95, +198,229,203,151,131,112, 0, 44,120,189, 95, 52, 32, 81, 2, 78, 27,180,198,243,112, 59,131, 78,183, 41,137, 41, 23, 51,251,197, + 0,188, 28,112, 90, 17, 73, 87,145, 83,152, 93,101,227, 95, 26,198, 24, 54,109,218,132, 49, 99,198, 96,222,188,121,209,245,235, +215,223, 73, 68, 29,131,136, 4,132,103,250, 33, 82, 58,243, 63,164, 28, 0,160,216, 9,120, 12,192, 17,120,140,191, 3,158,156, +128,144,141, 63,224, 49, 88,115,231,206,197, 83, 79, 61,133,132,132, 4,204,152, 49, 3, 60,207, 23,183,196,245,253,126, 39,176, +219,237,202,178,254,217,173, 86, 43,172, 86, 43, 28, 14, 7,150, 45, 91,134,166, 77,155, 6, 21, 26,182,219,237, 53, 87,175, 94, + 13,198, 24, 86,175, 94,141,213,171, 87,251,142,195,102,179,193,110,183, 99,217,178,101,104,210,164, 73,192,181, 57,127,164, 82, + 41,142, 31, 63,142, 39,159,124,178,248, 88,124,252,239,201,196,129, 66,220,229, 65, 68,141, 1, 60,231,119,191,216, 17, 8, 54, + 26,224,114,185,164,190, 54,194,254,134,223, 63, 10, 32,145, 72, 16, 31, 31,143,248,248,120, 44, 93,186, 84,158,148,148, 52, 28, +101, 56, 0, 0,112,227,198,141, 18,198,190,244,207,192, 19,168,224,241,233,149,158,253,155, 76,225,221, 73, 97, 0,120,146,253, +110,250, 50,136,142,142,110, 16, 17, 17,209, 98,251,246,237,178,140,140, 12, 92,185,114, 5,169,169,169,108,219,182,109,206,231, +158,123,174, 12,153, 18, 28, 5,110, 94,122,136,140,140, 28, 19, 17, 17,241,202,182,109,219,162,125,134,255,240,225,195,226,246, +237,219, 11,255,239,255,254,175,124, 69,167, 13,111,244,136, 0,148, 90,192,105, 1, 32,129,197,168, 11,250, 34, 75, 96, 55, 97, +102, 79, 13, 32,215,120,180,136,131,165,168, 82, 95,243, 1, 97,140, 97,219,182,109, 72, 78, 78,198,162, 69,139, 32,145, 72, 80, + 88, 88, 24,173,213,106, 51, 0,148,155,140, 20,104,166, 31,206, 13, 40,159,138,218, 1,151, 91, 8,200,187,230,191, 22,191, 27, +127, 57,128,111, 42, 91,204, 70, 42,149,162,101,203,150, 72, 73, 73,193,247,223,127,143,243,231,207, 67, 20,197,226,208,241,157, +206, 1,248, 35, 83,137, 48,255,237,130,174, 92,185,130,201,147, 39, 99,210,164, 73,184,118,237, 90,137,124,142, 43, 87,174, 96, +252,248,241, 24, 55,110, 28, 50, 50, 50,144,152,152, 8,187,221,174, 46, 75,136,227,184,163,103,206,156, 65, 81, 81,209, 77, 78, +128,201,100,186,201,248, 23, 21, 21,129,227,184, 35,193, 14, 84, 20, 69,232,245,122,232,116,186,128,183, 48, 97, 0, 20,249, 39, +252, 77,155, 54,173,233,180,105,211,134,198,198,198,118, 29, 59,118, 44, 95, 80, 80,128,195,135, 15, 99,206,156, 57,246, 5, 11, + 22, 8, 39, 78,156,184, 28,132,230, 17,224,247, 92,134,215, 95,127,253,133,105,211,166,101,198,197,197,173, 24, 55,110,156,170, +176,176, 16,191,254,250, 43,222,121,231,157,220,247,222,123,207,112,242,228,201,229, 21, 42, 10, 22,204,220, 93, 0, 56, 45,160, +201, 71, 48,243,135,115,176, 85,214, 1,112, 90,240,198,174, 66,192,105, 1, 55,229, 8,222,216,120, 30,230,194,192,193,151,114, + 56,187,114,229, 74,216,108, 37, 35, 17,140, 49,236,222,189,187,216,248,191,240,194, 11, 0,138,151, 65,171, 66,125,198,152, 47, + 82, 81,191,162,147,239, 54, 42, 42, 5, 92,222, 46, 0,255,132,191,211,240,108, 27, 91, 11,207,114,192,110, 34,234,231,237,247, + 28, 52, 62,163, 48,118,236, 88,220,127,255,253,104,212,168,209, 77, 9,128,190,237, 88, 97, 74, 34,149, 74,209,163, 71, 15,228, +228,228, 20,103,234,218,237,246,226,232, 73,101, 96,140,101, 0,248,183,111,230, 95,201, 28, 0, 12, 24, 48, 0,251,246,237,131, + 40,138,232,218,181, 43,242,243,127,255,183,168, 93,187,118, 89,143,149, 57, 96, 65, 16, 54,101,102,102,222,159,150,150,166,140, +143,143, 47,177,238,239,251, 66,145, 72, 36,136,137,137, 65,126,126, 62,174, 95,191,110,177,219,237, 1,247, 95,251,227,116, 58, +203, 12,249,251,255, 30,142, 0,220, 54, 76,107,214,172,209, 60,244,208, 67,168,169, 75, 67,220,249,175,240,132, 61, 15, 78,165, + 29,123,209, 1,151,220, 13,112,244,232, 81, 0, 8,246, 13, 57,255,205, 55,223, 52, 29, 54,108, 24,106,234, 78, 34, 46,253,107, + 60,110,207,131, 67,229,192,207,104,143,203,238,134, 72, 77, 77, 5,128, 96,139,217, 20,239,115,127,253,245,215, 91,235,245,250, +164,244,244,116, 62, 58, 58, 26,159,126,250, 41,151,158,158, 46,236,219,183, 15, 78,167, 51, 11, 64, 26, 99,204, 17,132,102,241, +238,161,233,211,167,191,149,159,159, 63,249,210,165, 75,106,175,166,236,204,153, 51,230,125,251,246, 49,151,203,245, 45,128,215, +189,185, 72,229,227,118,227,205,253,110,188,209,219, 92,124,223,102, 40, 8,242, 18, 75,193, 68,188,177,223,129,153,189,189,249, +125,110, 1,150,194,236,202, 40, 13,249,232,163,143,222, 90,189,122,245,163, 99,198,140,225, 70,140, 24,129,217,179,103, 3, 0, +198,140, 25, 83,108,252, 87,173, 90,181,110,213,170, 85, 35,128,224,182,222, 18,209, 80,120,118, 79, 0,128,133, 49,182,177, 50, +131,187,155, 40, 43,235,191, 52,229, 89,219,181,240, 24,255, 83,240,172,249,159, 6,208, 23,158, 28,128, 86,240,108, 5, 12, 9, +127, 67,223,176, 97,195,176,241, 15, 1,255,245,126,223, 90,117, 85,140,191, 63,149, 53,252,222,231, 18, 17, 89, 0,224,244,233, +211,112,185, 92, 22,198, 24,249,110,129, 30, 43, 75, 75, 16,132, 21, 23, 46, 92,184,146,158,158,142,140,140,140, 98,163,236, 51, +254,190, 90, 7,114,185, 28, 6,131, 1, 23, 47, 94,188,234,118,187,191,168,104,124,140, 49, 82, 40, 20,136,141,141, 45,158,233, + 23, 21, 21,149,152,249,191,244,210, 75,120,243,205, 55,125,231,135,119, 0,220, 90,246,190,247,222,123, 87, 71,140, 24,129,227, +251,182,194,221,102, 36,146, 22,156,135,179,205, 72, 24,175,157,195,103,159,125,134,173, 91,183, 94, 5,176, 55, 72,189, 65,239, +191,255,254,154,225,195,135,179, 19,251,183, 67,108, 59, 18, 73,243,207,195,213,250, 17, 24,178,210,241,233,167,159,178,109,219, +182,173, 1, 48, 40, 24, 49,198,152, 1, 0,166, 79,159, 94, 63, 59, 59, 59,169,113,227,198,252,200,145, 35, 17, 23, 23, 7,169, + 84,138,125,251,246,185,157, 78,231, 46,198, 88,106,144,198, 31,222,239, 79,188,242,202, 43,163,115,115,115, 39, 55,109,218, 84, + 61,124,248,112,212,170, 85, 11, 60,207,211,129, 3, 7, 76, 46,151,171, 59, 99,108, 98, 80,198, 31,200,188,127, 3,216,177, 39, +224,201, 5,232,173, 68,239, 58, 18,216,117, 37,195,246,217,217,217, 88,185,114, 37, 3,144, 89,142,214,198,251,191, 5, 60, 90, + 86,204,236,165, 66,239,122, 18, 88, 10, 74, 70, 0,114,115,115,177,106,213, 42, 0, 8,104,124, 25, 99, 25,140,177,209, 58,157, +174,197,162, 69,139, 86,245,234,213,171,216,209,254,232,163,143,124,198,255,115, 0,143,150,247, 93, 80, 6,106,198, 88, 26, 99, + 44, 13,191, 59, 2,128, 39, 55,192,247, 61, 24,206, 13, 8,145,242,114, 0,110, 0, 56, 0, 96,152,111,166,239,221, 10,216, 15, + 30,231, 32,104, 87,211,151,233, 31, 44, 18, 73, 72, 91, 68,111, 57,127,132,241,248, 18,253,124,142,128,219,237,174, 22,227,239, +163, 42, 78, 64, 78, 78,206,196,174, 93,187,126,228,116, 58,161,211,233, 38, 6,251, 88, 25, 99,112, 17,209, 35,187,119,239,222, +211,175, 95,191,154, 81, 81, 81, 37,146,144,180, 90, 45, 28, 14, 7, 46, 92,184,128,221,187,119, 23,216,237,246,145,161,214, 0, +240, 95, 94, 8,103,255,223, 25,152,167, 20,236,129,231,218, 81,230,153,189, 63, 36, 71, 70, 70,106, 6,246, 7,178,174, 93,131, + 61,251,156,105,116, 67, 28, 95,114,162,140,194, 63,129,245, 46, 2,120,244,185,118,180,234,212,222,141,239,105, 53,154,166, 3, +251, 63,143,172,235, 89,176,103,159, 61,255,120, 35, 76, 93,114,162,236,194, 63,129,120,230,153,103, 34, 13, 6, 67,231,214,173, + 91,243, 74,165, 18, 27, 55,110,196,182,109,219, 0,192,229,118,187, 83,125,197,128, 66, 97,194,132, 9, 45,245,122,253,178,182, +109,219,170, 85, 42, 21, 54,109,218,132,173, 91,183, 2,128,197,237,118,255,147, 49,246, 91,176, 90,222, 45,202,121,219, 51,209, +246,137, 36,103,189,183,250, 41,209, 32, 81,134,227, 70,207,215,178, 78,167,195,238,221,187,145,150,150,118, 5,158, 40,133,185, + 28,173,113, 68,180,124,231, 21, 44,127,162,185,163,222,155,189, 21,168, 31,235,198,119,133,215, 0, 89, 77,232,245,122,236,217, +179, 7,105,105,105, 87, 24, 99,227, 24, 99, 21, 58,102,140,177,116, 0, 99,137,104, 12,224,249,236, 26,141, 70,159, 3,241, 15, +198, 88,232, 73, 75,101,255,157, 6,213,161,243, 87,165,244, 18, 64,233,136,192,237,171, 4,184, 41, 5,175, 29,148,128,136,192, +113, 92,241,173,172,251, 41, 41, 41,183,189,162, 19, 17, 77, 8,148, 4,232,112, 56,138,147, 1,155, 54,109, 10,198,216,199, 65, +232,177,178, 18,243,252,147, 0,109, 54, 27,154, 52,105, 82,225,181, 18, 17, 43, 40, 40, 40,177,247,191,172,104, 9,199,113,193, +134,211,130,173,240, 87,217,173,129, 85,194, 87, 10,248,158,123,238,169, 87,167, 78, 29,149,111, 63,180, 78,167, 67, 86, 86, 86, +184, 20,240, 95,133,137, 20, 1, 57,234,231, 90,208,224,146, 17,202, 70, 90,216,226,213,200,132, 3, 87,240, 81, 96,131, 21,144, +151,168, 33, 68,140,206,179,224,137, 12, 61, 18,238,137, 70,118,172, 10, 95, 58, 4,124, 45, 95,196, 50,130,149, 25, 61,122,116, +205,130,130,130,190, 6,131,129, 23, 69,209, 23,141,114,187,221,110, 6, 32,221, 59, 11, 13,137,145, 35, 71,118,213,233,116, 59, + 76, 38,147,202,229,114,209,165, 75,151,152,209,104,180,185,221,110, 2,176, 0,192,204, 96, 10,140,149, 5, 17,197, 40,120,180, +159,249, 96, 82,108,187,126,195,241,230, 23,187,145,154,154,122,195,229,114, 29, 11,213, 81, 33,162, 49, 74, 9, 22, 79,236, 32, +141,172,115, 79, 75,172,185,172, 66,106,106,170, 94, 16,132,137,140,177,213,149, 24, 27,243,119,176,181, 90,109,165, 62,107,225, + 37,128, 91,195,109,113, 0,100, 50,153, 91, 16,132,160,227,251, 82,169, 84,116, 58,157,183,117,218, 29,194, 54, 64,155,211,233, + 92, 85,209,121,254,245,191,203, 67, 46,151,231,217,237,246,114,107,131, 43,149,202, 92,187,221, 94,161, 86, 48,117,198, 1,128, +136, 94,131,167,202, 99, 69,220,145, 94, 0,192, 45,109, 6,100, 47,235,120, 56,236,127, 7,120,131, 56,228,162, 38,148,248, 61, +187,149,131, 3, 87,161,195,154,242,171, 99,150,201, 51, 36,133, 18, 93, 33, 65,113,102,153,203,133, 34, 62, 6,199, 48,147,149, +249,190,151, 69,199,142, 29,251, 26, 12,134, 26,122,189,222,166,215,235,205, 46,151,203, 8, 79, 62, 66, 14, 99,101, 52, 37, 10, + 78,115,187,193, 96,184, 87,167,211,101, 27, 12,134, 75, 46,151,235, 12,128, 12, 0, 91, 24, 99,213, 18,186, 38,162,186,113,113, +113,109,243,242,242,142, 51, 22,124, 4, 37,128,214,187, 0, 94, 4, 48,159, 5, 81,174,188, 2,173, 98, 35, 19,118,180,111, 63, +190, 40, 64, 89,249, 0,183,197, 1, 8, 19, 38, 76,152,187, 25,242, 47, 90, 31, 38,204,109,194, 63, 17,176,172,164,192,112,214, + 93,152, 48, 97,194,220, 98,194,198, 63,204, 31,145,176, 3, 16, 38, 76,152, 48, 97,194,220,133, 84,185, 29, 99,152, 48, 97,194, +132, 9, 19,230,143,131,127,246,127,121,197,128,194, 57, 0, 97,194,132, 9, 19, 38,204, 93, 72, 56, 2, 16, 38, 76,152, 48, 97, +194,252, 5,169,168, 14, 64,216, 1, 8, 19, 38, 76,152, 48, 97,254, 98, 4, 83, 10, 56,236, 0,220,165, 16,209, 89,198, 88,243, +202, 62,238,119, 94, 52, 0, 37, 99,172,194,194,225,222,254, 18,106,111, 15,130, 48,183, 0, 37, 79, 6,187, 27, 1, 59,172, 72, + 57,184,228, 60, 9,114,158, 51,200,164,188, 69, 34,145,200, 5, 55,203,205, 51,216,238, 45,171, 58, 27, 17, 21, 0,136, 4, 96, + 4, 96,129,231, 59,195, 9, 79,105, 89, 51, 60,173,172,157,240,180,187, 53,192,211,144,165, 8,192,228,202,214,106,184,147,168, +120, 26,102,115, 67, 1, 0, 28,129, 69,202, 32, 68, 43,224,138,150,195,169,149,195,174,149,193,170,149,195, 90, 67, 6, 75, 93, + 45,140, 83, 90,195,132,255, 4, 46, 7,172,228, 41,215,238, 70, 28, 0,112,128, 24, 41,135, 49, 90, 1, 99,180, 28, 58,141, 12, +121, 90, 25,178, 35,229,184, 26, 45,199,229,122, 90,156,159,210, 30,233, 0,138,104, 97,104,107,179, 68,196,171,213,234,133, 46, +151,107,188, 82,169,204,210,235,245,163, 24, 99,199, 66,189,254,152,152,152,183, 21, 10,197, 84,155,205,182, 76,167,211,189, 24, +234,243,195,252,177,248, 75, 70, 0, 56,142,115, 49,198, 42, 44, 20, 68, 68,110, 81, 20,203,189, 70, 34, 58, 11, 79,207, 3, 31, + 27, 24, 99,195, 42, 59,182, 91,160,151, 10,207,151,233,126, 34,234, 1, 96, 33, 99,172, 83,101,245,252, 72,170,226,227, 62, 36, + 0,230, 18,209, 39,140,177,253,129, 78, 34,162, 14, 0, 70, 3,120, 55, 72,221, 50,241, 47,176, 20,108,225,163,187, 9,187, 27, + 90,177,240, 50,160, 77, 0, 76,121,128,249,134,231,167,233, 6,224, 48, 57,109, 86,139,219,229,180,219, 35,228,146, 34, 18, 93, +133,191,165,103, 40, 30,123,127,187, 50,207, 96,227,224,215,173,206,143,200,156,156,156,235,113,113,113, 60, 17, 89,114,115,115, + 21, 14,135,195, 81,183,110, 93, 19,199,113,198, 99,199,142,169,172, 86,171,189,115,231,206, 69, 50,153,204,240,218,107,175, 21, +206,153, 51, 39, 17, 21,180,119,253,163, 98,115, 67,193,126, 94, 12, 70, 4,178, 20, 16, 51,231,203, 96,211, 73,140, 70,147,184, +245,116,129, 50,202, 85, 40,220, 31,149,237,128,211,108,131, 4, 78,104, 32, 16,145,138,227,184,251, 68, 81,220,202, 24, 19,252, +245,236,110,196,249,233,113,204,156, 31,197,172, 58,185,201,104,116,111, 61, 93,192, 71,185,138,204,247, 71, 95, 47,100, 78, 75, + 30, 60,142,147,137,251, 0,117,184, 69,146, 61,162, 40, 38,123,203, 38, 87, 8,207,243,255,108,209,162,197,248,117,235,214,169, +182,108,217,210,244,229,151, 95, 94, 3,160, 73,168,215,159,156,156,252,210,146, 37, 75,164,201,201,201,227,136,104,106, 89, 78, + 28, 17, 37,200,100,178, 55,190,251,238,187,231, 7, 14, 28, 24, 84, 47,132,170, 32,147,201,114, 5, 65,168,176, 16,154,143, 96, +138,171,221, 45, 84, 42, 2,224,171,220,228,171,218, 84,209,253,219, 13, 99, 76,242,202, 43,175,148, 40, 33,236,235, 73,239,127, + 75, 73, 73,169,208, 73,240,205,114,189,198,117, 45,128,247,170, 56,182,106,213, 3, 48, 25,192, 90, 34,154, 7, 32, 5,192, 35, + 85, 17,243,119, 80, 2,149,197,245, 59,151, 1, 56, 87, 94, 36,128, 49, 86, 64, 68, 75, 1,124, 75, 68, 80, 40, 20,241, 0, 96, +183,219,139,123,115,251,189, 22, 3, 25, 99, 65, 53, 25,247,214, 77, 33,255,159,126,127,211,119, 78,208, 95, 10,165,180,137,227, +184, 20,137, 68,242, 79, 65, 16,154,249,190,228, 36, 18,201, 20,137, 68,242,188, 32, 8, 45, 24, 99,182,114,158,175,148, 72, 36, +103, 24, 99,139,221,110,247,251,222, 99,188, 68, 34, 73,103,140,125, 34,138,226,188, 59,186,239, 91,155, 8,188, 44, 47,113,200, + 41,139,180,111,186,170,112,253,120,201,237,168, 25,169, 53,247,110, 83, 95, 82,167,118,162,188, 77,139,230, 71, 34, 34, 14, 68, +149,211,218, 67, 31, 31, 31,239,140,137,137,153,171,211,233, 24,128,255, 49,198,220, 68,244,180,247,241,229,222,251, 15,193,227, + 64,108, 2,240, 48,128,208, 43,249,253, 81, 96, 34, 6, 60,241, 34,186, 39, 2, 51,187,192, 5,192,156,178, 11,156,213, 5, 65, +193, 67, 84, 54,131,179, 87, 2,172,136,130,133,102, 65, 66, 68,125,222,122,235, 45, 54,109,218, 52, 33,144, 94,255,199, 95, 68, +143,218,192,204, 46, 48, 19,112, 41,101, 23,228, 54, 23, 12,114, 9, 28,138, 36, 20,246,170,131, 43, 0, 50,185, 15,160, 32,162, + 45,111,190,249, 38,123,237,181,215,130,110, 79,169,213,106, 71, 61,247,220,115,170,248,248,120, 60,244,208, 67,248,215,191,254, + 85,143,136, 34,202,235, 1, 80, 26, 34,138,141,139,139, 19,101, 50, 25,122,245,234, 37,221,187,119,111, 65,100,100,228, 10,131, +193,240,162,223, 57, 17, 0, 54, 79,152, 48, 65, 61,112,224, 64, 37, 60,109,226,111, 41,130, 32,196,153,205,102, 40,149,129, 11, +181,250,250,162, 88, 44, 22,104, 52,154, 74,125, 47,252, 21,169, 82, 4,128,136, 58, 48,198,142, 6,123,255,118,242,206, 59,239, + 84,155,150,159,129,122,164,188, 89,236,157,208,243,206,252, 31, 1,176, 15, 64,207,106,208,243, 57, 40, 44,123,127,209, 14,183, + 93,116,186,172,162,195,101,115, 59, 92, 86,183,211,101,118, 59,236, 58,193,218,233,245, 38,147,130,117,240, 24, 99,191,248,198, +232,235,220, 71, 68,245,253,140,182, 19,192,125,140,177,227, 33,140,147, 0,188,204, 24,123, 26,192, 80,198, 88,119, 0,217, 68, + 20, 76,239,245,128, 16, 81,140, 84, 42, 93, 23, 25, 25,121,111, 97, 97,161, 2, 0, 79, 68, 26,185, 92,254,117,116,116,116, 15, +157, 78, 39, 7, 32, 7, 16,208, 1, 0, 32,103,140,213,141,140,140,124, 75, 46,151,223,239,116, 58, 31, 3, 96, 19, 69,177, 65, +141, 26, 53,102,152, 76,166, 1, 68, 52,130, 49, 86, 84,142,198,173,195,236,105,199,252,233,111, 0,207, 1, 79,118,138, 49, 20, +184, 34,197,245,233, 70, 89,164, 70,109, 21,121,133,245, 72,150,141,143,174,163,182, 66, 93, 83, 47,149,202, 0, 32,144,195, 98, + 6,160,119,187,111,178,231,110,148, 52,242,130,223,253, 80,140, 78, 3, 0,115, 1,220, 15,192, 10,207,255,249, 12,111,131,159, +144, 33,162, 6,188, 84, 58,223,237,118, 15,224,136,179, 17, 71,251, 92,130,240,106, 40,122,204,148,135,218, 17, 64,140, 18, 34, + 0,139, 91,132, 37, 66, 10, 94,201,195, 42,229, 96,138,150,193, 8, 7,204, 52, 11,140,136,122,142, 30, 61,154,155, 54,109,154, +166, 34,189,104,185,103,233,196, 45,226,138, 90, 10,181,146, 71, 22,207,225, 66,180, 2,231,224, 49,254,110, 0,223,142, 26, 53, + 74,246,218,107,175,133, 52,123, 47, 42, 42,250, 98,249,242,229,237,134, 13, 27,166,145,201,100,120,228,145, 71,220,235,214,173, + 43,208,106,181,215, 76, 38,211,163, 21, 45, 7, 16, 81,108, 76, 76,204,175,123,246,236,145,170,213,106,188,242,202, 43,170,209, +163, 71,227,233,167,159,158, 0, 79, 73, 96, 16,145, 4,192, 55, 15, 60,240, 64,196,226,197,139, 67,142, 46, 84, 5,181, 90,141, +253,251,247, 23,119, 68,229,121, 30, 29, 59,118,196,153, 51,103,138,239,251,126,134,241, 80,209,236, 31,248,147, 46, 1, 0,192, +233,180,180, 47, 73, 34, 97,162,203,101, 19, 1,139, 75, 16,108,240,124,129,216,192,113, 86,165, 82,233,110,222,188,249,178,138, +116,254,200,198,223,135,215, 9, 64,117,233,249,112,219, 69,231,249,149, 57,169,213,161,229, 27, 35,126,159, 17,200,253,102,234, +178, 80,199,238,157,249, 79, 0,240,153,255,113,165, 82,153,231,155,249, 43,149,202,160,162, 9,126,154, 93,165, 82,233,198,185, +115,231, 70,245,233,211,135,239,220,185,179,155, 49,118,175, 84, 42, 93, 51,123,246,236,152,191,253,237,111,124,231,206,157, 29, +101, 53,113, 42,141, 92, 46,119,109,217,178, 69,245,175,127,253,171,247,201,147, 39,207, 9,130, 48, 82, 42,149,178,109,219,182, +169, 38, 77,154,212,237,240,225,195,233, 68, 52,148, 49,246, 75, 40, 99,172, 22, 44,249, 16, 25,240,197, 89, 64, 37,151,186,135, +116,138,118,169,162, 99,178,227,107,144,198, 73, 50,153,200, 43, 21,109,146, 26, 31,237,218,169,195,249, 13, 7,211,147,204,118, +161,188, 62, 8,252,229,203,151, 35,254,247,191,255,173, 28, 49, 98,132,141,136,158,246, 58,118, 43,188, 51,255,161,222,251, 91, +188,221, 28,123, 0,168, 7, 79,145,177,114, 95, 72, 34,106, 2, 79,203,223,197, 0,166, 2,144, 1,120, 2,192, 94, 34,234,206, + 24,203, 12,229,178,137,168,137, 68, 34, 57,144,220,171,247,254,225,207, 78,124,219,106,177,209,250,165, 75,186,156, 77, 61,120, +128,136,238, 13, 70, 47, 82, 6, 1,166, 92,233,103,253,225, 38, 14,102, 0,102,142,131,229, 95,237, 96, 59, 93, 4, 71,125, 13, +116,173, 52, 48,226, 35,230,198,199,116,111,167, 78,157,212, 43, 87,174,140, 48,155,205,136,136,136,184, 73, 79, 43,131, 17,166, + 92,237,103, 3, 96,231, 8,151, 0,100, 74, 56,100,254,171, 29,178, 79, 23, 34,191,190, 6, 39, 91,213, 68, 58, 45,100, 86,124, + 64,159,117,238,220,185,225,170, 85,171, 26, 5,210, 11,112,221,245, 84, 42,213, 91,243,230,205,139, 96,140,193,106,181, 98,222, +188,121,138,151, 95,126, 25, 91,182,108,105, 50,119,238,220,175, 0, 52, 43,235,185, 90,173,246,109,167,211,249, 60,207,243,138, +159,126,250, 73, 18, 31, 31,207,165,164,164, 56,151, 47, 95, 46, 50,198, 72,169, 84,126,224,119,250,226, 86,173, 90,181,248,225, +135, 31, 26, 88, 44, 22, 92,184,112, 1,237,218,181, 11,106,140,213,129, 68, 34, 41,190, 61,251,236,179, 0,128,167,158,122, 10, + 95,125,245, 21,120,158, 47,118, 2,194,252, 78, 69, 17,128, 63,115, 37, 64,118,224,224,193,125, 39, 79,157, 58,146,113,233,210, +217,252,194,194, 76,147,197,114,195,205,152, 73, 46,151,187, 21,138,160,123,187, 76, 5, 16, 15, 96, 31, 17, 49,111,136,188, 42, + 84,183,158,143,115,213,164, 83,140,219, 33,150, 29,178,172, 60, 87,136, 72, 78, 68,190,248,179, 3,149, 12, 17,122, 35, 0, 55, +205,160,173, 86,107,188, 47, 50, 17,236,250, 63, 17,145, 84, 42, 77,169, 85,171,214,174,195,135, 15,215, 28, 63,126, 60,159,159, +159, 15, 34, 66,108,108,236,182,212,212,212, 90, 19, 38, 76,224, 13, 6, 67,208, 45,150,121,158, 71,167, 78,157, 48,117,234, 84, +249,179,207, 62, 27, 43,147,201,182, 73,165, 82,180,107,215, 14, 83,166, 76,145, 79,154, 52,169,166, 66,161,216, 37,149, 74, 83, +168, 58,251, 54, 7,131, 57, 31, 28,199,137, 83,186,107, 77, 79,117,137, 53,187,149, 49,214,168,154, 9, 69, 19, 7,181, 79, 79, +110, 90,191,160,109, 82,163,188, 65,125,123,164,147, 50, 82,167,183,187,173,140, 56, 43, 2, 71, 0, 28, 86,171,213,106,177, 88, +124,143,187,224,153,237,251,112,122,111,254,247, 77,229,232,249,243, 22,128, 37,140,177,119, 24, 99,217,140,177, 76,198,216,108, +120, 28,130,144,155, 80,241, 82,233,220,182, 61,123, 29,124,101,201,255,182,197, 55, 74,210,215,168,215, 76,247,232,180,121, 91, + 26,182,233,188,159,227,249,160,114, 79, 34,229,112,193, 82, 32, 18, 96,129, 8, 11, 99,176,114,128,165, 65, 36,140,131, 26,161, +176, 85, 20, 76,248,136,185,136,168,101,221,186,117,227,127,250,233,167,136, 27, 55,110,224,212,169,178, 27, 83, 70,201, 97, 98, +150,124,129, 35,100,194,147, 56,121, 5, 64,102, 3, 45,210, 7, 53,196,145, 86, 53,113,158, 22, 50, 51, 17, 77,175, 91,183,110, +255,159,126,250,169, 81,121,122,165, 33,162,186, 42,149,234,215,157, 59,119,198,182,107,215,142,114,115,115,177,125,251,118,152, +205,102, 40, 20, 10,116,233,210, 5,118,187,189, 78,160,231, 11,130, 48,245,220,185,115,154, 67,135, 14, 73, 35, 34, 34,184, 41, + 83,166, 56,191,248,226,139, 44, 65, 16,234, 9,130,160, 48, 26,141,175,122,255,206,191,227,226,226, 30, 60,120,240, 96,131,162, +162, 34,156, 58,117, 10, 39, 78,156, 8,106,140,213,133, 84, 42,197, 11, 47,188, 0,169, 84,138,143, 63,254, 24,105,105,105, 88, +177, 98, 5,164, 82, 41, 70,141, 26, 21,142, 0,148,194,127, 23, 64,160,104, 64,153,175,150,119,205,181, 67,176,247,239, 4,162, + 40, 90, 84, 42, 21, 20, 10, 69,241, 77, 46,151,151,184, 5, 67, 85, 18,244,110,135,158,159,110,133, 25,249,161,226,182,139,206, +138,207, 10, 30,198, 88, 3, 34,202,132, 39, 19, 28,126,142, 64,200,221,206,188, 17,128,126,213, 49, 46,141, 70,179, 38, 38, 38, +102,224,177, 99,199,148, 14,135, 3,103,207,158,133, 86,171,197,191,255,253,111,164,164,164,200, 93, 46, 23, 50, 50, 50, 16, 25, + 25, 25,180, 3,224, 59, 47, 49, 49, 17,143, 60,242, 8,117,235,214, 77,158,150,150,230,246, 29, 27, 62,124, 56,186,117,235,166, +156, 52,105,210,235, 5, 5, 5, 29, 81,197,220,141,144,176, 22, 48,187,188,134,173,119,139,104, 71,100, 76,220, 53,168,107, 24, +210,245,146,104,171, 68,109, 27,255, 80,167,159,160,174, 97, 88,191,239,116,115,163, 67,180,141,127,236,161,141,107,118, 29, 86, +253,150,126, 41,144, 90, 70,203,150, 45,175,118,233,210,101,236,147, 79, 62,233,194,239, 51,255, 7,137,200, 13, 96, 51, 99, 76, + 36,162,238, 68,228, 2,144, 10,160, 16, 21,204,254,189,244, 4,240, 82, 25,199, 87, 2, 8,217,186, 48,145,245, 28,250,143,103, + 22, 22, 21,153, 97, 48, 88, 97, 48,219, 97, 48, 88,209,188,247,131,191, 94, 58,241,107, 74, 48, 26, 49, 74, 56, 97, 41,100, 38, + 1,214,115, 58, 56,239,137,132, 53, 90, 14, 11, 56, 88, 32,194,138, 69, 76, 32,162, 6, 90,173,182,217,161, 67,135,228,217,217, +217,184,124,249, 50, 46, 95,190,140, 46, 93,186,220,164, 23,173,128, 1,150, 66,183,201,137,107,103,138,160,107, 26,133,172,104, +133,199, 9, 0,112,133, 22, 50, 35, 17, 61,174,209,104, 94, 60,116,232, 80,205,138,244,136,136,231, 56,110, 66, 68, 68,196, 19, + 70,163,113,149, 74,165,154,177, 99,199,142, 90,109,218,180,161,139, 23, 47,194,225,112,224,216,177, 99,226,138, 21, 43,108,189, +123,247, 86,127,253,245,215, 22,158,231, 63, 15,116,189, 18,137,228,251, 22, 45, 90, 60,248,208, 67, 15,161, 79,159, 62,242, 47, +190,248,194,237,114,185,186, 48,198,242,253,254,230,136,136,136,136,148,163, 71,143,214,200,207,207,199,229,203,151,145,153,153, + 9,147, 41,232, 20,133,106,161, 91,183,110, 16, 4,161,120,166,239,191, 28,176,103,207, 30,212,172, 89, 19, 22, 75,165,154, 53, +222,181, 4,116,151, 74,175,237, 87,116,255,118,227, 18, 4,155, 84, 42, 45, 97,240, 85, 42, 21,252,157,130, 96,160,250,195, 94, +208, 38,182,126,213,148,115,102,182,152,185,238,163,170,142,171,186,245,146,123,198,190, 80,187,145,250,213,236, 76,203,236, 99, +123,243,171,172,231,143,203, 86,189, 14,128,151,250,126,161,255,170, 38,138, 6,220, 90, 24,138,174, 40,138,215,204,102, 51, 14, + 28, 56,128,164,164, 36,196,197,197,129,227, 56,232,245,122,225,224,193,131,146,118,237,218, 33, 62, 62, 30, 28,199,133,228, 0, + 16, 17, 18, 19, 19, 65, 68,200,201,201,129,201,100, 18,136, 72,226, 59,150,151,151,231,251,146,188, 22,236, 88,171, 10, 1, 34, + 4,135,195, 46,175, 97, 45, 20, 53,118,185, 60,218,168, 80,215,212, 89, 76,130,204, 10,149, 13, 17, 53,245, 36,215, 24, 12,118, +209,170,183, 58,109,144, 71,232,165, 50,185, 13,129,103,236, 38, 0,122, 81, 20, 93, 40, 57,211,247, 95,243,135,247, 49,183, 87, +199, 20,100, 18,164, 12,101, 59, 10, 92,169,191, 21, 20, 12, 76,106, 54, 9,172,160,192, 4,131,217, 10,131,193, 1,179,201, 10, +157,206, 74, 40, 25,181, 8,136,150,135, 83, 52, 23, 58,190,191, 4,183,148,131,211,226,132,179,111,109, 88, 96,131, 5,255,101, +206, 90,181,106, 37,202,100,178, 14,219,183,111,151,250,140,225,137, 19, 39,240,227,143, 63,154, 38, 76,152, 32, 97,172,100, 27, + 99,173, 20,133,204, 92, 88,240,125, 6,236, 60,135, 66,171,128,162,190,117, 61,209, 0, 90,200,244, 53,107,214, 28, 40,147,201, +254,179, 99,199, 14, 77, 41,189,243, 19, 38, 76, 80, 49,198,172,254,122,106,181,122,193,179,207, 62,251,236,132, 9, 19,228,235, +214,173,107, 39, 8,130,180, 89,179,102,220,153, 51,103,224,118,187,241,249,231,159,187, 86,174, 92,121,195,229,114, 45, 57,118, +236, 88, 7,147,201,180, 30,192, 87,129,174,215,108, 54, 63, 74, 68,201,223,125,247,221,193,132,132, 4, 48,198, 56,127,227, 95, +171, 86,173,254,114,185,252,227, 29, 59,118,104, 11, 11, 11, 41, 51, 51, 19,105,105,105,248,237,183,223,142,180,104,209,194, 26, + 72,247, 86,112,232,208, 33, 60,245,212, 83,197, 70,223, 63,236,223,169, 83, 39,236,218,181, 11, 18,201,109,237, 34,255,167,231, +182,196, 75,110,197,174, 2,167,203,101, 45,109,240, 21, 10, 5,252,157,130, 96,136,170,223,105, 65,179, 1,211,164,233, 91,103, +207, 3, 80,101, 3, 91,221,122, 13,146, 52, 11, 6, 62, 94, 79,250,227,170, 43,213,162,231,143,203,234,190, 21, 14, 0,224,151, + 7, 80,153, 39,171, 84,170, 92, 0, 32,162,115,129,182,250,249,118, 7, 4,163,103, 54,155,167, 16,209,129, 71, 31,125,116,249, +107,175,189,166,156, 52,105,146, 68, 34,145,224,127,255,251,159,116,197,138, 21,230,105,211,166, 41, 94,123,237, 53, 62,148, 72, +189,207, 1,136,143,143,199,252,249,243, 93,239,190,251,174,157,231,121,229,226,197,139, 17, 31, 31,143,133, 11, 23,186,103,206, +156,105,179,217,108, 79, 50,198,214, 7, 45, 92, 69, 20, 60, 4,187,205, 42,238,185, 46,209,239,185, 84, 36,225,229,182,198,237, +146,196,200,177,131,251,120,102,254, 63,255,150,164,183,185, 28,195, 6,246,223, 82,163, 86, 66,193,132, 87,231,245,251,237,236, + 69, 0,248, 49,128,100,194,230,205,155,185,119,222,121,103,250,243,207, 63,239, 40, 99,230,223,197,251,249, 61,226,141, 12, 52, + 5, 32, 37,162,252, 32,156,128, 29, 0,198, 2, 40,157,209,251, 36, 60,201,128, 33, 65, 28,183,235,135,207,150,221, 59,248,133, + 89,219,204, 6, 59, 12, 38, 43, 12, 6, 43,206,252,180,190, 11,136,130,210,211,200, 97, 19, 11,175, 10,137, 42, 8, 9, 26, 24, + 90, 68, 65, 15, 23, 44, 51, 99, 95,175,235,124,245,213,230,241,241,241,154,158, 61,123,138,110,183,155,142, 29, 59,134, 85,171, + 86, 57,126,254,249,103,206,237,118, 95, 41,109,252, 1, 64, 35, 67,174, 88,120,213, 24,175,134, 62, 65,141,211, 45,107,224, 20, +128,204,153,154, 25, 15, 11,175,190,154,146,144,144,208,164, 87,175, 94, 78,183,219, 45,241,234, 21,236,221,187, 87, 46,138,226, + 55, 40, 35, 17, 85,169, 84, 62, 53,111,222, 60,121, 70, 70, 6,166, 76,153,162, 60,123,246, 44,142, 29,243,228,247,125,253,245, +215,174,213,171, 87,231,217,237,246,206,193,212,229,240,193, 24, 59,174, 82,169,214,127,252,241,199,237,228,114,249,122, 0,152, + 57,115,230, 83, 78,167,243,229,218,181,107, 55,235,222,189,187,192, 24,147, 28, 63,126, 28, 95,126,249,101,225,238,221,187,165, +110,183,251, 7,198, 88,185,223, 31, 68,116,191, 76, 38,251,196,233,116, 62,206, 24, 11,249,253, 44,141, 90,173,198,119,223,125, + 7,158,231,241,196, 19, 79,224,208,161, 67,232,222,189, 59, 54,109,218,132, 3, 7, 14,132,195,255,165,240, 15,255, 7, 42, 10, +116, 91, 95,177,106,222, 85, 96, 41,109,240, 75, 71, 1,130,129,147,200,165, 0,192, 73,149,234, 50,198, 27,242, 30,252,242,244, + 42,163,201, 75, 73, 10, 0, 82, 57, 87, 45,122,254, 56,138,132, 91,225,193, 95, 33,162,250,190,223, 43, 35, 96,179,217,226, 42, +218,234, 23,106,100,129, 49,182,158,136,142,205,155, 55,111,211,222,189,123, 27,124,245,213, 87, 42, 0,176,219,237,237, 23, 44, + 88,176,102,199,142, 29, 77,215,173, 91,167, 10, 86, 79, 16, 4,152, 76, 38, 12, 26, 52,200,122,242,228,201,243,118,187,125,164, + 92, 46, 63,107,177, 88, 48,108,216, 48,235,161, 67,135, 50,109, 54,219, 96,198, 88,149,118, 45,132,138,156,231,156, 86,187,221, +185,231,178, 67,162, 80, 69,152, 93, 18,153,242, 92,174,149, 4,121,180, 81, 38,215,232,244, 54,183,181,192,104,119,170, 34,107, + 20, 64, 30,161,187,126,163,208,106,182,217, 93,229, 24,107,171,213,106, 53, 21, 21, 21,249, 30, 23,224,201, 3,128,223,125,255, + 89,188, 19,158,100,220, 96,120, 13,192, 1, 34,226, 1, 44,247,234,140, 5,240, 28,128,222, 65,106, 20,227, 22,132,151,207, 31, +253,229,215,111,230,164,112, 13, 59, 63,112,216,230,132, 59,227,224,198,123,117, 87,207,118, 3, 19,187, 7,163,161,149,193, 38, +101, 86, 71,207,122, 48,203, 24,204, 16, 97,153, 17, 61,189,177,174,176,176,229,185,115,231,120,141, 70,131, 31,127,252,145,211, +233,116,174, 67,135, 14,137,118,187,253, 6, 99,236, 56, 99,172,204,216,179, 86,134,235,188,104,203,239, 85, 27,151,101, 18, 79, + 18,224,235, 17,211,255, 81, 84, 88, 56, 35, 61, 61, 93,173,209,104,176,121,243,102,153, 78,167,179, 28, 58,116, 72,112, 56, 28, +123, 25, 99, 83, 25, 99,101,126,118,236,118,251,165,237,219,183,183, 51,155,205,184,114,229, 10, 92, 46, 23,210,211,211,113,234, +212, 41,113,245,234,213,185, 94,227,159, 19,234,107,103,181, 90,159,240,253,254,250,235,175, 79, 46, 42, 42,122,235,220,185,115, +106,149, 74,133,173, 91,183, 74,117, 58,157,245,240,225,195, 14,187,221,126,128, 49, 54,153, 49, 22,112,205, 8, 0,136,168,127, + 84, 84,212,250,119,223,125, 87,253,252,243,207,111, 33,162,129,140,177,159, 67, 29,151, 63,254, 97,255,175,190,250, 10, 13, 27, + 54,196,183,223,126, 27, 94,251, 15,130,144,114, 0,254, 12, 56,157, 78, 75, 89, 97,127,159, 83,192,113,213,146,223, 88,173,123, +240,111,145,102, 72,122,228, 87, 7,160,253, 43,141,254, 85,193,185, 21,214, 1, 40,141, 55, 15, 32,232,217,121, 48,248, 71,136, +168, 84,125,128, 80,116, 24, 99,151,137, 40,249,192,129, 3, 11,155, 55,111,254,164, 40,138, 74, 0,215,140, 70, 99,167, 99,199, +142,189,219,188,121,243,103, 4, 65, 8, 42,106, 97,183,219,249, 6, 13, 26, 88, 29, 14,199, 50,139,197,242, 50, 0, 94, 16, 4, +174, 97,195,134, 86,139,197,178,220,106,181, 78,174,104,134,116, 43,144,203,248,194, 24,141,202, 16, 95, 51, 70, 83,104,135,178, +118, 66,252,217,250,117,235, 94, 95,191,239,183,102, 70,187,219,246,204,152,145,223, 67,166, 54, 60,245,210,236,251,114, 11,138, +108, 91, 54,126,183,116,220, 51,207,151,183,109,239,200,136, 17, 35, 78,143, 29, 59,118,224,172, 89,179, 4,120,178,253, 69, 34, +234,230, 93,243, 63,226,189,127,143,247,126,102,176, 53, 16, 24, 99,153, 68,212, 27,158,100,192, 67, 0, 84, 0,182, 1, 8,121, + 7,128,159, 94,247,236,243, 39,231, 94, 63,119,252, 69, 6,166, 36,146,108, 7, 19,131,218, 1, 0, 0, 81,114, 88, 0,216,101, +158,170,135,150, 87,213,175,196, 22,228,230,182,106,210,164,137,164, 93,187,118,216,178,101, 11, 56,142,195,254,253,251,153, 32, + 8,251, 24, 99, 55, 42,208,187, 2,224,134, 76,226, 9,251, 79, 83,188,210, 35, 63, 39,231,245,123,238,185, 71,149,156,156,236, +211,163, 3, 7, 14,184, 5, 65,120,176, 34, 35,105, 54,155, 31, 31, 49, 98,196, 26,167,211,217,168,123,247,238,152, 56,113,162, + 50, 33, 33, 1, 43, 87,174, 52,219,237,246, 57,149, 49,254,254,188,250,234,171, 67, 10, 10, 10,102, 55,110,220, 88,149,156,156, +140,173, 91,183,226,216,177, 99,116,240,224, 65, 38, 8,194, 8,198,216,238,138, 52,136,232,111,145,145,145,223, 29, 61,122, 84, + 45,147,201, 48,127,254,124,117, 74, 74,202,102, 34, 26,204, 24,251,169, 50,227,210,235,245, 37, 66,255, 82,169, 20, 57, 57, 57, + 80,171,213, 97,227, 95, 5,254,148,175, 28,199,113, 89, 61,123,247,254,160,162,243, 36, 18, 73, 86, 69,231,104, 20, 58,220, 83, +235, 8,234,117, 73,197, 35,255,215,152, 1,128, 75, 96, 66,230, 57,211,191, 25, 99,139, 40,196, 61,248,113, 98, 30,250,186,246, +225, 65,126, 51,222,118,101,174, 41, 0, 0, 32, 0, 73, 68, 65, 84,107, 61,157, 1,128,195,205,132,212, 2,199,191,191,187,193, + 22,121,103,234,243, 0, 44,132,119,230, 94,158,158,202,236, 64,131, 92,194, 3,121,102,188,215, 90, 89,101, 61,230, 87, 7,160, + 60, 3, 90, 69, 35,126,184,146,207, 3,112,243, 86, 63,255, 37, 0,223,152, 42, 59, 54,175, 81,158, 72, 68,219,181, 90,237, 51, + 70,163, 81,240,134,110,167, 16,209, 14,173, 86,251,162,209,104, 44,175, 6, 0, 0,216,212,106,245,206,162,162,162, 15, 25, 99, + 91, 0,207,235, 21, 17, 17,177, 53, 63, 63,127, 25, 99,236,251,202,140,173, 58,144, 75,121, 51,152, 88,208,167, 83, 11,211,249, +124, 7,107,215,170,197,185,102,247, 52,206, 94,185,249,151,182, 58,139,103,205, 31, 50,181, 33,251, 70,161, 53, 43, 39,207, 6, +121,132,126,197,202, 85,229,149,236, 53, 1, 48,184, 61,133, 0,252,207,115,122,239,251, 71, 6, 66,222, 85,194, 60,251,243, 71, +133,250,188, 10,244, 42,237, 84,199,169, 96,134, 27, 14,112,176, 76,176,254, 83,106,200,185,212,181,121,243,230,146,168,168, 40, +108,218,180, 9, 63,252,240, 3, 36, 18,137, 91, 16,132,227, 21, 25,127, 0,168,165,194, 37,120,170, 44,101, 62,103,123, 38, 82, +151,125,105,101, 82, 82,146,202, 95,143,227, 56,171,203,229,250,119, 48, 51,100,198,216, 25, 0,173,136, 72,113,224,192,129,162, + 97,195,134, 33, 42, 42, 10, 29, 59,118,212,166,167,167,143, 1,176,164,178,215,254,236,179,207, 54,213,233,116,171,147,146,146, + 84, 49, 49, 49,248,241,199, 31,177, 97,195, 6, 72, 36, 18,171,203,229,154, 30,164,241,239, 23, 25, 25,185,225,232,209,163,106, +185, 92,142,140,140, 12,116,235,214, 13,203,150, 45, 83, 63,251,236,179,155,136,104, 8, 99,108, 79, 40,227,226, 56, 14,177,177, +177, 65,159, 31,206, 3, 8,158,219,226, 0, 84,247,174, 2,183,219, 93,183,186,198,214, 62,233, 26,251,239,216, 58,244,237, 17, + 51,156,174, 98, 89,233,247,159,103,190, 10,192,103, 96,131,222,131, 63, 68,117,150,205,157,248, 2, 33,235, 58, 16, 27, 93,172, +247,250,209,194, 87, 1, 44,242,134,233, 83,224,153,185,167, 16,209,145,242,180,219, 57,229,172,255,125,171, 8, 59,255, 6,180, +150, 84, 89,207,143,138,182, 21, 86,101,219,225,186, 42, 60, 55,232,237,125, 85,193,107,164,191, 47,117,108, 11,128, 45, 65, 60, +215, 1,224,129, 82,199,220, 0, 6, 86,231, 24, 43, 3,199, 73,148,135,143, 28,151,117,235,216,254,151,238,170,104,195,234,157, + 71, 91, 29,186,112, 35,246,185,113,143,110,128, 44,194,240,228,212, 55,250,102,223, 40,116, 46,249,207,162, 79, 26, 39,181, 42, + 34, 9,255, 52, 0, 48,198, 62, 14, 32,217,224,225,135, 31,206,121,240,193, 7, 87,174, 89,179,198, 77, 68, 93,189, 57, 0,190, +153,127, 99,239,253,171,222,251, 81, 68, 36, 4, 10,137,255,209,233, 88, 3, 38, 72, 32,140,202,121, 76, 85, 80,112,185,159,201, +100,146, 92,186,116, 9,151, 47, 95,134, 94,175,119,139,162, 8, 81, 20, 47, 2, 40, 55, 4, 94,172, 23,135, 11, 0,140,143,101, +143,172, 87, 84,148,177,211,100, 50,169, 50, 50, 50,144,153,153,201,244,122,189, 93, 20, 69, 18, 69,241, 19, 0, 1, 51,245,203, +130, 49,102, 87,169, 84,151, 14, 31, 62,220, 34, 57, 57,153,118,236,216, 97,177,217,108,159, 85,252,204,178,121,244,209, 71,239, + 45, 42, 42,218,105, 50,153, 84,151, 46, 93, 66,102,102, 38,116, 58,157,141, 49, 6,151,203,181, 10, 65, 58, 22, 18,137,100,211, +138, 21, 43,148,114,185, 28, 23, 46, 92,128, 90,173,134, 82,169, 68,175, 94,189,240,205, 55,223,168, 31,126,248,225, 31,225,137, +244, 4,141, 40,138,112,108,120, 9,211,246,137, 32,162,226, 74,175,190, 60, 28,255,234,175, 68,132, 25, 51,102, 84,230, 37,184, + 43,161, 32,163,117,127, 89, 26,180,111,181,182,199,128,164,225, 14,227,241,226, 25,165,224, 16, 45, 87, 47,154, 83,124, 89,247, + 20,100, 99, 28, 0,232,152, 88,127,237,136, 54,245,135, 75,175,167, 22,235,217,220,204,114,162,208,145,178, 46,143,125, 20,234, +154,253,128, 38,138,181,195, 90,199, 15,183, 94,204,171, 22,189,219, 1, 17, 37, 84, 53, 20, 25,166,114,196,199, 68,236,141,138, + 80,171, 53, 17,234,227, 82,169, 76,111,176,218,155, 48,144,165,110, 98,194,247,188, 92, 94,116,242,244,185, 30, 86,155,195,154, + 16, 31,255,225,233, 51,103,156, 68, 52, 1, 8,236, 0, 16,209, 28,120,214,230, 15,193, 19, 13,168,231,253,121,204,251, 51, 6, +128, 29, 64,182,119,109, 70, 5, 64, 96,165,106,226,255,105,120,129, 56, 44, 98, 98,199,142, 29,251, 26, 12,134, 26,122,189,222, +166,215,235, 45, 46,151,203, 0, 79,133,195, 92, 22,100,125,126, 0, 96,147, 73, 78, 11,153,163, 67,135, 14,219, 12, 6, 67, 87, +189, 94,159,173,215,235, 47,185,221,238,179, 0, 46, 2,216,201, 24,187, 80,153,161, 18, 81, 11,181, 90,253,165, 32, 8, 13, 57, +142, 91,110,183,219,167,150,149,136, 24, 12,254,227, 51, 24, 12,151, 93, 46,151,111,124,187, 25, 99, 65, 79, 6, 42,170,219,175, + 80, 40,242,108, 54, 91, 72, 14,190, 76, 38,115,243, 28, 56,135, 16,220,165, 73, 36, 18,209,233,116,134,195, 0, 65,112,215, 59, + 0, 97,194,132, 9,115,171,137,141,141,165,252,252,252, 63,236,151,237, 31,121,124, 68,164, 0, 16,116,101, 55, 0,118,198,152, +253, 86,141,231,175, 68,216, 1, 8, 19, 38, 76,152, 48, 97,238, 66,254,204,165,128,195,132, 9, 19, 38, 76,152, 48,149, 36,236, + 0,132, 9, 19, 38, 76,152, 48,119, 33, 97, 7, 32, 76,152, 48, 97,194,132,185, 11, 9, 59, 0, 97,194,132, 9, 19, 38,204, 93, +200,159,178, 16, 80,152,187, 27,242, 22,237, 15,182,226,220, 31, 17,171,213,154, 80,149,231,171, 84,170, 59,182,205,146,136, 54, + 1, 24,228,189,187,153, 49, 54,168,188,243,195,220,221, 16, 17, 7,160,150,247,110,126,101,183, 42,134, 9, 13, 34, 74, 2, 48, + 2,158,109,188, 12, 30,123, 63,199,255,245, 15, 71, 0,238, 50,136, 40,134,136,222, 34,162,183,137, 40,198,123,108, 19, 17, 49, +239,109,211,157,212,171,224,111, 53, 32,162,245, 26,141,198, 16, 29, 29,109, 34,162, 31,136,168, 89,117,233,223, 41,148, 41,177, + 39, 85,147,213,217,170,201,234,108,101, 74,236,201, 59, 61,158, 32, 24,148,158,158,142,244,244,116, 0, 24,232,253,130, 15, 83, + 14, 50,153, 44, 67, 46,151, 47, 35,162,200, 59, 61,150, 59,192, 47,181,106,213,202, 73, 72, 72,200, 1,112,224, 78, 15,230, 46, +226, 49,198,216,108, 0, 17, 0,230,195, 99,239, 75, 84, 80, 13, 71, 0,238, 62, 94, 24, 55,110,220,244, 26, 53,106,224,253,247, +223, 31, 72, 68,221, 0, 12,242,245,246,214,104, 52,131,136, 40, 2,192, 96,120, 74,170,246, 6,176, 27,192, 63, 24, 99,198,178, +244,198, 62,252,192,244, 26,145, 17, 88,248,249,186, 98, 61,241,215,207, 0,155, 30, 92,159, 41,161,234,149, 9, 17,213,213,104, + 52, 39, 7, 14, 28,104,237,222,189,187,132,227, 56,183, 78,167,107,255,201, 39,159,156, 32,162,118,140,177,244, 42,188, 38,119, + 20,114, 90, 99,177,204,219,252,232, 25,138,253,199, 63,254,241, 53, 99, 12,105,105,105, 39, 85, 42,213,254, 45, 91,182,236, 87, +169, 84, 65, 69, 59, 84, 42, 85, 42,199,113,117,125, 85,210,124, 29, 14,189,213, 44,175, 25, 12,134,144,138, 68, 17, 81, 67, 0, +245, 43, 56,173,159,183, 15, 0,224,153,225,157,174, 72, 87, 42,149,230,186, 92,174, 56,239,239,121, 78,167, 51,190,188,227, 55, +177,244, 62, 5,128,246,240, 20, 34,242,225,132,231, 11,206,255,152,205,123,243, 63,166, 7,176, 11,207,238,186,109,189, 26, 4, + 65,104,212,185,115,231,177,199,143, 31,127,148,136, 38, 1, 88,241,103,142, 96,149, 7, 17, 53,145, 72, 36, 95, 2,144,187,221, +238,231, 1,116, 62,122,244, 40, 12, 6, 3, 90,181,106,117, 47, 17,245, 36,162, 69,241,241,241, 44, 39, 39,103,164,183,124,115, +152,234,199, 87,210,220, 12, 79, 4,192,129, 82,109,191,195, 14,192,221, 71,124,147, 38, 77, 48,125,250,116, 20, 22, 22,182, 91, +177, 98,197, 77, 37, 72,229,114,249,141,190,125,251, 42,135, 12, 25,130, 62,125,250, 96,234,212,169,143,108,221,186,245, 43, 0, +223,149,169, 87, 55, 30,211,159,121, 4,133,133,133,237, 86,110,220,227,209,179, 22, 1, 54,189, 71, 79, 42,185,209,191,195, 61, +202, 71,122, 36,225,239,201,245, 49, 97,241,143,143,108, 56,116,177, 76,189, 17, 77, 61,141,127,214,189,216,211,115,255, 67, 79, + 23,209, 39, 58,213,130,226,158,238,152,251,225,127, 12,209,209,209,187, 93, 46,215,218,221,187,119, 55,171, 91,183,238, 83, 79, + 62,249,228, 2, 0, 67,170,227,197,249, 35,176,114,229,202, 94,130, 32,192,233,116,246,218,186,117,235,136,222,189,123,111,156, + 56,113,226,194, 39,159,124,178, 66,135,137,227,184,186, 63,253,244, 83,156, 86,171, 5,199,113,144, 72, 36,224, 56, 14,118,187, + 29, 93,186,116, 9,105, 28, 68,244, 70,131, 6, 13,166, 55,104,208,160,196, 12, 95, 16, 4,140, 28, 57, 18,118,187, 29,173, 91, +183, 70,100,100,228, 14,192, 83,178,245,250,245,235, 32,162,215, 24, 99,115,202,211,118,185, 92,113, 70,163, 17,162, 40, 34, 42, + 42, 42,174,162,227,101, 80, 27, 57,191, 61,194,204,249,147,138,199, 27,211, 96, 37,220, 2,207, 12,215, 71,255,126,172,209,215, +112, 59,193, 12, 89,143, 21, 31,211,196, 47, 69,124,139, 75, 0, 42,116, 26,137,168, 79, 13, 41,102, 89, 69,180, 7, 0, 21,135, + 99,133, 2,102, 85,166,169,205,250,245,235, 21, 95,127,253,181,226,195, 15, 63, 92, 92, 88, 88, 56,153,136,198, 49,198, 78,132, +162, 65, 68, 60,207,243,135, 69, 81,252,216,237,118, 47,245, 29,151,201,100, 71,221,110,247, 10,183,219,189,200,119,204,231, 76, +241, 60,159, 39, 8, 66,192,234,123, 60,207,231,186,221,238, 56,137, 68,146,231,114,185,138,207,147, 72, 36, 47,242, 60,255,152, +195,225,232,234,119,236, 5,158,231,199, 57, 28,142,242, 74,183, 47,222,185,115,103,103,181, 90,141, 17, 35, 70,252,220,185,115, +103,200,229,114,236,217,179, 7, 73, 73, 73, 48, 24, 12, 63,127,241,197, 23, 48, 26,141, 24, 63,126,252, 82, 0,127, 11,229, 53, + 8, 19, 52,190, 46,157, 28,128, 88,120,122,119,148,136, 0,132, 11, 1,221,101, 16, 81,125,158,231,143,238,220,185,179,198,189, +247,222,139,113,227,198,225,198,141, 27, 96,140, 33, 42, 42, 10,131, 6, 13,194,128, 1, 3,160, 82,169, 80, 84, 84,132,173, 91, +183, 98,238,220,185,206,188,188,188,158,140,177,155,154,252, 16, 81,125, 94, 34, 57,186,227,147, 89, 53,238,109, 94, 31,227,102, +252, 7, 55,138, 12, 0, 19, 17,163, 81,226,161,110,205, 49,244,222,123, 16,169,224, 96, 48, 24,177,241,151,179,120,117,213,126, +103,118,145,165, 76,189, 17, 77,137,173, 59,127,115,163,159,136,136,136, 43,111,190,249,102,236, 11, 47,188,176,153,231,249,157, + 25, 25, 25,191, 14, 25, 50,164, 96,237,218,181,191, 13, 30, 60,152,207,204,204,212,252,153,102, 84,254, 57, 0,226,148,216,139, + 17,204,234,105, 79,172,172,233,254, 63,227,144, 84, 81, 20,209,173, 91,183,196,193,131, 7,215,205,201,201,177, 63,254,248,227, +159, 29, 59,118,236,109,223,115, 2,229, 0,104, 52,154,220,163, 71,143,198,173, 95,191, 30, 74,165,178, 68,151,204,137, 19, 39, +230, 21, 22, 22, 6, 93,134,149,136, 46,101,101,101, 53,172, 93,187,246, 77,143, 93,185,114, 5,122,189, 30, 17, 17, 17,136,138, +138,130, 32, 8, 16, 4, 1, 89, 89, 89,232,214,173,219,101,198, 88,163, 10,180, 25, 99, 12,235,215,175,199,136, 17, 35,138,155, + 59, 5, 58,126, 19, 75,239,107, 42, 94, 59, 58, 11,247,220,215,154,123,114,125, 43,113,249,240, 83,184,250,235, 53,184, 28, 18, + 52,234, 85,151,123,114,125,115,113,249,240,179,184,122,248, 58, 92,118,160, 81,175,218,197,199, 46,238, 62,195,213,105,255, 6, +158,221,245, 91,121, 99,140,146,211,156,134,117,234,190,184, 97,201,124, 85, 66,147,230,112, 23, 92,199,233,159,183,225,177,249, + 43,172, 5,122,227,135,122,135,123, 90, 8,175, 37, 43, 40, 40,192,193,131, 7, 97, 50,153,176,111,223, 62,182, 98,197, 10, 59, + 99,108,181,221,110,255, 55, 99, 76, 31,164,142,130,136, 44, 90,173,214,102,179,217,118, 56,255,159,189,235, 14,143,170,232,222, +239,236,173,219,211, 19,144, 18,138, 16,233, 82, 62, 58, 4, 16, 20, 2,210, 81, 65, 84, 68,253, 68, 5, 62, 16, 81,176, 16, 20, + 41, 98,143, 88, 64,233, 32, 63, 44,128, 8, 9,157,132, 30,164, 35, 16, 32, 64, 8, 33, 9, 1,210,118,147,173,247,252,254, 72, +118, 77, 66,178,217, 32,138,101,223,231,153,103,247,206,206,125,239,185,101,239, 57,115,102,230, 28,155,237, 9, 34,202,103,140, +145,159,159, 95, 65, 97, 97, 97,188,213,106,125,140,136,114, 25, 99,180, 97,195, 6, 68, 69, 69,121, 76,158,197, 24,163,181,107, +215, 98,192,128, 1,174,188, 44, 70, 73,146, 86,233,116,186,174,217,217,217,130,211,233, 20, 24, 99, 70, 89,150, 87, 26, 12,134, +174,215,174, 93,211, 86,194,183,230,185,231,158, 27,208,171, 87, 47, 24,141, 70, 4, 5, 5, 33, 53, 53, 21,215,174, 93,131, 70, +163, 65,189,122,245, 32,138, 34, 22, 44, 88,128,207, 63,255,124, 45, 17, 13,244,246, 58,250, 80,117, 48,198,238, 65, 81,194,173, +239,168, 76,154,105,159, 7,224, 95, 6, 34, 74, 97,140, 61, 50,116,232,208, 77,135, 14, 29,226,190,253,246, 91, 56, 28, 14,119, +201,201,201,193,207, 63,255,140,181,107,215, 34, 62, 62,190,208,102,179,197, 2,248,176, 60,101, 93,146,111,216,203,239,109,250, +101,105, 52,247,127,239, 60, 3, 56,108,128,179,168,228,231,229, 99,221,158, 19, 88,157,112, 18, 91, 14, 95, 42,180, 58,156, 30, +249, 92, 61,255,114,224, 84,171,213, 84, 80, 80,176, 54, 61, 61,253, 84, 68, 68, 68,102, 68, 68, 68, 88, 64, 64,128, 74, 81, 20, +165,162,157,254,234,120,224,129, 7,218,189,242,202,242,236,126,253,250,169, 71,143, 30,189, 59, 45, 57,109,230,170, 85,239, 29, + 7,128, 71, 31,125,180,217,214,173, 91,167,206,156, 57,179,211,184,113,227, 6, 60,240,192, 3,219,182,110,221,186,223, 19,159, + 43, 57,138, 44,203,248,244,211, 79,179,179,179,179,109, 64, 81, 70, 53,167,211,153, 90, 69,241,190,238,218,181,235,187, 53,107, +150,206,189,213,180,105, 83,204,154, 53, 11,115,230,204,193,241,227,199,161, 40, 10,136, 8, 68,132, 43, 87,174, 40, 0,150,121, + 67,110,177, 88,160,209,220,154, 23,166,162,250, 63, 19,140,177,200,230,117,106,140, 63,148,184, 95,195, 86,207, 0, 86, 78,132, +224,116,160, 85,173, 70, 56, 62,253, 73, 77,195,215, 23,142, 99,140,109,174,138, 39,192,117, 95, 20, 69, 65,223,190,125, 89,143, + 30, 61,212, 11, 23, 46, 28,177,125,251,246,161, 28,199, 77, 80, 20,101,145, 55, 70, 44, 99,140,126,252,241, 71,237,132, 9, 19, + 30, 58,115,230,204,105,198, 88, 20, 0,172, 95,191, 94, 51,113,226,196,110,199,142, 29, 59,195, 24,123, 24, 0,170, 85,243,110, +174,169,203,200, 99,140,181,145, 36,105,253,172, 89,179, 2,219,182,109,203,119,238,220,217,193, 24,107, 45,203,242,250, 57,115, +230, 4,117,236,216,145,111,221,186,181, 39,217, 84, 0,166,207,159, 63,191,111,231,206,157,249,228,228,100, 56,157, 78,183, 49, +106,179,217,144,155,155, 11,147,201,132, 47,191,252,210, 1, 96, 58, 99,140,243, 77, 12,188,243, 96,140, 73, 0,234, 20,111,254, + 12, 64,205, 92, 22,182, 11,174, 63,174,175,252,187, 10,128,103,253,252,252,242,187,116,233, 66,157, 59,119,166, 49, 99,198,208, +245,235,215,169, 99,199,142, 4, 32, 14,192, 35, 0,116, 85,226,211,107,242,187,182,168, 79, 93,155,215,163,241,131, 58,146, 18, + 55,157, 34,155,213,174, 26,223,103,157,169, 28,110, 9,192,186,241,227,199,155,151, 45, 91,246,243, 19, 79, 60,209,172,103,207, +158, 29, 18, 19, 19, 87,237,216,177, 35, 3,192, 15,119,251,122, 86,181,152,205,230,106,102,179,185, 90,195,134, 13,231,216,237, +118,101,229,202,149,151,187,117,235,214,199, 85,239, 42,221,186,117,235, 83, 48, 54,208, 65,207,129,232, 57,144,242,162,246,154, +217,108,174, 86, 17,175, 94,175,207, 72, 78, 78,166,121,243,230,145,159,159, 95,198, 29,120, 78, 26, 3,136, 44, 81,222,138,140, +140,164, 27, 55,110, 80,231,206,157, 9,192, 91,101,126,175,227, 37, 47,101,103,103, 83,124,124, 60,161,120, 65,135,167,250, 91, +202, 23,221,235,208, 91,193, 31, 41, 19, 65,215,198,128,250, 53,144,169, 77,221,128,204,179,227, 66,215, 40, 19, 65,174,114, 98, +236, 61,235,218,133, 27, 50,135, 55,145, 41,253,191, 69,117, 52, 45,236, 11,250,162,123,132, 39,249, 2, 5,236,188, 24,187,146, +148,121,255, 37,165, 31,138,202,195,140,148, 81, 53, 73,153, 53,152,126,120,161, 47, 5,234,228,157, 85,184,142,148,147,147, 67, + 9, 9, 9,180,105,211, 38,218,190,125, 59,237,218,181,139,246,239,223, 79, 75,151, 46,165,250,245,235,155,180, 90,237, 9, 0, + 45, 43,225,145, 85, 42,149,131,136,232,179,207, 62,163, 81,163, 70, 41,162, 40, 22, 20, 95, 43, 90,190,124, 57,141, 25, 51, 70, + 17, 69,177, 16, 0,157, 57,115,198,243,117, 44,150,237,212,169, 83, 4,128, 66, 66, 66, 10,142, 30, 61, 74,185,185,185,180,101, +203, 22, 2,160,132,134,134, 22, 28, 63,126,156,242,243,243,105,255,254,253, 30,249, 0, 28, 8, 14, 14,166,193,131, 7,211,153, + 51,103, 40, 38, 38,134, 80, 52,238,124, 13, 64, 86,207,158, 61,105,243,230,205,244,243,207, 63, 83,139, 22, 45, 40, 32, 32,128, + 80,148, 89,242,174,255, 39,255,105, 5,192, 8, 20, 37,241, 34, 0, 7, 80, 52, 36, 32,151,108,227,243, 0,252, 75, 65, 68, 11, + 24, 99,223, 37, 36, 36,180, 0,208, 75, 81,148, 41,118,187, 29,197,157,233,143, 0,196, 3,248,156, 49,214, 5,192,114, 34,138, +246,134, 47,254,232,249, 22, 0,122,129, 28, 83,224,176,128, 20,103,149,248,134,124,178, 11,223,191,248,219, 54, 99,172,102,120, +120,248,206, 17, 35, 70,212,205,203,203, 67, 74, 74, 74,183,215, 95,127,125,159,191,191, 63, 59,186,119,155,250,249,137,175,231, + 1,120,249,119, 94,142,187,134,166, 77,155, 54, 35, 34,150,144,144,144,181,100,201,146, 91, 86, 0, 44, 89,178,228,152,122, 70, + 45,174,228, 36, 65, 79,124, 46, 15,128, 36, 73,238, 58,215, 24,111,121,237, 61, 78,180, 3, 64, 37, 38,244, 21, 47,191,124,239, +137, 39,158,128,213,106,197,240,225,195,177,107,215,174,190, 0,222,161,226, 55, 78, 85, 96,179,217,202,237,233, 87, 84, 95, 6, + 87, 80,173,233,154, 66,155,115, 71,219, 89,199,102,252, 24,187,163,233,133, 11, 23, 66,158,158,252,180,101,215,164,238,238, 57, + 0,255,251,228, 72,151, 49,211, 99, 66,218,182,109,139,174, 61, 59,159, 59, 56,225,190,183, 13,106, 62, 29,192,101, 79,228, 5, + 10, 90, 86,175,215, 16, 88, 49,190,168,130, 23,128,192, 26, 64,224, 61,128, 32,161,117,131, 48, 20,216,156, 45,171,114,190, 46, + 15, 0, 99, 12,130, 32, 64, 16, 4,240, 60,143,214,173, 91, 99,195,134, 13,218, 31,126,248,161,241,204,153, 51,119,251,251,251, +199,100,103,103,191, 90, 25, 95, 80, 80, 16,250,244,233,195, 90,182,108,169, 62,124,248,176, 3, 0, 31, 24, 24,136, 65,131, 6, +177,182,109,219,202, 7, 14, 28,112,104, 52, 26,175,222,241, 90,173, 22, 47,190,248,162, 99,226,196,137,106,157, 78,135,179,103, +207,194,104, 52, 98,220,184,113,206,137, 19, 39,170,245,122, 61, 82, 82, 82,160,215,235, 43,163,250,207,161, 67,135,160, 40, 10, + 78,158, 60,233,190,143,130, 32,168,141, 70, 35,142, 31, 63,142,209,163, 71,187, 27,235,116, 58,228,231,231,123,157, 10,222,135, + 42,225, 27, 34,146, 25, 99,132,162,201,215,183, 12, 51,249, 12,128,127, 49,136, 40,135, 49,118, 77, 16,132,231, 95,120,225, 5, +216,237,118,244,232,209, 3,137,137,137,171,156, 78,103, 82,207,158, 61,219, 78,154, 52, 9, 79, 60,241,196,155,140,177,197, 68, +116,201, 43, 62, 78,245,252,171,131,218, 2, 14, 43, 30,110, 29,142, 61,167,210, 86, 57, 20, 74, 26,220,166,102,219, 79, 30,107, +134,246,239,108,243,138,143, 49, 86,187, 94,189,122, 9,137,137,137,181, 82, 83, 83,241,226,139, 47, 98,207,158, 61, 91,223,123, +239,189, 38, 60,207,115,125,234,241,181, 47, 92,184,214,132,136,170,234,218,254,203,128,136, 80,194,240,250,221, 96,140,193, 98, +177, 64,150,101,168, 84, 69,115,247,156, 78,103,232,254,253,251, 97, 52, 26,193,113,156,187, 88, 44, 22, 68, 68, 68,120,154,104, + 87, 22,163, 58,116,232,208,166, 87,175, 94, 72, 74, 74, 66,247,238,221,209,166, 77,155, 54, 7, 15, 30, 28, 5,160,202,185,232, +157, 78, 39,180, 90,173,215,245,165,240,252, 54, 59,128, 4, 45, 99,115,150, 47, 95,222,180,105,211,166,120,229,149, 87,104,119, +114,238,167,120,126,219, 62, 87,179,109, 99,216, 5,251, 55,223, 60, 55,124,248,112,213,156, 79,231,223,235, 55,104,208,127, 20, + 69, 25,231,141,124,142,107,151, 33, 40, 78, 64, 84, 23, 41,126,151, 1, 16, 88, 3,138, 83, 6, 88,133,195,224,229,130, 49, 6, + 89,150,193,113,156, 91,249,187, 12, 1,142,227, 32,138,162,215, 60, 0, 16, 24, 24, 8,158,231, 97, 54,155,193,243, 60, 1, 69, + 70, 1,199,113, 48,155,205,208,106,181, 94, 15,165,104, 52, 26,104,181, 90,164,164,164,160,118,237,218, 8, 10, 10, 2, 0,240, + 60, 79, 41, 41, 41,104,208,160, 1,130,130,130,220,207,148, 39,100,102,102, 98,199,142, 29, 8, 12, 12,116, 31,223,110,183,235, +178,178,178, 96, 54,155,225, 90,113,164,211,233,160,211,233,220,231,227,195, 93,192,221,118, 83,248,202, 93,117, 17, 85,103,140, + 93,142,137,137,161,148,148, 20, 90,190,124, 57, 37, 37, 37,209,119,223,125, 71, 79, 60,241, 4, 37, 38, 38,210,252,249,243,137, +231,249, 76, 0,188, 87,124,192,229,101, 47, 71,145,178,230,127,180,117,218,195,164,252,223, 51,244,203,140, 40,154,216,187, 33, +217, 22, 12,160,132,201, 29, 72,224, 88,197,124, 37,134, 0,234,212,169,115,250,230,205,155,116,233,210, 37,122,254,249,231, 73, + 16,132, 95, 75,182, 29,124, 47,168,170,231,252, 87, 41, 46, 23,127,131, 6, 13,230,220,184,113, 67,249,250,235,175, 43, 28, 2, + 48,191, 20,224,245, 16,128,193, 96, 56,232,231,231,151, 17, 16, 16,144, 97, 52, 26, 15, 22,223, 23, 58,125,250, 52,189,253,246, +219, 52,119,238, 92,154, 55,111, 30, 45, 90,180,136, 86,173, 90, 85,169,123,184,196,189, 21, 24, 99,233,155, 54,109,162,157, 59, +119,146,209,104,164,184,184, 56, 90,181,106, 21, 49,198,210, 1, 8, 85,124,246, 40, 45, 45,141, 46, 93,186,116,203, 16, 64,121, +245, 21,112,244, 30, 55,110, 28, 17, 17,125,251,237,183,212,174, 93, 59,106,223,190,189,173,125,251,246,182,135, 31,126,216,230, +250,222,174, 93, 59,199,146, 37, 75,136,136,232,213, 87, 95, 37, 0, 67, 43,147, 47, 80,192,206, 3, 51,199,144,242,198, 3,164, +140,137, 32,229,141, 30,164,124,244, 4, 41, 75,167,146,178, 97, 30, 45,155, 62,129, 2,253,140, 59,171,114,190,102,179,153,206, +158, 61, 75,167, 79,159,166,243,231,207,211,165, 75,151, 40, 45, 45,141, 54,111,222, 76,247,221,119,159, 73,175,215,123, 53, 4, +192,113,156,131,136,232,200,145, 35,244,214, 91,111, 41,178, 44,155,139,175, 21, 93,188,120,145, 62,254,248, 99, 69,173, 86, 23, +184,142,233,197,117,164,130,130, 2, 2, 64, 90,173,214,188,120,241, 98,197,108, 54, 83,118,118, 54, 1, 80, 52, 26, 77,193,162, + 69,139, 20, 69, 81, 72, 81,148,202,134, 0,190, 6,144, 17, 20, 20, 68, 43, 87,174,164,117,235,214,209,168, 81,163, 92,251, 80, + 76, 76, 12,133,134,134, 82,104,104, 40,205,157, 59,151,168,104, 39,175,158, 65, 95,169, 90, 1,176,185,248, 51, 17, 64, 47, 20, + 13, 7,136,165,218,220,109, 33,125,229,174, 62, 32,111,142, 31, 63,158, 46, 93,186, 68, 47,188,240, 2, 1,176,116,235,214,141, +182,110,221, 74,191,252,242, 11,125,245,213, 87,164, 86,171, 45, 0, 30,242,150,239,245, 97,237, 72, 89, 51,158,166, 14,106, 73, + 0, 44,253, 90,214,160,171,159, 60, 76,202,194,129,148,240, 74,123,210, 73,156,103,190, 98, 3, 0, 64,189, 49, 99,198,208,153, + 51,103,232,197, 23, 95, 36, 81, 20, 47, 1,168, 89,178,237, 63,193, 0,104,223,190,253,192, 37, 75,150, 92, 73, 77, 77, 85,134, + 14, 29,154,208,163, 71,143,135,178,178,178,170,103,101,101, 85,239,209,163,199, 67,125,251,246, 77, 72, 72, 72, 80,102,204,152, +113,165,125,251,246, 3, 93,251, 85,241, 62, 83, 82, 82, 18,205,157, 59,151, 62,251,236, 51, 90,184,112, 33,125,251,237,183,180, +110,221,186,170, 24, 0, 81,173, 91,183,166,179,103,207, 82,255,254,253, 9,192,185,190,125,251,210,222,189,123,169,105,211,166, + 4,160,111, 85,101, 74, 79, 79,167,226, 28,244, 84, 89,125, 5, 28,243,179,179,179,169, 42,176, 90,173,196,243,252,114, 47,228, +139,172, 27,226,103, 54, 47,152, 68,202,135, 35, 73,137,121,134,148,229,111,145, 18,251, 21,101,111,255, 63, 10, 14,244, 55, 1, +136,172,202,249, 22, 22, 22,210,229,203,151, 41, 37, 37,133,210,210,210, 40, 41, 41,137, 70,142, 28, 89,168, 86,171,115, 57,142, +123, 26,197,171,178, 42,225,145, 57,142,115, 92,187,118,141,162,162,162, 10,180, 90,237, 69, 0,141, 0, 80,126,126, 62, 61,242, +200, 35,133, 90,173, 54, 21, 64,115,151,210,245,198, 0,112,181, 3,208, 92,167,211, 93,121,250,233,167, 11,111,222,188, 73, 28, +199,217, 1, 52,211,233,116,169,195,135, 15, 47, 52,153, 76,222,240,221, 31, 18, 18, 98, 79, 76, 76,164, 45, 91,182,208,209,163, + 71,221, 6,128,201,100,162,244,244,116, 74, 79, 79,167,252,252,124,175,228,243,149,223, 87, 0,212, 64,209, 60,172, 91,230,189, +220,117,225,124,229,238, 21, 0,223,205,159, 63,159,118,238,220, 73, 0,110, 2, 8, 3,240,174,193, 96,112,116,239,222,189, 74, +202,223,197,183,230,181, 40,186, 56,111,120, 41,190, 0,173,224, 24,220, 50,172,114,229, 79,165,149,186, 90,173,142,191,255,254, +251, 73, 20,197,243, 0,106,223,210,190,156, 9,131,127,151, 82,178,151,159,255,156,198,236,234,225,155,199, 6, 58, 6, 15, 30, +188,111,208,160, 65,251,222,126,251,237,148,248,248,120,229,251,239,191, 47,168, 95,191,254,103, 37,247,169,226,125,166,243,231, +207, 83, 76, 76, 12,125,243,205, 55,180,114,229, 74, 90,187,118, 45,109,222,188,185, 42, 6,192,183,209,209,209,244,203, 47,191, +144, 70,163,113, 2,104,173, 86,171,157,113,113,113, 52,110,220, 56, 2,240,109, 85,101,202,202,202,186,165,135, 90, 81,125, 5, + 28,131,167, 76,153, 66, 68, 68,107,214,172,161,135, 30,122,200, 93,158,121,230,153, 82,219, 43, 86,172, 32, 34,162,119,222,121, +135, 0, 12,241, 70, 70,163,200,207,172, 25,228,103,250,126,220, 16,186,244,249, 36,186,184,108, 14, 45,155, 49,153,130, 3, 3, + 76, 70,189,126,102, 85,207,215,106,181,210,181,107,215, 40, 51, 51,147, 62,249,228, 19, 69,175,215, 23,232,116,186,175, 1,248, + 85,129, 71, 86,169, 84,202, 61,247,220, 99,214,233,116, 43, 1,104, 92,252,225,225,225, 38,189, 94,255, 35,138, 39,219, 2,168, +180,199, 94, 94, 59, 0, 58,163,209,184,166, 78,157, 58,102,142,227,236,174, 58,189, 94,255, 67,120,120,184,201, 11,190,173,235, +214,173,163,163, 71,143,210,146, 37, 75,232,192,129, 3, 62, 15,192, 93, 40, 0,186,160, 40, 10, 96,100,137,162, 42,213,230,110, + 11,233, 43,119,245, 1,121,239,181,215, 94,163, 99,199,142,145, 74,165, 42,196,111,113, 33, 26, 2,120, 28, 64,163,170,242,205, + 29,217,142, 44, 75, 71,146,138,225,182,248,202,246,234,139,173,215,242,221,203,255, 16, 3,128,158, 3,185,241, 28,232,208,161, + 67,180,127,255,126, 74, 72, 72,160, 89,179,102, 93,189,247,222,123,191,156, 55,111, 94,195,223, 99, 0, 92,188,120,145,190,254, +250,107, 90,185,114, 37,173, 89,179,134, 54,109,218, 68,187,118,237,242,234,229, 11, 64, 39, 8,130, 57, 33, 33,129,102,206,156, + 73, 0,182, 20,215,111,153, 50,101, 10,173, 88,177,130,120,158, 55,163,106,171, 70, 40, 63, 63,255, 22, 5, 85, 81,189, 7,158, + 79,190,255,254,123,178,219,237,212,181,107, 87,103,241, 75, 78, 46, 81, 90,182,111,223,222,102,181, 90, 41, 54, 54,150, 56,142, +251,170,138,215, 46, 50, 80,175,221,169,150,196, 60,181, 36,230, 5,250,251,237, 68, 21,122,254, 37,207,203,100, 50,209,158, 61, +123,168, 73,147, 38,249, 6,131,225, 24,128, 22,183,193,195, 27, 12,134,125, 28,199, 61, 89,178,222, 96, 48,236,225, 56,238,217, +146,117,106,181, 58, 3, 0,169,213,106,143,171, 65, 42,106, 39, 8,194,115, 70,163,113, 71,201, 58,142,227,158, 53, 24, 12,123, + 42,145,113,213,192,129, 3,233,233,167,159, 38,198, 88, 78, 96, 96,160,207, 3,112, 23, 10,128,205, 0,234, 3,216, 89,162,248, +134, 0,124,197,253,128, 60, 59,108,216, 48, 58,122,244, 40, 85,171, 86,141, 80,198,197,126, 59,124,207,117,191,151,148,165,143, + 82,173, 64,245,237,241, 85, 65,169,255, 19,134, 0,202, 51, 0, 30,122,232,161,248, 94,189,122,197,223,123,239,189,159,182,110, +221,122, 88, 86, 86, 86,245,178,115, 3,170,120, 95,232,212,169, 83,180, 98,197, 10,250,241,199, 31, 41, 46, 46,142, 18, 18, 18, +232,224,193,131,222, 42,217,208,186,117,235, 82, 98, 98, 34,117,232,208,129, 0, 60, 81, 92,255, 68,203,150, 45,233,187,239,190, +163,123,238,185,135, 0, 52,247, 86, 38, 89,150, 51, 80,228,114, 38, 89,150, 51, 42,171,247, 32, 27,111, 52, 26,247,156, 60,121, +146,126,250,233, 39, 2, 16, 93,230,247, 9, 75,150, 44,161, 11, 23, 46, 80,112,112,240, 47,101, 95,128,127, 86, 1, 64, 79, 61, +245, 84,161, 70,163,201, 97,140, 61, 5, 47,220,253,127,215, 2,192, 8,224, 75, 20, 77, 12, 13,113,221, 79, 34,159, 7,224,175, + 86,124,145, 0,255,197, 96,140,117,110,218,180,105,194,194,133, 11, 49,124,248,112,156, 59,119,174, 5, 17,221,118, 50, 26,198, + 88,231,255,212, 13, 72,216,255, 70, 87,180,120,107, 43,142, 95,201,175, 58,223,188, 46, 4,252, 22, 2,184,108, 72,224, 91,182, +203,137, 26,248,119, 64,201, 72,128,234,201, 33,199,152,221, 28, 12, 0, 36,104,179, 10,223,187,214,188,178,253,171,146, 13, 80, + 20,197, 12,187,221, 94,238,108,127, 89,150, 51, 11, 11, 11, 61, 70, 7, 44, 94,254, 23, 23, 22, 22,214, 43, 35, 35,227, 23, 0, +157,137,200, 82, 28,104,100, 93, 72, 72,200,131,215,174, 93,219, 6,160, 39,221,133, 23, 10, 99, 44, 84,171,213,206,151, 36,169, +250,205,155, 55,159, 36,162, 83, 37,126, 11, 11, 8, 8,248, 9,128,253,230,205,155,195,136, 40,237,207,150, 15, 0,180, 90,109, +178, 74,165,218,106, 50,153, 38, 19, 81,238,221,144,225,110,129, 49,246, 53,128,209, 21, 61, 26,197,121, 42,254,150,255,227,191, + 50, 24, 99, 77, 1,236, 42, 83, 29, 74, 68, 86,119, 27,159, 1,240,239, 6, 99,108, 71,181,106,213, 34,211,211,211, 55, 2, 24, + 84,242,225,184, 93,190,218,129,234,200,148, 27,133,119,132,239,159,138,191, 91, 58,224, 98, 35,160, 38, 17, 93, 46, 83, 47, 0, +240, 7,112,147,136, 28,229,238,236,195,191, 30,106,181, 58,195, 98,177,220,182, 17,234, 67,213,193, 24,203, 5, 80,234,154, 19, +145,165, 84, 27,159, 1,240,239, 70,113,232,206, 80, 20,101,113,251,221, 47,240, 59,205,231,131, 15, 62,248,224, 67,213,193, 24, +179, 16,145,236,169,141, 47,143,247,191, 28, 68,164, 16, 81,250,157, 82,214,119,154,207, 7, 31,124,240,193,135,219, 66, 23,198, +216, 1, 79, 13,124, 30, 0, 31,124,240,193, 7, 31,124,248,135,129, 49,102, 65, 81, 30,149,146, 80,151, 28, 6,240, 25, 0, 62, +248,224,131, 15, 62,248,240, 47,132,111, 8,192, 7, 31,124,240,193, 7, 31,254, 97, 96,140,229, 48,198, 44, 37,202,127,202,182, +241, 25, 0, 94,130, 49, 22,201, 24,139, 46, 46,145,119, 91, 30, 31,124,184, 91, 96,140, 25, 25, 99,147, 24, 99,171,139,203, 36, +198,152,209,203,125,249,134, 13, 27,158, 27, 53,106, 20, 49,198,110, 41,130, 32, 84,121,238, 8, 99,140,191,239,190,251, 42,228, +148, 36,201,107,206,202,228, 19, 69,209, 55,183,197,135,191, 11, 66, 1,248,149, 40, 91,139,151,238,186, 81,105, 54, 64,198, 24, + 7,160,151, 36, 73,207, 58, 28,142, 30, 60,207,111,183, 90,173, 11, 0,108, 34, 34,167,183,146, 48,198, 66,121,158,111, 28, 20, + 20,212,154, 49,214,220,110,183,215, 22, 4, 33,133,136,142, 93,191,126,253, 23,135,195,241, 43, 17,101, 86,237,252,254, 84, 68, + 42,118,203, 52,112,162, 43, 35,214,206,202,118, 40,190,118, 15,138,162,248,172,195,225,232,206,243,252,118,155,205, 86,229,107, + 87,130, 47, 28,192, 11, 0, 30, 68, 81,132,167,203, 40,138,241,252, 37, 17, 37,221, 6, 95, 43,163,209,248, 10, 99,172,173,201, +100,170,161,211,233,174, 16,209,129,220,220,220,185, 68,116,232, 54,248,218,202,178,252, 18,128,142, 54,155,173,134, 40,138, 41, + 0,118, 91, 44,150,143,111, 39,190, 0, 99,172,163,191,140,151,136,208,222,100, 71,117,131,136, 75,138,130, 61, 57, 54,124, 64, + 68, 39,171,202,231,195,239, 7, 99,172,189,159,159,223,215,131, 6, 13,178,212,170, 85, 43, 92,175,215,163,176,176,176,222,231, +159,127, 62,138, 49,246, 12, 17,237,243,176, 47, 31, 17, 17,113,116,211,166, 77,245, 23, 45, 90,132, 77,155, 54, 65,150,229, 82, +165, 97,195,134, 92, 21,229, 41,197,169, 40, 10, 28, 14, 7,114,115,115,145,147,147,131,220,220, 92,180,110,221,218, 43,206, 63, + 66, 62,192,115, 28,134,178,240,102, 73,220,157,230,243,225,159, 9,215, 18,236,226,116,192, 0,208,190,236,178,236, 10, 13, 0, +198, 88, 35, 73,146,158, 17, 4, 97,164,191,191,127,206,195, 15, 63,124,108,228,200,145,159, 45, 91,182,172,225, 79, 63,253,244, + 73,118,118,182,159, 44,203, 75,173, 86,235, 55, 37, 3,111,148,133, 78,167,139,149, 36,169, 78,131, 6, 13, 76, 13, 26, 52,184, +209,184,113,227,107,237,219,183,191,218,161, 67,135, 19,123,247,238, 13,220,183,111, 95,211, 95,127,253,181,199,217,179,103, 3, + 3, 2, 2,116,133,133,133, 23, 11, 11, 11,123,123, 58, 49,198, 24,253,209,129, 35,138,123,249,145,197,155, 59, 1, 0, 54, 51, + 32, 86,126, 88,198, 88, 35, 81, 20,159,225,121,254,113, 63, 63,191,236, 62,125,250, 28, 12, 12, 12, 92,117,253,250,117,109,108, +108,236, 71, 57, 57, 57,254,146, 36, 45,183,217,108, 95,123,186,118,101, 56,159, 1,240,110,157, 58,117,182, 50,198,110,206,152, + 49,227,149,233,211,167,247,183, 90,173,126,151, 46, 93,218,201, 24,123, 31,192,135,222, 4, 98, 97,140,241, 90,173,246, 93,163, +209, 56,246,141, 55,222,144,219,183,111,207, 26, 54,108,136,164,164,164,240,125,251,246,213,158, 49, 99,198,195, 58,157, 46,198, +108, 54,191,238,205,108,126,198,152, 40, 8,194,251,146, 36,141, 30, 61,122,180,166,113,227,198,144, 36, 9,103,206,156,169,127, +232,208,161,122,187,119,239, 30, 38, 8,194, 7, 14,135, 99,186, 55,134, 15, 99, 76,214, 8,248, 40, 64,198, 19,239, 15, 12,215, +116,104,217, 20,213,131,140, 56,127,254,236,189, 9,135,207,212,159,182, 45,111,168, 90, 96,239, 91, 28,120,155,136,238, 76, 30, + 93, 31, 42, 5, 99,204,232,239,239,255,245, 11, 47,188, 16, 58,106,212,168, 99,213,171, 87,255, 38, 47, 47,111,215,158, 61,123, +238, 91,176, 96,193, 43, 99,198,140,249,154, 49,214,161,162, 64, 55, 17, 17, 17,123,227,226,226, 26,215,170, 85, 11, 0,110, 81, +174,178,236,113,197, 82,185,136,136,136,216,187,105,211, 38, 55,167,221,110, 47,165,252,115,115,189,143,185,243, 71,200, 87, 44, + 83,168,201,100,170, 52,197,113,118,118, 54, 2, 2, 2, 42, 85,236,229,241, 93,188,120, 17, 75,151, 46,197,164, 73,147,220,245, +233,233,233,168, 94,189,122, 85,210, 61,251,240, 15,132, 75, 87, 22, 15, 3,248,149,156, 4, 88,174, 1, 32, 73,210, 94,181, 90, +221,160, 75,151, 46,199,198,142, 29,187, 48, 42, 42,234,154,235,183, 46, 93,186,236, 91,176, 96,193,190, 13, 27, 54,132,196,196, +196,180, 78, 72, 72, 72, 16, 69, 49,201,102,179,117, 44,143,203,108, 54, 63,180, 99,199,142, 73,178, 44, 91, 67, 67, 67,109, 70, +163, 81,148, 36, 73, 2,128,254,253,251,103,116,234,212,233,242,209,232, 94,155,111, 0, 0, 32, 0, 73, 68, 65, 84,163, 71,149, + 67,135, 14,105,114,115,115, 53, 51,103,206,140,246,116, 50,140, 49,106,211,166,141, 77, 20,197,249,118,187,253,249, 59,169, 0, +130,131,131, 35, 29, 14, 71,164,205,102, 3,199,113,145,246, 19, 63,117,133,168,131,170,126, 87, 0,216,169,210, 6,186,154,238, +172,136, 67, 16,132, 95, 69, 81,188,167, 99,199,142,251,198,142, 29,251,217,192,129, 3, 51, 0, 96,233,210,165, 53,159,120,226, +137, 84, 0, 9,107,214,172, 9,139,137,137,105,183,103,207,158,189, 60,207, 95,117, 56, 28,141, 60,201,197, 24,123,158,231,249, +177,203,151, 47,159,177, 99,199,142,250,109,218,180, 57,254,216, 99,143,101, 7, 5, 5,173,255,250,235,175, 91,124,245,213, 87, +111,244,237,219,247, 57,187,221, 46, 0,152, 93,217,121,106,181,218,119, 27, 53,106, 52,118,221,186,117,234,106,213,126,139, 71, + 19, 20, 20,132,142, 29, 59,178, 17, 35, 70,168,251,247,239, 63,246,212,169, 83, 0,240,106,101,124,146, 36,125,212,172, 89,179, + 81,243,230,205, 83,135,135,135, 67,163,209, 32, 53, 53, 21,181,106,213, 66,211,166, 77, 89,203,150, 45, 53, 43, 86,172,152,144, +149,149, 5, 0,111, 85,198,167, 23,241,101,183, 58,226,208, 85,115, 39,105,212,247, 15, 6, 76,153, 64, 94, 58, 26,132, 54,196, + 21,125, 11, 54,219,184, 77,187, 96, 71,242,203,167,110,192, 1, 96, 70,101,124, 62,220, 49, 60, 59,120,240, 96,203,200,145, 35, +143,214,171, 87,175, 7,128, 43,106,181, 90,172, 89,179,230,183,215,175, 95,215,126,250,233,167,253, 6, 12, 24,240, 44,128,247, +203,219,185, 93,187,118,109, 22, 47, 94, 12, 0, 56,118,236, 24,122,247,238, 13,181, 90,125,139,146, 45,209, 99, 1, 0,168, 84, + 42,167,211,233, 44,247, 93,213,174, 93,187, 54,139, 22, 45, 2, 0,156, 58,117, 10, 57, 57, 57,165,148,127, 85, 12, 0,111,228, +187, 93,104,181, 90,172, 91,183, 14,162, 40,186,139, 36, 73,165,182, 69, 81,252, 93,124,174,250,173, 91,183,194,223,223, 31,126, +126,126,183, 45,239,157,132, 44,203,155,172, 86,235, 59, 68,180,251,110,203,242,111, 66, 57,171, 0,218,123, 21, 8,136, 49, 70, +137,137,137,255, 11, 15, 15, 47, 12, 12, 12,212,170,138,125,222, 37, 97,179,217,148,163, 71,143, 90,183,108,217,226,247,198, 27, +111,188, 91, 81,143,188,152,107, 82,201, 58, 89,150,173,249,249,249,214, 13, 27, 54,248, 93,191,126, 93, 35,203,178,251, 33,158, + 57,115,102,180, 39,174, 58,117,234,216, 15, 30, 60, 40,108,223,190, 29,143, 63,254,248,122,155,205, 54,224, 78, 25, 1,245,234, +213,139, 62,191,224,191,211, 32,106, 17,248,240,155,184,177, 99, 62, 32,106,161,106,212, 39, 30,197,201, 20,136,104,167, 39, 14, +198, 24,133,135,135,239, 55,153, 76,134,145, 35, 71,238,152, 51,103,206, 9, 65, 16, 40, 54, 54, 54,184,119,239,222, 89,118,187, +157,189,250,234,171, 77,151, 44, 89,210,141,227,184,188,172,172,172,118,158,188, 25,197,110,255, 95, 22, 45, 90, 52,253,169,167, +158,186,254,208, 67, 15,245, 95,180,104, 81,108,181,106,213,108, 0,208,173, 91,183, 33, 63,255,252,243,247,235,214,173,211,143, + 24, 49,226, 29, 0,221,137,232, 87, 15,124,173,140, 70,227,174,211,167, 79,151, 82,254, 37, 97, 50,153,112,238,220, 57,116,239, +222,189, 48, 39, 39,167,179,167,225, 0,198, 88, 39,181, 90,189, 41, 62, 62, 94,211,184,113, 99, 40,138,130,180,180, 52, 92,185, +114, 5, 38,147, 9,102,179, 25, 55,110,220, 64,114,114, 50,190,248,226,139, 2,155,205,214,193,211,112, 0, 99,236,161, 48, 13, +190, 79, 89, 51, 67, 43, 52,238,139,244,140,116, 4,217,211, 33,154,174, 98,198,150,116, 28, 57,159,142,171, 87,175,226, 49,255, + 83,120,115, 91, 94, 65,158, 13,237,137,232,120, 69,124, 62,220, 57, 48,198, 86,207,152, 49,163,199,132, 9, 19,190,210,104, 52, +181, 0,172, 63,127,254,252,217,123,239,189,247,202,200,145, 35,235, 70, 71, 71,199,213,171, 87,111, 11, 17, 13,171, 96,127,218, +180,105, 83,185, 74,223, 85,158,124,242, 73,188,240,194, 11,144, 36, 9,178, 44, 67,146, 36, 52,111,222,188,194, 80,177,140, 49, + 82, 20, 5, 86,171,181, 84,207,255,218,181,107, 56,114,228, 8,146,147,147,177,100,201, 18,160, 40, 46,253, 91,158, 66, 1,123, + 35,159,193, 96,168,114,216,218, 98,143, 37, 24, 99, 80,169, 84, 16, 4, 1,162, 40, 66, 16, 4, 8,130,224, 54, 4,118,237,218, +133,106,213,170, 85,202, 95,146,143,231,121,240, 60,143,248,248,120,196,198,198, 98,218,180,105,240,243,243,131, 32, 8, 56,122, +244, 40,106,212,168,113,215,195,236, 22,207,195, 48, 89,173,214,222, 62, 35,224,207, 67,241,120,127,201,123,111, 45,235, 33,246, + 52, 7,128,191,116,233,146,254,242,229,203,206,106,213,170,229, 7, 7, 7,203,130, 32, 8,102,179,217,177,125,251,118,231,174, + 93,187,140, 68,100,168,138,213,234,130,197, 98,145,142, 29, 59, 70, 87,175, 94,213, 84,101,127, 34, 98, 28,199,173,120,249,229, +151,135,207,158, 61, 27,203,151, 47,239, 55,124,248,112,103, 81,148,210,210,144, 36, 41,211, 98,177,120, 28,251,170, 83,167, 78, +164, 40,138,145,162, 40,130,231,249,157, 6,131,161,200,205, 15,192, 96, 48,196,135,245,122,113,167,217,108,142, 84, 78,109,236, + 10, 81,219,213,229, 9,168, 76,206, 85,171, 86, 45, 58,120,240, 96,224, 87, 95,125,213,125,225,194,133,189,163,162,162,118, 14, + 31, 62,252,226,136, 17, 35,218,174, 95,191, 62, 82,175,215, 95,232,222,189,251,242,134, 13, 27,222,120,247,221,119,219, 85, 66, + 55,186,110,221,186,235,134, 12, 25,146,125,237,218, 53,193,108, 54,171, 11, 10, 10, 84, 73, 73, 73, 26,158,231, 21,171,213,202, +159, 58,117, 74, 8, 9, 9, 41,168, 93,187,246,234,148,148,148,241, 0,158,171,136,204,104, 52,190,242,198, 27,111,200,158,148, +255,141, 27, 55, 0, 0, 47,189,244,146, 28, 19, 19,243, 10,128, 71, 43,226,147,101,249,141,241,227,199,107,106,212,168, 1,198, + 24, 78,158, 60,233, 86,252,102,179, 25, 38,147, 9,118,187, 29, 70,163, 17,157, 58,117, 82,239,222,189,123, 50,128, 17, 21,241, + 5,170,241,230,146,209,205,181, 98,147,190,184,113, 45, 3,155, 79,100,160,153,148,142,251,229, 12,164, 93,205, 64,122,122, 58, + 50, 50, 50, 80,171,186, 5, 83,219, 66, 61,243, 0, 38, 0, 24, 85,201, 53,244,225, 14,193, 96, 48, 32, 55, 55, 55, 94,163,209, +232, 79,159, 62,125,161, 81,163, 70,105, 0, 12,249,249,249, 58,131,193, 80,233,254,101,149,107,131, 6, 13, 0, 0,121,121,121, +144,101, 25,122,189, 30,106,181, 26,146, 36,185, 75,101,176, 88, 44,238,222,126, 78, 78, 14,126,254,249,103, 68, 70, 70, 98,252, +248,241,208,235,245,152, 49, 99, 6, 18, 18, 18,250,141, 26, 53,106, 8, 99,236, 49, 34,218,232,173,124,119, 98, 8,192,133,109, +219,182,121,236,253, 87,245, 93, 90,150,207,133, 45, 91,182,192,207,207,207,171,107,247,103, 97,241,226,197,186, 81,163, 70,197, + 50,198,124, 70,192,159,135,251, 0, 28, 41,177,221, 30,192,254,146, 13, 42,157, 4,168, 40, 10,151,150,150,166, 47, 78,225,152, +183,110,221,186,106, 42,149,138,185,122,237,127, 54, 20, 69, 25,185,116,233,210,225, 42,149, 10,211,167, 79,199,119,223,125,135, +188,188, 60, 84,175, 94, 29, 54,155, 13,138,162, 64,146, 36,244,234,213, 43,212,229, 74,172,104, 34,140, 74,165,138, 60, 51, 49, +124, 26, 68, 29,186, 44,188, 22,169, 82,169,208,229,221,237,176, 90,173,208,235,245, 16, 4, 97,167, 74,165, 2,108,230,174, 85, +149,179, 77,155, 54, 55,218,180,105,243,221,165, 75,151,180,159,126,250,105,151, 65,131, 6, 61, 28, 26, 26,186,167,119,239,222, +159,133,133,133,153, 5, 65,240,150,170, 93, 68, 68,196,185, 53,107,214,132,133,133,133, 89, 20, 69, 97, 26,141, 70,241,243,243, +179,153,205,102,178,219,237,202,175,191,254, 42, 95,188,120, 81, 14, 13, 13, 53,167,164,164,120,148,149, 49,214,182,125,251,246, +229,246, 8, 92,202,255,198,141, 27,184,121,243, 38, 66, 66, 66, 24, 99,172,173, 39, 62, 34,106,217,164, 73, 19, 20, 22, 22,194, +100, 50,185, 75, 65, 65,129,251,187,217,108,134,162, 40,168, 81,163, 6, 83,169, 84, 30, 13, 30,179, 29,205,255,211,166, 13,144, +159, 9,131, 45, 3,247,114,233,168,175,202, 0,242, 50,240,106, 68, 58, 98,173, 25,168, 89, 35, 29, 81, 53,109,216, 45,128,113, + 42,116,170,252, 18,250,112,135,144, 88, 80, 80, 80, 47, 49, 49,241,126,142,227, 86, 62,250,232,163, 54, 0, 6, 0,250,113,227, +198, 13,206,200,200,184, 4, 32,209, 19, 65, 89,133,154,149,149,229, 86,252,138,162, 64,167,211,185,123,254,222, 26, 0,174, 94, +127, 78, 78, 14,214,173, 91,135, 9, 19, 38,192,110,183,227,232,209,163, 88,184,112, 33, 94,124,241, 69,180,111,223, 62,248,151, + 95,126, 73,111,213,170,213, 42,198, 88, 99, 34, 74,245, 70,190,146, 6, 1,199, 85,121,254, 95, 41,244,237,219,215,221,243, 47, +105, 0,184,206,115,199,142, 29, 85,226, 27, 58,116, 40,120,158,135, 40,138,216,188,121,179,187,254,145, 71, 30,129, 40,138, 56, +120,240, 96,165, 28,197,238,249, 94,149,181, 51, 24, 12,155,115,115,115, 31,172,146,128, 37,240,232,163,143, 34, 53, 53, 85, 55, +109,218, 52,159, 17,240,231, 97,127, 73,239, 79,121,115, 0,188, 94, 6,168, 40, 10,187,114,229,138,232,112, 56,238,170, 59,169, + 56,212, 44,250,247,239,143,169, 83,167,162, 89,179,102, 56,122,244, 40,178,178,178, 96,179,217,208,119,125, 63,200,178,140,240, +240,112,252,250,235,175,184,116,233, 18, 42, 74, 66, 81,172,220, 1,155, 25,106,181,186,235,206,255,214,238,154, 48,190, 9, 14, +188,209, 5,199,231, 14,238,170,209,104, 34,117, 58,221,206,208,158, 47,196,107, 90, 14, 2,128,200,170, 46, 1, 12, 15, 15, 55, +127,248,225,135,177, 60,207,231,245,236,217,115,163,191,191,191,185,138,167,220,188,109,219,182, 87, 70,142, 28,153,214,179,103, +207, 27,146, 36,217,170, 85,171,102,179, 88, 44, 74,118,118, 54, 41,138,226,244,243,243,203,175, 89,179,102, 86,189,122,245, 82, + 0, 68,120, 34, 51,153, 76, 53, 26, 54,108,120, 75,125,126,126, 62,174, 95,191,142,235,215,175,187,141, 0,198, 24, 76, 38, 83, +141,138,184, 24, 99,178,205,102, 11, 84,171,213,200,204,204, 68, 74, 74,138, 91,225,151, 84,254, 54,155, 13, 64,209, 28, 3,155, +205, 86,203, 3, 95,136, 66, 16,141,254, 1, 64,126, 6, 4, 83, 58, 58,232, 51,160,183,102, 0,249,233,168,205, 50,240,124,157, +116, 68,213, 44,154,200, 26, 17, 0,228,219, 80,219,187,203,232,195,239, 65,113,210,159,196,181,107,215, 54,230, 56,238,109,158, +231,159,238,215,175, 95,221,129, 3, 7,214,217,186,117,235,232,142, 29, 59, 62, 50,116,232, 80, 17,192, 2, 79, 60, 46,165,234, + 42,193,193,193,208,235,245,238,223,245,122,125, 41,229,171, 86,171, 43,149, 45, 39, 39, 7,217,217,217,184,124,249, 50,122,246, +236, 9,135,195,129, 35, 71,142,192,102,179, 97,217,178,101, 80, 20, 5, 38,147, 9, 6,131,161, 90,116,116,116, 38,128,143,189, +149,175,172,242,215,233,116,184,221, 37,134,241,241,241,136,143,143,199,174, 93,187,144,144,144,224, 46,241,241,241,216,185,115, +103,149,123,236,113,113,113,216,188,121, 51,182,108,217, 82,106,223,216,216, 88, 36, 36, 36,120,197,103,181, 90,223,145, 36,201, +244,237,183,223,150,155, 46,246,240,225,195,208,235,245,166,188,188,188,119,170, 36, 92, 57,104,215,174, 29, 98, 98, 98,116, 26, +141, 38,150, 49,230, 51,220,255, 2,168,212, 3,240, 87, 69,189,122,245, 96, 54,155,241,194, 11, 47,160,101,203,150,176,217,108, +168, 93,187, 54, 18, 70,196, 67, 45,203,120,234,169,167,112,248,240, 97,104, 52,154, 10, 57, 20, 69, 41,118,249, 51,112,156, 14, +176,150,212,205, 12, 26,141, 38, 82, 81, 20,216,237,118,100,110,120, 31,144,180, 93, 85,205,135, 68,194,139, 97, 0, 23,178,178, +178,164,220,220, 92, 1, 0,179,217,108,124,177,135,162, 42,107,137,207, 45, 92,184,176, 79,163, 70,141,126, 24, 50,100, 72, 6, + 80, 52, 91,248,250,245,235,200,204,204,132,205,102, 99,153,153,153,216,179,103, 79,112,108,108,108,127, 20, 45, 13,172, 16, 58, +157,238, 74, 82, 82, 82,120, 80, 80,144,187, 46, 63, 63,223,221,235,191,121,243,102, 41, 47,128, 78,167,187, 82, 17, 23, 17, 89, + 68, 81,204, 61,127,254,188,191,193, 96,184,197,245, 95, 82,249,187,228, 22, 4,225,170, 7,241,178, 24, 96,207,185,146, 36,248, +107, 2,144,153,153,129, 95,206,102,160, 33,151,142,122,170, 12, 32, 47, 29,112, 20, 25,175, 38, 59,240,235, 13, 64, 39,160, 66, +249,124,184, 51, 96,140,133,183,108,217, 50, 97,244,232,209, 53, 51, 50, 50, 48,117,234, 84,203,236,217,179, 31,158, 51,103,206, +120,189, 94,143,180,180,180, 75,205,155, 55,207, 56,115,230,204, 51,149,165,186, 45,169, 84,131,131,131, 97,183,219,193,113,156, +107,105, 45,230,204,153,131, 57,115,230,184,219,231,229,229, 85, 42, 95,118,118, 54,114,115,115,241,203, 47,191, 96,234,212,169, + 56,121,242,164,251, 24, 42,149, 10,146, 36, 65,173, 86, 67,165, 82, 97,216,176, 97,120,253,245,215, 59,123, 35, 95,121, 61,255, +167,159,126, 26,227,199,143,119,247,218,131,131,131,189,118, 11,244,235,215,207,221,243, 47,249,233, 58,206,198,141, 21,142, 76, +148,139,199, 31,127,220,237, 69, 88,183,110, 93,169,122, 89,150,145,144,144, 80, 41, 7, 17,237,102,140,245, 30, 53,106, 84,108, +106,106,170,174, 93,187,118,208,235,245,208,235,245, 56,117,234, 20, 70,140, 24, 97,202,207,207,191, 35, 61,118,189, 94,143,206, +157, 59, 99,242,228,201,186, 15, 62,248, 96, 9,128,122,191,151,211, 7,143,176, 50,198, 74,142, 91,217, 0,120, 61, 7,224, 47, + 13,139,197,130, 26, 53,106, 32, 56, 56, 24, 33, 33, 33,240,243,243,131,191,191, 63,242,243,243, 33,203, 50,190,254,250,107, 12, + 25, 50,196,163, 1,224,112, 56, 0, 91, 1, 0, 6,167, 83,141, 33, 63, 3,122,189, 10,118,123, 30,242,243,211,176,119, 74,167, +174,144,180, 93, 27,188,180,194, 61, 55,192, 75,217, 84,135, 14, 29, 10, 74, 75, 75,211,235,116, 58, 91,227,198,141,111, 48,198, +200,233,116,178,156,156, 28, 67, 70, 70,134,100, 52, 26, 11,195,195,195,189,153,162, 28, 47, 8, 66,216,218,181,107, 35,230,205, +155,215,233,244,233,211,141,122,247,238, 13,187,221, 14,155,205,134,212,212,212,251,222,123,239,189, 65,130, 32,220, 80, 20,229, + 87, 0, 41,158,200,136,232,192,190,125,251,106,119,236,216,145, 1, 69, 47,216,146, 74,223, 85,172, 86, 43,242,242,242,136,136, + 60, 38,147,224, 56,238,232,129, 3, 7,186,213,170, 85, 11, 78,167,179, 92,229, 31, 24, 24, 8,171,213,138,171, 87,175, 2, 30, + 92,196, 68, 68,193, 26,118,242,224,225, 99,255,233, 20, 92, 7, 83, 55,102,224, 92, 74, 58, 50,210, 51,240,115,143,116,220,171, + 45, 4, 0, 36,243,245, 48,244, 39, 11,114,179,210, 0,134, 61, 94, 92, 67, 0, 0, 99,172,155, 94,196,130,124, 27, 70, 84,118, + 94, 62, 20,129, 49, 22,222,170, 85,171,189, 59,119,238,172,118,238,220, 57, 76,154, 52, 9, 39, 78,156,232, 23, 21, 21,213, 2, +128, 43,178, 88, 34,128, 5,222,228,185, 47,169, 88,237,118, 59,202, 14,133,125,252,241,199, 24, 58,116, 40, 36, 73, 66, 80, 80, +144, 87,227,238,174, 33,128,228,228,100,136,162, 8,167,211,137,103,158,121, 6, 41, 41, 41, 48, 26,141,165,148,186,191,191,127, + 24, 0, 45, 99, 76, 42, 47, 85,181, 39,229, 15,252,102, 32,120, 59, 60, 81, 18,174, 94,126,121, 99,255,229,204,179,174, 20,235, +214,173, 43,197,231,194,250,245,235,171,180, 2,192,101, 4, 76,155, 54, 45, 54, 38, 38, 70,215,185,115,103,156, 60,121, 18,143, + 63,254,184,201,100, 50,221, 49,119,189, 94,175,199,201,147, 39,241,254,251,239,155, 76, 38,211,147,119,130,211, 7,143,232, 10, +160,176,196,182,247,113, 0,238, 20, 84, 42, 85,238, 59,239,188,211,254,245,215, 95,223,175, 82,169, 60,173, 81,103,113,113,113, +173,138,115, 24, 87, 10,215, 56,189,193, 96,128,209,104,132,193, 96,128, 94,175,135,221,110,135, 44,203,184,114,229, 10, 62,254, +184,200,211,167, 86,171,203, 13, 48,100,177, 88, 0, 91,209,178,244, 77, 15, 2, 16, 11, 1,169, 0, 16,181,120,248, 7, 42, 82, +250, 12,224,121, 62,190,214,163, 51,119, 22,247, 70,118, 86, 38,219,204,153, 51,187,134,135,135,103,182,107,215,238, 74,163, 70, +141, 92, 93, 24, 69,173, 86,219, 13, 6,195, 13,179,217,172, 77, 79, 79, 15, 77, 78, 78,174,239,197,169, 46, 57,127,254,252,158, +217,179,103, 71,119,237,218,245, 70,255,254,253, 7,188,242,202, 43, 27,156, 78,167,253,250,245,235,152, 61,123,182, 42, 42, 42, +234,199,211,167, 79,139, 73, 73, 73,179, 1,244,245, 68,150,155,155, 59,119,198,140, 25, 15,143, 24, 49, 66,173,213,106,221, 61, +253,235,215,175,187, 13, 1,171,213, 10, 34,194,162, 69,139,172,185,185,185,115, 61,241, 89, 44,150,247, 55,111,222,220,182, 73, +147, 38,154,208,208, 80, 88, 44,150, 82,202, 95,173, 86,195,223,223, 31,103,206,156, 65,124,124,124,129,213,106,253,196, 19,223, +245, 66,188,247,220,255, 93, 90,114,184,254,126,237,149,171, 34, 50, 50, 50,144,158,145,129,180,155, 5,184, 87, 11, 64,237,135, +237, 57,245,112, 46,125, 15,172,133,112, 58, 20,196,120,113, 13,193, 24,139, 12,210,139, 63, 45,125,117,168,110,216,244,149, 91, + 24, 99, 15,122, 10, 90,227, 67,105,229,127,241,226, 69, 44, 95,190, 28,123,247,238, 77, 34,162,173, 0,182,222, 14,167,203,197, + 46, 73, 18, 56,142, 43,242,194,149,128,107, 14, 64, 96, 96,160,219, 59, 80, 25, 92, 6,128, 70,163, 65,122,122, 58,244,122, 61, +126,248,225, 7,183, 18, 47,217,203,182, 90,173,233, 0, 2,202, 83,254,229,201, 87, 22, 26,141,230,182, 12,128, 27, 55,110,220, + 81,229, 95, 30, 31, 80,228, 13,185, 29,227,196,101, 4,140, 27, 55, 46,118,242,228,201,186, 98, 37,125, 71,199,234, 79,157, 58, +117,199,141, 10, 31, 60,226, 24, 0,137,136,108,140, 49, 17,128,189,108,131,114, 13, 0,158,231,143,247,233,211,231,217,255,254, +247,191,155,251,247,239,127, 75,143,210,245,192,254,250,235,175, 53,119,239,222,221, 69,165, 82,157,168, 72, 2, 69, 81, 90,197, +197,197, 45, 77, 76, 76, 28, 61,109,218,180, 53,173, 91,183,190, 81,150, 43, 61, 61,221,127,211,166, 77,189, 11, 10, 10,110, 16, + 81, 43,111,206,172,160,160, 0, 45, 91,182, 68, 80, 80, 16, 2, 2, 2, 96, 52, 26,161,209,104, 80, 80, 80,224,238, 53, 84,182, +252,165,160,160, 0,176,149,185, 4,197, 43, 10, 44, 22, 7,186,126,122, 18,133,133,110, 3,106,103,110,110,238,206,202,228,226, +121,254,232,254,253,251,255, 19, 17, 17,241, 99, 9,229,239,134, 74,165, 66, 64, 64,128, 57, 53, 53,149, 59,121,242,100, 55,149, + 74,117,164, 60, 30, 23,136, 40,137, 49, 54,235,209, 71, 31,125,234,171,175,190,250, 34, 32, 32, 32,115,219,182,109,161,247,221, +119,223,149, 35, 71,142, 24, 25, 99,249, 73, 73, 73,234,109,219,182, 61, 14,224,235,202, 34,248, 17,209, 33,157, 78, 23,211,191, +127,255,177, 95,124,241,133,154,136, 74,245,252,109, 54, 27,108, 54, 27,214,174, 93,107,177, 90,173,159,122,193,183, 81,150,229, +141,171, 87,175,126,120,192,128, 1,162, 36, 73,112, 58,139,140, 42,163,209,136,192,192, 64, 92,185,114, 5,171, 87,175, 46,116, + 58,157, 75, 43,251,227, 19,209, 15, 70,153,141, 28,191,244,224, 67,111,117, 8,150,190, 47, 52,163, 69, 61, 19, 34,107, 2, 48, + 84, 7, 66,239, 67,245,171,103, 32, 57,205, 78, 39,135, 37,118, 39,121,156,116, 6, 0,140,177, 46, 65,122,113,253,217, 29,223, +233,252,145,143,159, 46,108,215,247, 95,158,185,185,216, 8,216, 91,217,254,255, 86,220,115,207, 61, 49,241,241,241,213, 46, 94, +188,136, 37, 75,150,224,203, 47,191,188, 98,177, 88, 30,186, 93, 62, 89,150,157,101, 93,230, 70,163, 17,175,189,246, 26,180, 90, + 45,116, 58, 29, 66, 66, 66, 16, 24, 24, 8,167,211,137,242, 86,247,148,199, 57, 98,196, 8, 55,103, 68, 68, 4, 30,123,236, 49, + 20, 22, 22,222,210,155,151, 36, 9,223,124,243,141, 19, 40,223,107, 36,138,226, 45,242,185, 96, 48, 24, 48, 97,194, 4,132,133, +133,185, 13, 4,111,228, 3, 0,142,227,148,160,160, 32,175,180, 60,207,243,149, 46,105,246,196, 23, 29, 29, 93,101, 62, 23, 92, + 70,192, 7, 31,124,176,196,100, 50, 61,121, 39,149,244,145, 35, 71, 48, 98,196, 8,159,242,255,115,209, 6, 64, 12,128,182, 0, +126, 70, 81,204,148, 82,227, 66, 21,197, 1,224, 0, 60,197,113,220, 59,247,220,115, 79,250,132, 9, 19,182,118,236,216,241,218, +161, 67,135, 44, 7, 14, 28, 8,202,202,202, 10,218,183,111, 95,151,156,156,156, 16, 69, 81, 94, 7,176,196, 83,132, 55,198, 24, + 83,169, 84, 99, 85, 42, 85,244,131, 15, 62,184,227,205, 55,223,220,119,248,240,225,194,196,196,196,224, 3, 7, 14,180, 78, 74, + 74,234, 0, 32, 90, 81,148, 24,111, 34,217,121, 19, 10,211,155, 16,152, 28,199, 69, 59, 38,112,211, 32,105, 1,209, 85,116, 40, +189,173, 5, 36, 29,106,253,239,167,233,169,169,169,209,149,201,198, 24, 83, 1, 24,206,113,220,172,144,144,144,204,151, 94,122, +105,125,143, 30, 61,210, 31,120,224,129, 73,195,134, 13,123,255,202,149, 43,213,246,239,223,223,207,100, 50,133, 42,138, 50, 5, +192,138,202,206,153, 21,189,105, 94, 6,240, 74,104,104,232, 26,198, 88,173,126,253,250,173,254,254,251,239,135,216,237,246, 52, +147,201, 20, 5, 96, 17,128,233, 94, 70,238,227,181, 90,237,187,162, 40,142,125,225,133, 23,228,160,160, 32,166, 82,169, 92, 65, + 84,104,241,226,197, 22,155,205, 86,149, 72,128, 6, 73,146, 22, 11,130,240, 96,207,158, 61, 53, 53,107,214,132,193, 96, 64, 94, + 94, 30,210,210,210, 16, 23, 23,103,182,219,237,171,109, 54,219, 11,101, 3, 81, 84,196,103, 20,241,141, 70, 64,159,217,157,161, +233, 80, 29,168, 99, 4,146,178,129, 61, 87, 25,166, 36,144,217,234,196, 34,147, 29, 19,137,232, 22,171,182, 12, 87,231, 64,157, +184,241,236,206,239,116, 1,156, 5,244,243, 20, 64,109, 68,194, 85, 21,250,125,126, 44, 63,223,226,232, 77, 68, 94, 15, 35,252, +155,208,180,105,211, 43, 11, 22, 44,184,231,135, 31,126,192,231,159,127,126,165,160,160,160, 51, 17, 93,186,147,199, 96,140, 81, + 74, 74,138,187,151, 94,214,117,173, 40, 10, 84, 42,149, 87,107,217, 25, 99,213, 56,142, 59,189,111,223,190,220,144,144,144, 90, + 60,207,151, 50, 0, 50, 51, 51, 79,215,174, 93,187,134,195,225,104, 65, 68, 23,170, 42,103, 78, 78,206, 45,189,107,111,100, 83, + 75, 2,165,127,251, 50,230, 30, 42,154,235,224, 42,174,184, 0, 37,203,171,175,190,250,167,243,253,209, 96,140,145, 94,175,191, + 99,115, 9,124,240, 14,140, 49, 11, 17,201, 37,183, 1,148, 90, 5, 80,238,204, 79, 87, 1, 32,171, 84,170, 87, 56,142,187,209, +168, 81,163,221, 79, 62,249,228,236,144,144,144,253,140,177,155,140,177, 87, 0,200,158,246, 47,135,175,158, 32, 8,123,130,131, +131, 79, 15, 30, 60,248, 19,157, 78,119,150,227,184,189, 0,234, 85,133,231, 78, 21, 0,209,202, 4,144, 50, 73, 32,101,170, 31, + 41,209, 53, 72,153,217,144,148, 15, 90,146, 18,211,153,148,175,122,147,178,104, 8, 41, 43,159,164,144,144,144,232, 42,114,139, + 42,149,106, 34,199,113,215, 27, 52,104,176, 67,173, 86,167, 4, 4, 4,236, 96,140, 93,103,140, 77, 0, 32,222,134,188,141, 1, +204, 7,112, 1, 69,238,156, 43, 40, 82,252,173,110,243,252, 91, 25,141,198, 85,126,126,126, 23,121,158,183,251,249,249, 93, 52, + 26,141,171,126, 7, 95, 63,181, 90,189,135,231,249, 60,142,227,108,130, 32,228,200,178, 28, 15,160,199,109,242, 69,249,203,216, +161,229,145,205, 49, 56,117, 2,174,249,203,136, 3,208,206, 91, 14,145,131,249,236,151, 79, 19, 29, 90, 73,202,219,225,164,204, +109, 78,202,188,110,164, 44, 26, 76,241,211,251,145,200,115,230,187,241,236,253, 29, 10,128, 1,254,254,254,167, 4, 65,216, 13, + 32,252, 15, 58, 6,101,102,102, 82,110,110, 46, 89, 44, 22, 82, 20,229,150, 82,244,154,242,154,175, 15,199,113,121,111,189,245, + 86,242,249,243,231,147, 77, 38,147, 41, 43, 43,235,252,135, 31,126,152,196,243,124, 62,128, 71,110, 87,206,242,228,243, 70, 54, + 65, 16, 50, 80, 52,249,170,210, 34, 8, 66,198,159,205,247, 71, 23,131,193,176, 9, 64,167,187, 45,199,191,173, 0,176,148,221, + 46,171,179,203,245, 0,148, 99, 73, 24, 57,142,155, 66, 68, 79, 19,209, 66, 34,154, 69, 94, 76,248,169,128,139,169, 84,170,177, +140,177,201, 68,244,158,183,189,254, 63, 2, 37,227,253,203,178, 12,141, 70,131,226,160, 64,238, 97, 14, 87,114, 17,139,197,178, + 51, 59, 59,123,231,109, 28,195,192,113,220, 20, 69, 81, 94, 4,240, 25, 17,205, 38,162,202,167, 54,255,205,193, 24, 51,222,238, + 51, 82, 1,159, 76, 94,120, 15,202, 66,195,179,140, 66, 39, 42,244, 22,169, 37, 62,179,192, 98,247, 37, 75,185, 75,144,101,217, + 97,181, 90, 61, 14,244, 27, 12, 6,103,110,110,174,215,243,149, 24, 99, 53, 81, 20,142,184, 43,128, 16, 0,215, 1,236, 5, 48, +137,136,206,223,142,156,106,181,218, 97,177, 88,110,145, 83,175,215, 59,243,242,242,254,182,147,169,125,248,231,162,120, 62, 93, +201,119,223, 53, 0,193, 84, 98,254,139, 87, 6,128, 15, 62,248,224,195,223, 17, 21,205,246,247,193,135,127, 58, 24, 99,205, 80, +122,213, 85, 23,162,210,115,166,124, 6,128, 15, 62,248,224,131, 15, 62,252, 11,225,115, 93,249,224,131, 15, 62,248,224,195, 63, + 12,140,177, 8, 0,107,203, 84, 55, 35, 34,119,116, 54,159, 7,192, 7, 31,124,240,193, 7, 31,254, 97, 96,140,101, 1,184, 23, + 64, 54,128, 48, 20, 5,137,187,189, 92, 0, 62,248,224,131, 15, 62,248,224,195,223, 6,122, 34,202, 41,254, 94,238,132,108,159, + 1,224,131, 15, 62,248,224,131, 15,255, 66,252,237,230, 0, 20, 39, 55,144, 81,180,198,177,202,203,194,254,104, 48,198,196,136, +136,136, 61,233,233,233,173,115,115,111, 53,186, 84, 42,149,211,233,116,254,237,174,251,159,137,216, 3,231, 13, 38,107, 65,164, + 10,202,105, 5,170,251, 42,250,228,121,236, 31,216,161,217, 53, 79, 92,174,251,209,174, 93,187,214,139, 23, 47,190,229,119,223, +253,248,123,131, 49, 22,202, 24,155, 13,224, 49, 34,146, 84, 42,149, 35, 44, 44,108,119,126,126,254,211,121,121,121, 23,239,182, +124, 62,248,112, 23, 97, 44,254,108, 14, 32, 7, 64,175,178, 58,211,227,139,175, 56,126,112, 31, 0, 35, 0,116, 64,209, 90,218, + 21, 0, 54,150,156, 72,224, 9,222, 68,237, 43, 11, 73,146, 50, 45, 22, 75,185,107,179, 37, 73,186,234, 39, 65,147, 99, 69, 1, +128,128,170,240,254,209, 96,140,137, 13, 27, 54,220, 27, 23, 23,215, 42, 60, 60, 28, 27, 54,108,112, 71, 56,115, 69, 16,107,214, +172, 89,149,146,138, 75,146,148, 97,179,217,170,116,253,188,137,130, 88, 44,175, 31,207,243,147, 69, 81,236,238,112, 56,154, 0, + 32, 81, 20, 79, 88, 44,150,109, 14,135, 99,174, 55,241, 10, 24, 99,181,136,232, 50, 99, 44, 28, 69,217,166, 42,130,158,138,194, + 26,223, 71, 68,167, 61,113,102,228,230,126, 13,162,186,149, 29,155, 24,142, 2,120,198,131,108,238,251,177,120,241,226, 59,114, + 63, 60, 28,235, 29, 0,143, 1,200, 2, 48,159,136, 22,221, 9,222,170, 64,148,164, 12,187,135,103,197,211,255,170, 42, 96,140, +253, 12, 32,170,120,115, 3, 17,121,204, 63,225,129,199,143,231,249,201,146, 36,117,183,219,237, 77, 0,144, 36, 73, 39, 10, 11, + 11,189,126,254, 0, 76,235,214,173, 91,255, 37, 75,150, 72, 28,199, 33,245,215, 68,254,163,143, 62,142, 76, 75,187,178,139, 38, +178, 71, 1, 92,100, 31, 82,218,237,200,231,131, 15,127,115, 52,100,140, 37, 2, 80, 3,240, 3,112,203,114,216, 91, 12,128,226, +176,179,157, 0,140, 80,169, 84,195,122,244,232,225, 63,114,228, 72,244,234,213, 11,155, 55,111, 30,178,108,217,178, 33,219,182, +109,203,102,140,173, 70,145, 49,176,219, 83, 32, 31,187,221, 30,106, 50,153,160,213,106,189,146, 56, 43, 43, 11, 33, 33, 33, 21, +190,196,172, 86,171,255,213, 9, 6,112,179,243,170,150,237,226, 79, 64, 68, 68,196,238,184,184,184, 86,181,107, 23,165,168,119, +197, 12, 47, 89,120,158, 7, 99,140,188,237,121,218,108,182,208,195,135, 15, 67,230, 1, 81, 5,136,146, 12, 65,148, 32,202, 50, + 36, 73,118,111,131,169,220,121, 12, 24, 99,149, 26, 12,140,177, 7, 53, 26,205,138,247,222,123,207, 24, 25, 25,201,135,134,134, +194,102,179,225,220,185,115,237,183,110,221,218,234,195, 15, 63,252, 47, 99,236, 81, 34,218, 94, 9, 85,231,226,103,134, 1, 40, + 55,233, 82, 49,106, 51,198,186, 22,183,243,104, 0,100,155, 10,235, 62,214,189,121,171,111,183, 31, 59, 84,201,167, 71,193,202, +222,143,222,151,222, 47,202,254,104, 47, 0,236,133, 56, 63,116, 99,149,239, 71,121, 96,140, 53, 10, 14, 14,126,125,205,154, 53, +204,106,181,214,123,237,181,215,218, 49,198, 90, 3,120,233,247, 4,185,170,170,162,181,219,108,161,171,118, 30,131,200,243,144, + 4, 14, 34,207, 65, 20,126,251,222,242,222,123,170,100, 72,150,144, 35, 12,192,151, 0, 68, 0, 99, 1, 68,101,103,103,195,233, +116, 34, 40, 40, 40,138, 49, 86, 15, 64,140,159,159, 31,229,228,228,140, 38,162, 12, 47, 56, 31,212,106,181, 43,222,127,255,125, + 99,215,174, 93,221,207, 95,114,114,114,251,205,155, 55,183,250,224,131, 15,188,125,254,134,204,159, 63,223,127,215,174, 93,208, +104, 52,168,233,184,140, 37, 45, 78, 66,104,120,253, 30,226,229,159,152,195,210, 15,128,207, 0,240,225,223,136, 68,250, 45, 20, +112,185,222,242, 91, 86, 1, 48,198, 50,154, 53,107, 22, 58,114,228, 72, 12, 31, 62, 28,213,171, 87,191,101,167,171, 87,175, 98, +229,202,149, 88,182,108, 25,142, 31, 63,158, 73, 68, 21,246, 42, 24, 99, 68, 68, 88,179,102, 13,120,158, 7,207,243, 16, 4,161, +212,103,217,239, 13, 27, 54, 4, 85, 16,191, 90,175,215,159, 53,153, 76,247,234,116,186,115,249,249,249, 13,138,143,225, 26, 22, + 40, 11, 43, 17, 21,150, 83, 95, 82,190,234,178, 44,191,103,183,219,135, 56,157,206, 10,141, 10,158,231,109,178, 44,255, 96, 50, +153, 38, 19, 81,185, 57,232,253,252,252,200,229,246,175, 86,173, 26,126,248,225,135, 82,202, 95,150,101,244,237,219, 23,203,150, + 45, 67,179,102,205, 42, 60,199, 50,242,209,175,191,254,138,134, 75,219,130, 41,118,128, 20,128,168,184, 40, 69, 9, 73,168, 56, +223, 7, 47,131,205,202, 5,227, 37,143,220,140,177,222,141, 26, 53,250, 62, 46, 46, 78,163, 40, 10, 46, 94,188,136,154, 53,107, +130,227, 56,164,167,167, 35, 32, 32, 0,105,105,105,120,252,241,199, 11,210,211,211,251,121,122, 9,215,173, 91,119,237,133, 11, + 23,222,171, 91,183,238,107,161,161,161,151, 42,106,151,150,150,214,224,242,229,203,111,215,172, 89,115, 90,106,106,234,131, 21, +181,147, 36, 41,227,177, 73,179, 66, 35, 26, 55,196,133,228,203,168, 91,175, 86,133,159,231,146, 46, 96,197,156, 87, 42,236,213, +142, 26, 53,138,194,195,195, 1, 0,167, 14,237,193,170, 30,166, 34,229, 95,108, 4,164,141,222, 95,229,251, 81, 30, 24, 99,145, +145,145,145, 59,118,236,216, 1,139,197, 2,187,221,142,126,253,250, 33, 62, 62,254, 24,128,119,137,232,187, 42,112, 5, 1,104, + 82,188,185,195,245,255,100,140, 85, 42, 95,101, 30, 0,163, 86,202,205,126,206, 58,166, 68,149,147, 1,199,240, 33, 37, 85, 34, +211,218,203,151, 47,247, 55,153, 76,232,208,161,131,163, 69,139, 22,252,142, 29, 59,240,217,103,159, 97,214,172, 89, 40, 44, 44, +116,108,220,184,145,191,124,249, 50,198,140, 25,179,241,198,141, 27, 81,149,240,245,110,220,184,241,247, 91,182,108,209, 40,138, +130, 11, 23, 46,192, 98,177, 64, 16, 4,232,245,122, 4, 4, 4, 32, 53, 53, 21,143, 61,246, 88,193,213,171, 87, 61, 62,127,140, +177,156,179,103,207, 26,143, 30, 61, 10,131,193,128,123, 44,231,209, 56,254, 37,176, 15, 9, 52,145, 65,245,145,187,233, 73, 0, + 31,162, 40,111,137,215, 9,114,138,143,209,210, 32, 98, 89,158, 13,255,165, 59, 16,203,158, 49,214, 73,150,229,175, 44, 22,203, + 72, 34, 58,252,123,249,254, 40, 48,198, 58,105, 52,154, 55,205,102,115,133,255, 87, 31,254,186, 40,155, 11,160, 60,148,215,227, + 9,157, 49, 99, 6,252,252,252, 16, 22, 86,190, 94, 15, 11, 11, 67,243,230,205, 97,179,217,112,252,248,113,175,122, 21, 60,207, + 67,237,200, 71,224,134,183, 96, 17,141,112, 14,154, 91,161, 65,224, 9,249,249,249, 13, 24, 99,100, 50,153,254,195, 24,243, 3, + 0, 73,146, 46,248,249,249,105,202,182,205,206,206,182, 48,198,130,200, 67, 66, 27, 89,150,223,255,248,227,143, 31, 25, 53,106, +148,170,228,177,157, 14, 7, 44,133,133,176,217,237,176,219,108,200,207,207, 23, 63,249,244,211, 97, 75,150, 46, 85, 3, 24, 88, + 30, 87,110,110, 46, 54,109,218,116, 75,175,191,164,203,217,149, 78,180, 42, 61, 79, 73,146,160,178,153, 96,237,250, 26, 84, 78, + 27, 84,138, 21,203,183,159, 64, 76,236, 73,212,240,151,176,244,201, 38, 48,112, 54,224, 66,124, 81, 4,112, 15, 96,140, 5,168, +213,234,229, 27, 55,110,212,100,102,102,226,236,217,179,104,218,180, 41, 94,126,249,101,112, 28,135,217,179,103,227,218,181,107, + 8, 11, 11,195,130, 5, 11, 52,195,134, 13, 91,197, 24,171, 95,145, 59,214,110,183,119,175, 89,179,102, 15, 34,194,229,203,151, +129, 98,163,178, 88,113,185,191, 19, 17, 66, 66, 66,182, 86,214, 33,182,217,108,161, 61,218, 52, 70,154,137,112,127,163,250, 48, +217,128, 54,205, 34,144,103, 81,208,238,254,198,200, 45,116,162, 83,155,230,200, 41,112,224,209, 62,145, 88,248,182,181,194,231, +111,241,226,197,216,180,105, 19,122, 94,152, 11, 60, 80,212,235, 87,189, 82,228, 53, 80, 94, 15,116,135,127,174,234,253,240,132, +231,158,123, 14,111,190,249, 38,182,109,219,134,132,132,132,230,253,251,247, 95,194, 24,139, 37, 34, 83,101,251, 50,198, 94, 15, + 12, 12,124,171,105,211,166, 34, 0, 84,118,173,202,194,102,181,134,209, 68, 54,116, 77,146,188,128,115, 88,140, 50, 7,168, 57, + 64,230, 0,153, 7,100,206,106, 76,205,192, 74,153, 47,170,151,100, 57, 87, 80, 91,158, 97,128, 71, 3, 0,128,120,244,232, 81, +248,251,251, 99,195,134, 13,124,253,250,245,177,103,207, 30,168,213,106,204,157, 59, 23,205,154, 53,227,181, 90, 45,214,173, 91, +135,155, 55,111,122, 52, 82, 24, 99, 1, 26,141,102,249,230,205,155, 53,179,102,205,194,253,247,223,143, 26, 53,106, 64,165, 82, +129,227, 56,216,237,118,100,103,103,163,122,245,234, 88,180,104,145,102,224,192,129, 30,159, 63, 0,214, 11, 23, 46, 56,212,106, + 53, 47,203, 50, 4, 82,195,161, 9, 6, 63,145,129,120, 57, 91,153, 96,121,152,125, 72,187, 25, 99, 29, 1,204, 67,145, 7,106, +161,183,215,148, 49,214, 50, 80, 47,237, 88,240,191,135, 13, 79,205,249, 62,150, 49,246,187, 18,218, 48,198, 58, 5, 4, 4,196, +206,152, 49, 67, 55, 97,194,132, 29,140,177,110,127, 69, 35,160,216, 72,137, 45, 40, 40,208,221,109, 89,124,184,125, 20, 39, 0, + 42, 9, 99,201,200,152,229,190,232, 66, 67,139,222,169, 91,182,108, 1, 0,116,233,210, 5,106,181, 26,133,133,133, 88,191,126, + 61, 14, 29, 42,202, 16, 91,149,156,211,130, 32, 32,232,232,106, 16, 47,130,153,174, 3,123, 23, 65,120,104, 66,185, 30, 0, 47, +113,201,245,197,106,181, 26,211,211,211,203, 59, 38, 95,124,142, 21, 26, 0, 14,135, 99,224,232,209,163, 85,177,177,177,112, 58, +157, 16, 4, 1,130, 32, 64, 20,197, 82,223, 37, 73,194,243,207, 63,207,125,241,229,151,253, 60, 9, 85, 82,217,151,252,238, 42, + 90,173, 22,106,181, 26,141, 27, 55,118,245, 60, 43, 29,131,118, 93,103,149,195, 2,149, 98, 5, 28, 86,188,240,205, 30, 20,218, +156, 56,124, 9,216,214,210,136,129,247,185,236, 31,207,157, 27, 65, 16, 94,153, 53,107,150, 81,165, 82,225,220,185,115,144, 36, + 9,249,249,249, 24, 60,120, 48,236,118, 59, 20, 69,129, 36, 73,112, 56, 28,104,220,184, 49,134, 14, 29,106,252,246, 30,213,179, + 88, 0, 0, 19,135, 73, 68, 65, 84,219,111,255, 7,224,237,242,248,174, 92,185,162, 39, 34,119,106,212, 62,125,250, 32, 58, 58, + 26, 17, 17, 17, 56,115,230, 12,162,163,163,177,113,227, 70, 0, 69, 10,205,155, 20,170,181, 3,212,168, 23,194,187,159, 7,142, +227,220,223,203,150,202, 32,203, 50, 96,183, 0, 14, 75,209,167, 11, 14, 11,100, 89,190,173,251,225, 9,169,169,169,232,216,177, + 35, 94,124,241, 69,180,104,209,194, 37,163, 30,128, 71, 3,128, 49, 22, 29, 17, 17, 49,109,199,142, 29, 8, 11, 11,131,195,225, +128,221,110, 71,126,126, 62, 30,125,244, 81, 0, 72, 46,206, 93,113,142,200,227,152, 54,111,183, 88,140,131,182, 85,110, 60,216, +159, 97, 70,168, 33,120,113, 90, 47, 13, 24, 48, 32,105,209,162, 69,252,181,107,215,112,248,240, 97,168,213,106,119, 73, 75, 75, +131,201,100,194,251,239,191,239, 64,209, 16, 65,133, 16, 69,241,149, 57,115,230, 24, 85, 42, 21,194,195,195,241,252,243,207, 99, +245,234,213, 8, 8, 8, 40,186, 31,201,113,224,117, 1,112,106, 31, 64,163, 70,141, 48,108,216, 48,227,202,149, 43, 43,124,254, + 0,124, 63,117,234,212,168, 41, 83,166,212, 14, 10, 10, 66,182, 45, 0,163,127,109,129,171,105,105, 87,182,116, 58,245, 40,138, +223, 19, 68,180,135, 49, 54, 25,192, 71,240,210, 0,112, 41,255,163,107, 62, 55,212,240,147, 16,148,244,157, 46,106, 13,110,219, + 8,112, 41,255,131, 7, 15,234, 52, 26, 13, 50, 51, 51, 13,115,230,204,249,203, 25, 1,140,177, 78, 58,157, 46,118,197,138, 21, +186,254,253,251,223, 17, 62, 73,146,150, 88,173,214, 39,239,132, 7,197, 7,175, 97, 68,145,193,235, 70,217,176,216, 30,223,160, +254,254,254, 0,128,253,251,247,227,212,169, 83, 56,113,226, 4, 84, 42,149, 91, 33, 86, 5,130,138, 65,119,105, 23,110,118, 28, + 7,166, 40, 80,118,206, 7,223,247,149, 82,202,159, 99, 69,134,130, 55, 32, 34,119,222, 80,173, 86,155, 34,138, 98, 53,160,200, +101,206, 24, 8, 96, 36,203,114,186,217,108,246,152, 46, 86, 81, 20,158,231,121, 88,173, 86,136,162,232,238,137,112, 28,135, 78, +157, 58,225,208,161, 67,238,228, 64,106,189, 30,138,162,120, 84, 16, 46,165, 95, 86,249,203,178, 12, 81, 20,221, 61, 78,215,167, + 55,248,205, 0, 40,128,202,105, 5,179, 23, 98,214,160,251,176,114,127, 42, 90,215, 80,227,193,186, 2, 96,241, 46,191,144, 40, +138, 61,187,118,237,202, 37, 37, 37, 65, 20, 69,136,162, 8,187,221,142,158, 61,123,130, 49,134,244,244,116, 72,146, 4, 81, 20, + 1, 0, 61,123,246, 20,215,175, 95,223, 19, 21,191,128, 75, 41,255, 13, 27, 54,184,235,136, 8, 27, 54,108, 64, 84, 84, 20, 54, +110,220,232,117,254,116, 65, 16,176,104,209,162,114,211,155,150, 44, 83,166, 76,169,148,171,200, 0, 40,116, 27, 1,202,155, 33, +197,195, 0,133,165,238, 67, 85,238, 71,101,200,202,202, 26, 27, 29, 29, 93, 11, 64, 48,128,159,137,232, 86,235,180, 4, 24, 99, + 3, 93,202,159,136,208,183,111, 95,140, 27, 55, 14,237,218,181, 67, 94, 94, 30, 94,126,249,101,100,103,103,215, 35,162, 29,103, +206,156, 81, 24, 99,145, 68,180,171, 2, 58,187, 32,201,185,235, 30,100, 70,217,213,251,231, 0, 53,255,219,119,183, 71, 64,150, +115, 1,139,199,116,207,174,121, 8,157, 59,119, 70,223,190,125,177,114,229, 74,140, 29,251,155,142, 31, 59,118, 44, 94,122,233, + 37,228,228,228,160,118,237,218,124,114,114,242,121,198, 88,133,243, 21, 92,207,223,133, 11, 23,208,186,117,107,140, 25, 51, 6, +163, 70,141,194, 79, 63,253, 4, 67,230, 47, 56,255,127,111, 33,124,208, 84,104, 68, 17,140, 49,244,234,213, 75,252,233,167,159, + 60, 61,127,111, 31, 57,114, 68,243,200, 35,143, 60,166, 40,138,196,113,156,163, 86,173, 90,187,243,243,243,159,102,137, 84,106, + 21, 0, 17,109,102,140, 53,242,116,190, 37,206,251, 55,229,239,175, 6,173,126, 6,157,106, 75,216, 48,210,160,139, 90,113,163, +202, 70, 64, 73,229,175,213,106,241,203, 47,191,160, 99,199,142,152, 49, 99,134,225,173,183,222,250,203, 24, 1, 46,229,127,224, +192, 1, 93, 96, 96,224, 29,227,155, 61,123,182,110,210,164, 73,191,219,131,226,131,119, 96,140,181, 0,112,164,120,179, 61, 17, +237, 47,175,157, 87,221,109,173, 86,139,140,140, 12,216,237,246, 42, 43,126, 23,252,175,236, 1,115,218, 65, 13, 34, 33,168,128, +194,245, 51,225,188,122, 26,234,122, 45,193,243, 60, 46,254,252, 5,142,172,124, 31,126, 17,237,161,246, 66, 42,154,200, 56, 0, + 28,128, 6, 55,159,198, 84, 43, 65, 46, 25,212,128, 3,160,226,109, 54, 81,133,251, 80, 52,254,231, 17,174, 30,101,159, 62,125, +176,115,231, 78,119,239,146,231,121, 52,109,218, 20,201,201,201,224,184,202, 59,135,229, 77,252,115, 25, 3,140, 49,183,162,113, +245, 60,189,129, 75, 25,171, 28,133, 56,155,154,133, 90,122,134,113,157,130, 48,238, 63, 26,192, 86, 8,216,204,128,173, 82, 15, + 51, 24, 99,140,231,249, 70, 97, 97, 97, 72, 77, 77,117, 43,250,154, 53,107,226,217,103,159, 5,199,113,248,252,243,207, 97, 50, +153,220,198, 65,163, 70,141, 80, 80, 80,208,220, 19,175,171,103, 31, 29, 29,237, 58, 78,169,223, 93, 94, 0,111, 61, 0,130, 32, + 96,204,152, 49, 21,246,250, 75,122, 6, 42,131, 90,173, 6, 28, 22,168, 94, 59, 5,229,173, 48,236, 76, 54, 97,231,197, 66, 68, +183, 35,112, 28,119, 91,247,195, 11,156, 36,162,207,170,208,126,208,212,169, 83,161, 40, 10,186,119,239,142,145, 35, 71,162,109, +219,182,136,137,137,193,238,221,187,177, 96,193, 2,172, 88,177, 2, 14,135, 3,107,215,174, 85, 77,158, 60,121, 20,128,114, 13, + 0, 70, 56, 62, 48,194,242, 44,202,252,183,253,191,146,190,200, 45,176, 26, 75,183,182, 24, 1,172,150,191, 80,123, 90, 53, 18, +149,157,157, 13, 63, 63, 63,236,217,179, 7, 26, 77,145,167,201, 53, 31, 97,250,244,233,164,213,106, 97,181, 90, 17, 23, 23, 7, +181, 90,141, 26, 53,106,148, 59, 7,160,228,243,151,149,149, 5, 0,120,242,201, 39,113,249,242,101, 60,254,216, 35,152,117,255, + 13,132, 55,237, 2,125,231,103,160,226,139,188,111,141, 27, 55,246,248,252, 17, 81, 38,128, 81,197,229,142,160, 60,229, 15, 0, +208,135,162, 83, 88, 16, 54,140,173,163,139,250,236,176,215,202,172, 60,229, 47,138, 34,212,106, 53, 34, 35, 35,241,209, 71, 31, + 25, 38, 78,156,120,215,141, 0,151,178,222,191,127,191,206, 53, 15,227, 78,241, 25,141, 70, 56,157, 78,221,148, 41, 83,124, 70, +192,159,131,253, 0,212, 68,100, 41,234, 20, 51,117,121,203,230,255,240,245,207, 65, 50,224, 60,189, 3, 33,135,190, 65, 78,211, + 1, 16, 52,122,240, 60, 15,241,222,246, 40, 60,185, 21,126, 13,255, 3,107,230, 5, 36,125,247, 1,186, 76,250, 18,135,127,252, + 10, 15,220, 58,239,240, 22,228, 20,226, 73,142, 21,185, 55,246,164, 74,159,240, 28, 19,121, 6,240,170,162,217,242,188, 10,224, + 64,182,230,247, 88, 71,193, 11, 3, 64, 16, 4, 12, 24, 48,160,104,204,184,103, 79,236,221,187, 23, 0,208,188,121,115,156, 63, +127,222,237,169,168, 12, 21, 13, 1,184,240,123, 60, 0,125,102,111,198,166,147,153, 48,200, 60,246,141,107,136,251,252, 21,220, +204,201,199,144, 85,153,144, 84, 78,196, 14,240,138, 14,118,187, 29, 98,113, 15, 75,146, 36, 8,130,128,252,252,124,247,177,108, + 54,155,219, 56,112, 25, 31, 21,161, 85,171, 86,185,173, 91,183, 70,171, 86,173,208,184,113, 99, 3,138,199,253, 75, 42,250,198, +141, 27, 83,171, 86,173,242, 92,237, 42, 3,207,243,152, 63,127,190,199,222,191, 74,165,194,155,111,190, 89, 41,151,123, 8, 0, + 0,236,133,216,121,209,130,183,247, 17,162,219, 21, 85,253, 17, 30,128,170,128, 49, 86, 23, 64,236,132, 9, 19,134, 19,145,170, +119,239,222,120,241,197, 23,145,145,145,129,175,190,250, 10,169,169,169,232,209,163, 7,252,252,252, 64, 68, 56,115,230,140, 25, +192, 15, 21, 18,126, 68,103, 25,112,182,108,117,238, 71,108,229,201,139, 25,165, 86, 5, 72, 2, 15,145,231,160,211, 72, 30,231, +241, 56,157, 78,204,155, 55,207,237,242, 47, 11,158,231,161,209,104, 42,252,189, 44,236,118, 59, 4, 65, 0, 99, 12,118,187, 29, + 51,102,204,192, 99, 81,145,216,114, 85,194,244, 15,230, 65, 37,136,165,134,225, 42, 3, 99,172,150, 36, 73, 31,219,237,246,126, +138,162,240, 0,160, 82,169, 28,106,181,122,189,217,108,254, 31, 17, 93, 46,110,231,149, 11,202, 32, 98,217, 55, 19, 7,254,166, +252, 25, 15,104, 3, 1,109, 16,160, 13, 66,167, 22, 65,152,243,148, 78, 55,121,201,158, 85, 0,106, 84,198, 39, 73,210,170,152, +152, 24,157, 86,171,197,193,131, 7, 33, 73, 82,169, 33,148,158, 61,123, 98,252,248,241,134,152,152,152,101, 0, 26,123, 35,227, + 31, 1, 73,146,150,204,156, 57, 83,231,231,231,135,228,228,100,252, 30, 15, 64, 73, 79, 66, 64, 64, 0,146,147,147, 17, 25, 25, +137,197,139, 23,235,158,126,250,105,159, 17,240, 23,193, 31,107, 0, 76,103,252,185, 71,128,130,185, 15,160,176, 65,127,216, 58, + 62,231, 86,164,154, 22,189,145, 21,247, 5,132, 71,167, 33, 57,110, 1,170,183,233,133, 6, 15, 60,130,106,141,219, 98,195,131, + 45, 42,165,222,116, 22, 49, 60, 3, 4, 14,224,152, 85,243,192,170,236, 82,131, 29, 12,192,241,145,254, 2,188, 56, 71, 75, 97, + 33, 4, 65,192,166, 77,155,208,189,123,119, 36, 38, 38,186, 61, 0,231,206,157, 67,253,250,245,113,245,234,213, 42, 25, 0,174, +207,178, 10, 84,163,209,148,234,121,122, 3, 73,146, 64, 0, 46, 92, 43, 82,210,121, 22, 7, 78,167,101,227, 62,141, 10, 63, 30, +191,137,157, 41,118,180, 12,169,156,135,136,200, 96, 48,156, 78, 78, 78,110,105, 48, 24,220,138,190,228, 88, 58,199,113,110,185, + 37, 73,194,233,211,167,161,213,106,143, 87,196,121,232,208, 33,163, 75,225,159, 56,113, 2,109,219,182,189,165,205,137, 19, 39, + 88,201,118,149, 65, 16, 4,140, 31, 63,190,220, 30,255,109,205, 1,112, 88,160, 76,245, 7,236, 5,136,110,167,184,149, 63,112, +123,247,163, 36, 88, 81,202, 77,247, 64,169,211,225,209,163, 94,118,223,237, 77,154, 52,233,118,243,230, 77, 92,189,122,213,214, +174, 93, 59,241,131, 15, 62, 64, 98, 98, 34,194,195,195,177,105,211, 38, 68, 71, 71, 99,245,234,213, 55, 1, 12, 46,222,237, 24, + 17,101, 87, 85, 78, 81,146, 50,155,212, 9, 43, 87,209,203,178,236,105,249,230,134,160,160,160,168,234,213,171,227,253,247,223, +135, 44,203, 24, 51,102, 12,166, 79,159, 78, 0, 16, 25, 25, 9, 65, 16,160, 86,171,209,189,123,119, 36, 37, 37, 1,192,134,242, +136,136,136,140, 70,227,233, 11, 23, 46,180,212,233,116,110, 67,128,136,176, 54,110, 59, 84, 12, 80,105,252, 75, 41,255, 83,167, + 78,121,124,254, 0, 64,146,164, 79,251,247,239,255,112, 76, 76, 12, 19, 4, 1, 38,147, 9,215,206, 31,227, 63,250,232,163, 1, + 7,246,237, 13,166,137,108, 42,128,139, 0,154,194,139,206, 64,158, 13,255,125, 98,214,255,197,254,124,122,149,174, 83,125,255, + 98,197,255,155, 1,112, 56,195,137, 41, 75,247,152, 77,133,214, 10, 99, 80,148,132,213,106,125,230,217,103,159,253,254,157,119, +222,209, 54,105,210,164,148,242, 87,171,213, 56,113,226, 4, 62,253,244, 83,147,201,100,250,175, 55,124,127, 20,172, 86,235,147, +147, 39, 79,142, 37, 34, 93,100,100, 36, 12, 6,195,109,241,184, 38, 16, 46, 95,190, 92, 23, 24, 24,136,212,212, 84, 4, 6, 6, +194, 96, 48,160,110,221,186,216,184,113,163, 46, 42, 42,202,103, 4,252, 5,240,199, 26, 0,211,200, 81, 67, 96,200, 55,231, 35, +255,228,153, 82, 19,253,196,251, 31, 66,250,234,183,145,242,109, 52,210,119,255,136,182,209,107, 32, 8, 2, 66,234,222,135,245, +151, 43,167,126,164, 57, 30, 71,145,167,159,223,122, 73,251,209,142,199,194, 2, 5, 6,112, 42, 64, 40,246, 0,200,106,237, 13, +192,243, 28, 0,149, 74,229,200,205,205,229,213,106, 53, 24, 99, 56,112,224,128,219, 72, 57,123,246, 44,120,158, 71, 90, 90, 26, + 92, 47, 22,142,227,156,158,248, 74, 14, 1,148,103, 48,184,226, 33, 84, 69,225,184,148,230,230,231, 35,176,234, 96, 58,234, 25, + 9,131,234, 41, 64, 97, 62, 30,188,199,138, 55,219, 2,207, 54,245,138, 10, 86,171,117,235,214,173, 91,155, 61,249,228,147,252, +141, 27, 55, 32,138, 98, 41, 87,122, 73, 3, 64, 20, 69,108,220,184,209,106, 50,153,182,122, 35, 95,116,116, 52, 98, 99, 99,221, +219,174,121, 0, 21, 13, 13, 84, 4, 65, 16, 48,111,222,188, 74, 61, 0,211,167, 79,175,148, 75,173, 86,195, 52,241,244, 29,189, + 31,197,231,226, 15, 96, 86,189,122,245,158,157, 49, 99,134,170, 73,147, 38,200,205,201,129,197, 98, 1,128, 74,205, 49,198, 88, +221,186,117,235,118, 59,124,248, 48,236,118, 59,174, 95,191, 46, 18, 17, 78,159, 62,141,193,131, 7, 59, 12, 6, 3, 63,123,246, +108, 76,159, 62, 29, 7, 14, 28, 8, 72, 73, 73,185, 76, 68, 23, 60,113, 86,180, 12, 80,148,164, 76,235,109, 6, 0, 34,162,190, +140,177,186,133,133,133, 73, 77,155, 54,229,175, 94,189,138,137, 19, 39, 66,173, 86,187,255,207,118,187, 29, 57, 57, 57,184,112, +225,130, 3, 64, 4, 17, 37, 87,196,103,181, 90,183,110,217,178,165,217, 83, 79, 61,197,231,230,230,186,149, 61, 19, 4,240, 37, + 20,191,235,115,195,134, 13,149, 62,127, 54,155,173,239,103,159,125,198,182,111,223, 14,181, 90, 13,157, 78,135,176,194,171, 88, +216,244, 4, 19,234, 91, 58, 17, 47,175,123,122,131,101, 6,128,167, 1,124,224,197, 57,239,102,140,245,142, 90,203, 98, 55,140, + 50,232, 58,133,133,186,141,128,195, 25, 78,244,120,227, 59,115,110,129,117, 8, 17,197,121,121, 13,227, 24, 99, 67,222,124,243, +205,239, 63,253,244, 83,109,139, 22, 45, 74, 41,255, 17, 35, 70,152, 76, 38,211, 93, 87,134,174,243,158, 50,101, 74,236,226,197, +139,117,117,235, 86, 26,139,171, 92,104, 52,154, 55, 11, 10, 10,116, 3, 6,120,116, 73,234, 12, 6,195,155, 0,124, 75, 12,255, + 56, 20,150,120,231,186,190,151, 26, 10, 40,207, 0, 88, 59,118,236,216, 1, 99,199,142, 69,131, 6, 13, 42,100,190,118,237, 26, + 18, 18, 18,128, 91,211, 13,150,130,217, 1, 48, 81,115,235,154,127,117, 48,234,190,184, 0,167, 63,127, 9,247, 14, 26,143, 26, + 45,187, 85,105, 21, 0,251,144,214, 0, 0, 77,100,117, 27, 7,155,199,221, 44,196, 45,203, 0, 3,212, 86, 51, 0,143, 99,106, +146, 36,173,157, 63,127,254, 35,195,134, 13, 99, 2,207,195,233,116, 66, 65,145,178,114,201, 42, 8, 2,114,115,115,241,238,187, +239, 42, 58,157,110,125, 69, 92,162, 40, 58,131,131,131, 57, 89,150,241,208, 67, 15, 65,150,229, 82, 69,173, 86,187,151, 86,186, +122,158, 94,131,151, 80, 59,255, 48, 94,141, 40,222, 46,114, 6,160,166, 30,152,222,193,123, 26,155,205, 54,231,195, 15, 63,124, +182, 71,143, 30,254,213,170, 85,131,211, 89,100,207,132,132,132,192,225,112,128,227, 56,247,208,192,190,125,251,176,122,245,234, +124,171,213,250,161, 39, 78, 87,207, 62, 46, 46, 14, 81, 81, 81, 72, 76, 76,116,175, 2,136,138,138, 66, 92, 92, 92,169,118,149, + 65, 16, 4, 76,154, 52,201,227, 10, 0,149,170,242, 52, 22,127,232,253, 0,222,158, 57,115,230,127, 39, 79,158, 12,149, 74,133, +252,255,111,239,108, 99,154,186,194, 56,254,127,122,251,118, 95,138, 3,149,136, 2, 93, 16,113,113, 56,151,248,201,132,184,201, + 32, 33, 89,140, 49, 27,201,220, 75,194,136,108,132,152, 96, 92,220,194, 38, 34,209,205, 48,183,133,234,190, 44, 91, 6,206, 56, + 93,226, 50, 17, 39, 99, 38, 11,198, 37,211, 72,182,100,153,213,205,134,160, 32,111,101,131,218,222,218, 94,104,207, 62,148,219, + 32,218,246, 82, 96, 48,189,191, 79,165,156, 62,247,158,156,211, 62,207,115,238, 57,255,199,235,197,141, 27, 55,176, 98,197, 10, + 92,233,236, 76,172, 98,200, 88, 23, 17,253, 92, 88, 88, 88,176,118,237, 90,172, 90,181, 10,130, 32,224,192,129, 3,240,249,124, +175,251,124,190,252,246,246,246,119,214,173, 91, 7,191,223, 15, 0,113,245, 44,128,123,133,128,204, 38, 14, 22, 35, 7,179,137, +195, 51, 79,229, 36, 37, 0, 52,137, 79,207,158, 61,107,148, 36, 9, 62,159, 15, 35, 35, 35, 8, 4, 2, 81, 39, 54, 58, 58,138, +156,156, 28, 56, 28, 14, 99, 85, 85,213, 17, 68,212, 67, 31, 72, 48, 24,108, 56,116,232, 80, 69,113,113,113,106, 70, 70, 6,194, +225,240, 61, 14,127,242,233,155,105,204, 63, 78, 81, 20,152, 76,166,232,216,154,199, 56,152,238,186, 65,159, 48, 96, 23,165,126, +231,194,155, 0, 62, 0,112, 76, 75,135,163, 65, 64,115,111,219,247,111, 61, 46, 21, 60,157,142, 95, 7,198,241,220,123, 39,101, +143, 63,160,217,249, 79,178,247, 3, 17,189, 88, 93, 93,125,170,185,185, 89, 92,191,126,253,130,114,254, 42,106,191,203,203,203, +219,206,157, 59,151,212, 17, 64, 93, 55, 96,254, 73,116,254, 95,229, 65, 66, 64, 28,128,114, 34,218, 87, 82, 82,178,188,178,178, + 18,203,150, 45, 67,107,107, 43,250,250,250,160, 40, 10, 58, 59, 59,113,253,250,245, 62, 0,251, 0,124,201, 24,139,153, 21,171, + 66, 64,215,174, 93,139, 41,252, 51,249,181,186,243, 59,129,144, 13, 3,144,170,254, 29, 75, 7, 96,116,116,212, 31, 8, 4,226, +202, 5, 19, 81,166, 32, 8,142, 96, 48,184, 57, 20, 10,197, 92,227,231, 56,110, 92,146,164, 86,143,199, 19,125,166, 24,239,254, +220,110,119,220,149,128,154,154, 26, 28, 60,120, 80, 83, 95,167,123, 30, 60,145,104, 12, 17,109,206,204,204, 60,209,212,212, 36, +230,229,229,193, 96, 48, 64,146, 34,223,117,245, 71,248,242,229,203,216,186,117,171,111,120,120,248, 5,198,216,143,177,108,217, +237,118, 15, 0, 10,135,195,247,157,253,143,245,122,104,104, 40,166, 44, 36, 17,177,158,158, 30, 52, 54, 54,198,204,252,213, 32, +162,174,174, 78,147, 64,206,108,142,199,132, 61, 11,128, 62, 69, 81,210,140, 70, 35,134,135,135,225,114,185,208,219,219,139,109, +219,182,141,133, 66,161, 84,198,152, 28,207,198,132, 29, 35,128,141,136, 8,255, 60,137,200,147,171, 99,140,177,139, 68,244, 89, +109,109,237, 27,133,133,133,216,180,105,211, 8, 99, 44,161,236,245, 92,172, 0, 76,220,231,233,170,170,170, 45, 60,207,195,225, +112,140,219,237,118, 99,123,123,123,116,217,191,171,171,107,220,225,112, 24, 7, 7, 7, 81, 95, 95,223,194, 24,139,155,250, 17, +209,230,172,172,172, 19, 71,143, 30, 21, 87,175, 94, 13, 34,138, 58,125,117,254, 93,186,116, 73,211,252, 3, 0,142,227,198, 58, + 58, 58,140,178, 44, 67, 16, 4, 72,146,132,197,222, 63,177,252,252, 78, 24,253, 67, 96, 70,235, 8,141, 71,244, 0,146,232,123, +129,205,106,106,107,216, 94, 44,213, 52,253, 36,123,228,233, 59,255, 41,246, 74,108, 54,219,169, 61,123,246,136,251,247,239, 95, + 80,206,127, 50, 68, 84, 96,179,217,218,188, 94,175,148,172, 64,150,206,194,231,190, 0, 32,250, 15, 34, 1,192, 78,179,217,252, +118,105,105,233,162,180,180, 52,116,116,116,192,233,116,122, 66,161,208,135, 0, 26, 25, 99,254,132, 23, 32, 98, 67, 67, 67,240, +120, 60,113,149, 0, 85,231, 15, 64,139, 83, 60, 13,224,217, 73,111, 45, 10,135,239, 63,255,174,229,199,124, 46,176, 88, 44,227, +138,162,196,205, 60,211,211,211, 81, 93, 93, 61, 47, 1,192, 68,155, 45, 86,171,181,185,172,172,140, 47, 42, 42,178,228,231,231, + 71,159,185,158, 57,115, 38,120,252,248,113,217,239,247,191,202, 24,107,139,103, 39, 55, 55,247, 91,151,203,245,209,202,149, 43, +119,103,100,100,116,199,106,215,211,211,147,119,243,230,205,247,179,179,179,107,111,221,186, 21, 51, 67, 36, 34,214,223,223,175, +249,220,191,150,190,206,230,120, 76, 92,243, 9,131,193,240,203,133, 11, 23, 30,179,219,237,232,238,238,198,213,171, 87,177,119, +239,222,144,219,237,222,197, 24, 59, 28,239,243, 90, 32,162,175, 26, 26, 26, 94, 19, 69, 17, 59,118,236,184,200, 24,219, 56, 19, +123, 22,171,117, 64, 9,222, 43,154,100,177, 90, 7, 3,218,106, 70, 76,149, 2,118,221,190,125, 27, 60,207, 35, 45, 45, 13, 0, +114, 1, 28, 65,164, 22, 68, 37,211, 38, 5,188,133,231,249,230,178,178, 50,190,184,184,216,146,159,159, 15,163,209, 8,167,211, +137,150,150, 22,205,243, 15, 0,120,158, 63,177, 97,195,134,210,138,138, 10, 46, 61, 61, 29,162, 40, 98,108,164, 23,141,142,195, + 33,231,111, 87, 58,156,175, 4,234, 0,116, 39, 91, 19,128,136, 10, 36,222,114,210,119, 55,184,125, 38,206,127,146,189, 18, 81, + 20,191,144,101,249,165,133,232,252, 85,136,168, 32, 37, 37,165,214,227,241,232, 25,253, 67, 74,204, 0, 32,218,128,104, 49, 34, + 95,238, 23, 16, 89,238,175, 98,140,253,173,245, 2, 86,171,117, 32, 24,140,173,214, 22,227, 51,154,138,217,168,216,108,182,191, + 20, 69,201,154,250,190,217,108,238, 81,229,130,231, 3, 45,153,103, 34,135,195,243,252, 64, 32, 16,152,171, 98, 64, 75,204,102, +243,110, 65, 16,138,100, 89, 94, 67, 68, 76, 20,197, 63,100, 89, 62,175, 40,202,199,140,177,127, 52,216, 40, 69, 36,115, 37, 0, +241, 42,243,101,171,237, 88,156, 66, 57,211,157, 47,211,153, 43,179, 49, 30,147,108,101, 2,248, 28,145, 64,180, 31,192,239, 0, +222,101,140, 57,181,222,123, 2,251,207, 75,146,244,141,193, 96,192,157, 59,119,202, 24, 99,167,102,104,143, 69, 79, 1, 76, 60, + 26,200, 88,156,146, 84,128, 76,179, 87, 12,104,137,217,108,222, 45,138, 98,145, 44,203,107, 0, 76,123,254, 77,216, 89, 42, 8, + 66, 93, 56, 28,126, 57, 20, 10,241, 0, 96, 50,153,238,114, 28,247,181,215,235,173,103,140,185,147,185, 63, 29,157,135,157,132, + 1,128, 78,242,168,153,103,188, 54, 41, 41, 41, 33,143,199, 51,239,229,104,213, 35, 82,211, 93,110, 32,162,165,140, 49, 55, 69, + 10, 16,197,147, 33, 20, 25, 99,221, 68,148,147,104, 51,219, 92,241,127, 26, 15, 32,186,209, 16,201,236,250,159,202, 76, 86, 0, +254, 11,146,157,127, 58, 58, 58,201,163, 7, 0, 58, 58, 58, 58, 58, 58,143, 32,137,183, 82,235,232,232,232,232,232,232, 60,116, +232, 1,128,142,142,142,142,142,206, 35,200,191, 46, 96, 71,216,137,209,203,202, 0, 0, 0, 0, 73, 69, 78, 68,174, 66, 96,130, }; diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index bf4beacaa58..97607b69446 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -78,7 +78,6 @@ #include "BIF_usiblender.h" #include "BIF_writeimage.h" #include "BIF_drawscene.h" - #ifdef WITH_VERSE #include "BIF_verse.h" #endif @@ -830,6 +829,8 @@ static void do_info_filemenu(void *arg, int event) if (untitled(dir)) { activate_fileselect(FILE_BLENDER, "Save As", dir, BIF_write_file); } else { + /* do NOT ask everytime for overwriting... */ + G.save_over = 1; BIF_write_file(dir); free_filesel_spec(dir); } diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index 27a39537988..14b8eca4135 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -831,6 +831,8 @@ int blenderqread(unsigned short event, short val) if (untitled(dir)) { activate_fileselect(FILE_BLENDER, "Save File", dir, BIF_write_file); } else { + /* do NOT ask everytime for overwriting... */ + G.save_over = 1; BIF_write_file(dir); free_filesel_spec(dir); } @@ -931,6 +933,8 @@ int blenderqread(unsigned short event, short val) if (untitled(dir)) { activate_fileselect(FILE_BLENDER, "Save File", dir, BIF_write_file); } else { + /* do NOT ask everytime for overwriting... */ + G.save_over = 1; BIF_write_file(dir); free_filesel_spec(dir); } diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index 969b9d4657b..97794148895 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -169,6 +169,28 @@ void asciitoraw(int ch, unsigned short *event, unsigned short *qual) /* this va_ stuff allows printf() style codes in these menus */ +static int vconfirm_choice(char *title, char *itemfmt, va_list ap) +{ + char *s, buf[512]; + + s= buf; + if (title) s+= sprintf(s, "%s%%t|", title); + vsprintf(s, itemfmt, ap); + + return (pupmenu(buf)); +} +int confirm_choice(char *title, char *itemfmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, itemfmt); + ret= vconfirm_choice(title, itemfmt, ap); + va_end(ap); + + return ret; +} + static int vconfirm(char *title, char *itemfmt, va_list ap) { char *s, buf[512]; diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 2bf2d5d9ae9..f3801342b3a 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -110,6 +110,7 @@ #include "BIF_resources.h" #include "BIF_screen.h" #include "BIF_space.h" +#include "BIF_toets.h" #include "BIF_toolbox.h" #include "BIF_cursors.h" @@ -793,7 +794,7 @@ void BIF_write_file(char *target) strcpy(di, target); } - if (BLI_exists(di)) { + if (BLI_exists(di) && !G.save_over) { if(!saveover(di)) return; } @@ -824,9 +825,13 @@ void BIF_write_file(char *target) G.save_over = 1; writeBlog(); + } else { error("%s", err); } + + /* CLEARS signal: "file needs save" on exit */ + U.uiflag &= ~USER_UNDOSAVE; waitcursor(0); } @@ -927,6 +932,41 @@ void BIF_init(void) BLI_strncpy(G.lib, G.sce, FILE_MAX); } +int exit_save_question(void) +{ + char dir[FILE_MAXDIR]; + int ret = 0; + + /* just go on if no undo there */ + /* better check necessary --> some flag */ + if(!(U.uiflag & USER_UNDOSAVE)) + return 1; + + /* do sweet question here */ + ret = confirm_choice("Warning: Unsaved changes", "Do you want to save your changes before exit?"); + + if(ret==1) + { + /* copyied from header_info.c */ + strcpy(dir, G.sce); + if (untitled(dir)) { + activate_fileselect(FILE_BLENDER, "Save As", dir, BIF_write_file); + } else { + /* do NOT ask everytime for overwriting... */ + G.save_over = 1; + BIF_write_file(dir); + free_filesel_spec(dir); + } + return 1; + } + else + { + /* cancel, ok, continue button available */ + } + + return 1; +} + /***/ extern ListBase editNurb; @@ -934,7 +974,15 @@ extern ListBase editelems; void exit_usiblender(void) { - struct TmpFont *tf; + struct TmpFont *tf; + + /* ask for save before exit */ + if(!exit_save_question()) + { + /* user pressed 'cancel' */ + return; + } + tf= G.ttfdata.first; while(tf) { From 9e96ac11bbe0212d031e59df461d3ae887e07d03 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 21 Dec 2007 01:24:09 +0000 Subject: [PATCH 068/101] WIP commit, just to have a nice return from holidays :) --- source/blender/blenkernel/BKE_blender.h | 1 - source/blender/blenkernel/BKE_cloth.h | 6 + source/blender/blenkernel/intern/cloth.c | 336 +++------------------- source/blender/src/drawobject.c | 340 +++++++++++++++++++++++ 4 files changed, 382 insertions(+), 301 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 84ebd3102b3..243425db139 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -70,7 +70,6 @@ extern void BKE_reset_undo(void); extern char *BKE_undo_menu_string(void); extern void BKE_undo_number(int nr); extern void BKE_undo_save_quit(void); -extern int BKE_undo_there(void); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index d888ba28ebe..b122347998d 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -67,6 +67,12 @@ typedef struct fc float *u, *u0; // velocity in x direction float *v, *v0; // velocity in y direction float *w, *w0; // velocity in z direction + unsigned char* _texture_data; + float _light_dir[3]; + int _ray_templ[4096][3]; + FILE* _fp; + int _cur_frame; + int _nframes; } fc; fc *f_init(void); void f_free(fc *m_fc); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 95d487b2ec7..318d6eac410 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -498,308 +498,33 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) return ret; } -#define AMBIENT 50 -#define DECAY 0.04f -#define ALMOST_EQUAL(a, b) ((fabs(a-b)<0.00001f)?1:0) - - // cube vertices -GLfloat cv[][3] = { - {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f}, - {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f} -}; - - // edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] -float edges[12][2][3] = { - {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, - {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, - {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, - {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, - - {{1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}}, - {{-1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}}, - {{-1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}}, - {{1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}}, - - {{-1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}}, - {{-1.0f, -1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}}, - {{-1.0f, -1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}}, - {{-1.0f, 1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}} -}; - -void light_ray(unsigned char* _texture_data, int _ray_templ[4096][3], int x, int y, int z, int n, float decay) +int m_fc_open(ClothModifierData *clmd) { - int xx = x, yy = y, zz = z, i = 0; - int offset; - - int l = 255; - float d; - - do { - offset = ((((zz*n) + yy)*n + xx) << 2); - if (_texture_data[offset + 2] > 0) - _texture_data[offset + 2] = (unsigned char) ((_texture_data[offset + 2] + l)*0.5f); - else - _texture_data[offset + 2] = (unsigned char) l; - d = _texture_data[offset+1]; - if (l > AMBIENT) { - l -= d*decay; - if (l < AMBIENT) - l = AMBIENT; - } - - i++; - xx = x + _ray_templ[i][0]; - yy = y + _ray_templ[i][1]; - zz = z + _ray_templ[i][2]; - - } while ((xx>=0)&&(xx=0)&&(yy=0)&&(zz0) ? 0 : n-1; - int sy = (_light_dir[1]>0) ? 0 : n-1; - int sz = (_light_dir[2]>0) ? 0 : n-1; - - float decay = 1.0f/(n*DECAY); - - for (i=0; i 0) ? 1 : -1; - int yinc = (ly > 0) ? 1 : -1; - int zinc = (lz > 0) ? 1 : -1; - float tx, ty, tz; - int i = 1; - int len = 0; - int maxlen = 3*edgelen*edgelen; - _ray_templ[0][0] = _ray_templ[0][2] = _ray_templ[0][2] = 0; + Cloth *cloth = clmd->clothObject; + int _N; + fc *m_fc = NULL; - while (len <= maxlen) - { - // fx + t*lx = (x+1) -> t = (x+1-fx)/lx - tx = (x+xinc-fx)/lx; - ty = (y+yinc-fy)/ly; - tz = (z+zinc-fz)/lz; + if(!cloth) + return 0; + + m_fc = cloth->m_fc; - if ((tx<=ty)&&(tx<=tz)) { - _ray_templ[i][0] = _ray_templ[i-1][0] + xinc; - x =+ xinc; - fx = x; + m_fc->_fp = fopen("/home/daniel/Desktop/f32rand.dat", "rb"); + if (!m_fc->_fp) + return 0; - if (ALMOST_EQUAL(ty,tx)) { - _ray_templ[i][1] = _ray_templ[i-1][1] + yinc; - y += yinc; - fy = y; - } else { - _ray_templ[i][1] = _ray_templ[i-1][1]; - fy += tx*ly; - } - - if (ALMOST_EQUAL(tz,tx)) { - _ray_templ[i][2] = _ray_templ[i-1][2] + zinc; - z += zinc; - fz = z; - } else { - _ray_templ[i][2] = _ray_templ[i-1][2]; - fz += tx*lz; - } - } else if ((ty0)&&(t<2)) { - ret[num][0] = edges[i][0][0] + edges[i][1][0]*t; - ret[num][1] = edges[i][0][1] + edges[i][1][1]*t; - ret[num][2] = edges[i][0][2] + edges[i][1][2]*t; - num++; - } - } - - return num; -} - -void draw_slices(float m[][4]) -{ - int i; - - Vec3 viewdir(m[0][2], m[1][2], m[2][2]); - viewdir.Normalize(); - // find cube vertex that is closest to the viewer - for (i=0; i<8; i++) { - float x = cv[i][0] + viewdir[0]; - float y = cv[i][1] + viewdir[1]; - float z = cv[i][2] + viewdir[2]; - if ((x>=-1.0f)&&(x<=1.0f) - &&(y>=-1.0f)&&(y<=1.0f) - &&(z>=-1.0f)&&(z<=1.0f)) - { - break; - } - } - if(i != 8) return; - - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glDisable(GL_DEPTH_TEST); - // our slices are defined by the plane equation a*x + b*y +c*z + d = 0 - // (a,b,c), the plane normal, are given by viewdir - // d is the parameter along the view direction. the first d is given by - // inserting previously found vertex into the plane equation - float d0 = -(viewdir[0]*cv[i][0] + viewdir[1]*cv[i][1] + viewdir[2]*cv[i][2]); - float dd = 2*d0/64.0f; - int n = 0; - for (float d = -d0; d < d0; d += dd) { - // intersect_edges returns the intersection points of all cube edges with - // the given plane that lie within the cube - float pt[12][3]; - int num = intersect_edges(pt, viewdir[0], viewdir[1], viewdir[2], d); - - if (num > 2) { - // sort points to get a convex polygon - // std::sort(pt.begin()+1, pt.end(), Convexcomp(pt[0], viewdir)); - int shuffled = 1; - - while(shuffled) - { - int j; - shuffled = 0; - - for(j = 0; j < num-1; j++) - { - // Vec3 va = a-p0, vb = b-p0; - // return dot(up, cross(va, vb)) >= 0; - float va[3], vb[3], vc[3]; - - VECSUB(va, pt[j], pt[0]); - VECSUB(vb, pt[j+1], pt[0]); - Crossf(vc, va, vb); - - if(INPR(viewdir, vc)>= 0) - { - float temp[3]; - - VECCOPY(temp, pt[j]); - VECCOPY(pt[j], pt[j+1]); - VECCOPY(pt[j+1], temp); - - shuffled = 1; - } - } - } - - glEnable(GL_TEXTURE_3D); - glEnable(GL_FRAGMENT_PROGRAM_ARB); - glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, _prog[0]); - glActiveTextureARB(GL_TEXTURE0_ARB); - glBindTexture(GL_TEXTURE_3D, _txt[0]); - glBegin(GL_POLYGON); - for (i=0; i_fp); + fread(&_N, sizeof(int), 1, m_fc->_fp); + printf("Resolution: %dx%dx%d\n", _N, _N, _N); + + fread(&m_fc->_nframes, sizeof(int), 1, m_fc->_fp); + printf("Number of frames: %d\n", m_fc->_nframes); + m_fc->_cur_frame = 0; + + return 1; } -void draw(void) -{ - int i; - - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - gluLookAt(0, 0, -_dist, 0, 0, 0, 0, 1, 0); - - float m[4][4]; - build_rotmatrix(m, _quat); - - glMultMatrixf(&m[0][0]); - - if (_draw_cube) - draw_cube(); - draw_slices(m, _draw_slice_outline); - - if (_dispstring != NULL) { - glMatrixMode(GL_PROJECTION); - glLoadMatrixd(_ortho_m); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glDisable(GL_TEXTURE_3D); - glDisable(GL_FRAGMENT_PROGRAM_ARB); - glColor4f(1.0, 1.0, 1.0, 1.0); - glRasterPos2i(-_sx/2 + 10, _sy/2 - 15); - - print_string(_dispstring); - - glMatrixMode(GL_PROJECTION); - glLoadMatrixd(_persp_m); - glMatrixMode(GL_MODELVIEW); - } -}*/ /************************************************ * clothModifier_do - main simulation function @@ -819,9 +544,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d float current_time = bsystem_time(ob, (float)G.scene->r.cfra, 0.0); ListBase *effectors = NULL; float deltaTime = current_time - clmd->sim_parms->sim_time; - unsigned char* _texture_data=NULL; - float _light_dir[3]; - int _ray_templ[4096][3]; clmd->sim_parms->dt = 1.0f / (clmd->sim_parms->stepsPerFrame * G.scene->r.frs_sec); @@ -1216,6 +938,9 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d cloth->m_fc = f_init(); + // open file + m_fc_open(clmd); + switch (ob->type) { case OB_MESH: @@ -1895,8 +1620,7 @@ fc *f_init(void) int i; int size; - fc *m_fc = MEM_callocN(sizeof(fc), - "f_c"); + fc *m_fc = MEM_callocN(sizeof(fc), "f_c"); for (i=0; i<10; i++) clear_buffer(buffers[i]); @@ -1913,12 +1637,24 @@ fc *f_init(void) for (i=0; iv[i] = -0.5f; + m_fc->_texture_data = (unsigned char*) MEM_callocN((30+2)*(30+2)*(30+2)*4, "fc_texture_data"); + + m_fc->_fp = 0; + return m_fc; } void f_free(fc *m_fc) { if(m_fc) + { + if(m_fc->_texture_data) + MEM_freeN(m_fc->_texture_data); + + if(m_fc->_fp) + fclose(m_fc->_fp); + MEM_freeN(m_fc); + } } diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index db2225f4823..a6fced7124a 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -78,6 +78,7 @@ #include "BLI_rand.h" #include "BKE_utildefines.h" +#include "BKE_cloth.h" #include "BKE_curve.h" #include "BKE_constraint.h" // for the get_constraint_target function #include "BKE_DerivedMesh.h" @@ -2174,6 +2175,345 @@ static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, Derived /* Mesh drawing routines */ + + +#define AMBIENT 50 +#define DECAY 0.04f +#define ALMOST_EQUAL(a, b) ((fabs(a-b)<0.00001f)?1:0) + + // cube vertices +GLfloat cv[][3] = { + {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f}, + {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f} +}; + + // edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] +float edges[12][2][3] = { + {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 1.0f}}, + + {{1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}}, + {{-1.0f, -1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}}, + {{-1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}}, + {{1.0f, -1.0f, -1.0f}, {0.0f, 1.0f, 0.0f}}, + + {{-1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}}, + {{-1.0f, -1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}}, + {{-1.0f, -1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}}, + {{-1.0f, 1.0f, -1.0f}, {1.0f, 0.0f, 0.0f}} +}; + +void light_ray(unsigned char* _texture_data, int _ray_templ[4096][3], int x, int y, int z, int n, float decay) +{ + int xx = x, yy = y, zz = z, i = 0; + int offset; + + int l = 255; + float d; + + do { + offset = ((((zz*n) + yy)*n + xx) << 2); + if (_texture_data[offset + 2] > 0) + _texture_data[offset + 2] = (unsigned char) ((_texture_data[offset + 2] + l)*0.5f); + else + _texture_data[offset + 2] = (unsigned char) l; + d = _texture_data[offset+1]; + if (l > AMBIENT) { + l -= d*decay; + if (l < AMBIENT) + l = AMBIENT; + } + + i++; + xx = x + _ray_templ[i][0]; + yy = y + _ray_templ[i][1]; + zz = z + _ray_templ[i][2]; + + } while ((xx>=0)&&(xx=0)&&(yy=0)&&(zz0) ? 0 : n-1; + int sy = (_light_dir[1]>0) ? 0 : n-1; + int sz = (_light_dir[2]>0) ? 0 : n-1; + + float decay = 1.0f/(n*DECAY); + + for (i=0; i 0) ? 1 : -1; + int yinc = (ly > 0) ? 1 : -1; + int zinc = (lz > 0) ? 1 : -1; + float tx, ty, tz; + int i = 1; + int len = 0; + int maxlen = 3*edgelen*edgelen; + _ray_templ[0][0] = _ray_templ[0][2] = _ray_templ[0][2] = 0; + + while (len <= maxlen) + { + // fx + t*lx = (x+1) -> t = (x+1-fx)/lx + tx = (x+xinc-fx)/lx; + ty = (y+yinc-fy)/ly; + tz = (z+zinc-fz)/lz; + + if ((tx<=ty)&&(tx<=tz)) { + _ray_templ[i][0] = _ray_templ[i-1][0] + xinc; + x =+ xinc; + fx = x; + + if (ALMOST_EQUAL(ty,tx)) { + _ray_templ[i][1] = _ray_templ[i-1][1] + yinc; + y += yinc; + fy = y; + } else { + _ray_templ[i][1] = _ray_templ[i-1][1]; + fy += tx*ly; + } + + if (ALMOST_EQUAL(tz,tx)) { + _ray_templ[i][2] = _ray_templ[i-1][2] + zinc; + z += zinc; + fz = z; + } else { + _ray_templ[i][2] = _ray_templ[i-1][2]; + fz += tx*lz; + } + } else if ((ty0)&&(t<2)) { + ret[num][0] = edges[i][0][0] + edges[i][1][0]*t; + ret[num][1] = edges[i][0][1] + edges[i][1][1]*t; + ret[num][2] = edges[i][0][2] + edges[i][1][2]*t; + num++; + } + } + + return num; +} + +void draw_slices ( float m[][4] ) +{ + int i; + + float viewdir[3]; + float d0; + float dd; + int n; + float d; + + viewdir[0] = m[0][2]; + viewdir[1] = m[1][2]; + viewdir[2] = m[2][2]; + Normalize(viewdir); + + // find cube vertex that is closest to the viewer + for ( i=0; i<8; i++ ) + { + float x = cv[i][0] + viewdir[0]; + float y = cv[i][1] + viewdir[1]; + float z = cv[i][2] + viewdir[2]; + if ( ( x>=-1.0f ) && ( x<=1.0f ) + && ( y>=-1.0f ) && ( y<=1.0f ) + && ( z>=-1.0f ) && ( z<=1.0f ) ) + { + break; + } + } + if ( i != 8 ) return; + + glBlendFunc ( GL_SRC_ALPHA, GL_ONE ); + glDisable ( GL_DEPTH_TEST ); + // our slices are defined by the plane equation a*x + b*y +c*z + d = 0 + // (a,b,c), the plane normal, are given by viewdir + // d is the parameter along the view direction. the first d is given by + // inserting previously found vertex into the plane equation + d0 = - ( viewdir[0]*cv[i][0] + viewdir[1]*cv[i][1] + viewdir[2]*cv[i][2] ); + dd = 2*d0/64.0f; + n = 0; + + for ( d = -d0; d < d0; d += dd ) + { + // intersect_edges returns the intersection points of all cube edges with + // the given plane that lie within the cube + float pt[12][3]; + int num = intersect_edges ( pt, viewdir[0], viewdir[1], viewdir[2], d ); + + if ( num > 2 ) + { + // sort points to get a convex polygon + // std::sort(pt.begin()+1, pt.end(), Convexcomp(pt[0], viewdir)); + int shuffled = 1; + + while ( shuffled ) + { + int j; + shuffled = 0; + + for ( j = 0; j < num-1; j++ ) + { + // Vec3 va = a-p0, vb = b-p0; + // return dot(up, cross(va, vb)) >= 0; + float va[3], vb[3], vc[3]; + + VECSUB ( va, pt[j], pt[0] ); + VECSUB ( vb, pt[j+1], pt[0] ); + Crossf ( vc, va, vb ); + + if ( INPR ( viewdir, vc ) >= 0 ) + { + float temp[3]; + + VECCOPY ( temp, pt[j] ); + VECCOPY ( pt[j], pt[j+1] ); + VECCOPY ( pt[j+1], temp ); + + shuffled = 1; + } + } + } +/* + glEnable ( GL_TEXTURE_3D ); + glEnable ( GL_FRAGMENT_PROGRAM_ARB ); + glBindProgramARB ( GL_FRAGMENT_PROGRAM_ARB, _prog[0] ); + glActiveTextureARB ( GL_TEXTURE0_ARB ); + glBindTexture ( GL_TEXTURE_3D, _txt[0] ); + glBegin ( GL_POLYGON ); + for ( i=0; iclothObject; + fc *m_fc = NULL; + + if(!cloth) + return; + + m_fc = cloth->m_fc; + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + // gluLookAt(0, 0, -_dist, 0, 0, 0, 0, 1, 0); + + // build_rotmatrix(m, _quat); + + glMultMatrixf(&m[0][0]); + + // ---------------------------------------- + // from ligth constructor + m_fc->_light_dir[0] = -1.0f; + m_fc->_light_dir[1] = 0.5f; + m_fc->_light_dir[2] = 0.0f; + + gen_ray_templ(m_fc->_ray_templ, m_fc->_light_dir, 30 + 2); + + cast_light(m_fc->_texture_data, m_fc->_ray_templ, m_fc->_light_dir, 30+2); + + glActiveTextureARB(GL_TEXTURE0_ARB); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 30+2, 30+2, 30+2, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_fc->_texture_data); + // ---------------------------------------- + + draw_slices(m); +/* + if (_dispstring != NULL) { + glMatrixMode(GL_PROJECTION); + glLoadMatrixd(_ortho_m); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glDisable(GL_TEXTURE_3D); + glDisable(GL_FRAGMENT_PROGRAM_ARB); + glColor4f(1.0, 1.0, 1.0, 1.0); + glRasterPos2i(-_sx/2 + 10, _sy/2 - 15); + + print_string(_dispstring); + + glMatrixMode(GL_PROJECTION); + glLoadMatrixd(_persp_m); + glMatrixMode(GL_MODELVIEW); + } +*/ +} + static void draw_mesh_object_outline(Object *ob, DerivedMesh *dm) { From 5b9a06e041240301d6ee527eaceea29704783346 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 2 Jan 2008 13:51:44 +0000 Subject: [PATCH 069/101] Pre merge commit, only added debug output so far --- source/blender/blenkernel/intern/implicit.c | 6 ++- source/blender/src/drawobject.c | 48 ++++++++++++++++++++- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 9e4428c1055..a1d60b34125 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1687,8 +1687,7 @@ int collisions_collision_response_static ( ClothModifierData *clmd, CollisionMod // If v_n_mag < 0 the edges are approaching each other. if ( magrelVel < -ALMOST_ZERO ) { - printf("magrelVel < -ALMOST_ZERO\n"); - + // Calculate Impulse magnitude to stop all motion in normal direction. // const double I_mag = v_n_mag / (1/m1 + 1/m2); float magnitude_i = magrelVel / 2.0f; // TODO implement masses @@ -1697,6 +1696,8 @@ int collisions_collision_response_static ( ClothModifierData *clmd, CollisionMod float vrel_t[3]; double impulse; float overlap = ( epsilon + ALMOST_ZERO-collpair->distance ); + + printf("magrelVel < -ALMOST_ZERO\n"); // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); @@ -1737,6 +1738,7 @@ int collisions_collision_response_static ( ClothModifierData *clmd, CollisionMod collmd->verts[collpair->point_indexB[2]].impulse_count++; */ + result = 1; // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index a6fced7124a..111f0789ee9 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -2483,7 +2483,7 @@ void draw_fl(ClothModifierData *clmd) m_fc->_light_dir[0] = -1.0f; m_fc->_light_dir[1] = 0.5f; m_fc->_light_dir[2] = 0.0f; - + gen_ray_templ(m_fc->_ray_templ, m_fc->_light_dir, 30 + 2); cast_light(m_fc->_texture_data, m_fc->_ray_templ, m_fc->_light_dir, 30+2); @@ -2514,6 +2514,52 @@ void draw_fl(ClothModifierData *clmd) */ } +void fc_load_frame(ClothModifierData *clmd) +{ + float* tmp = (float*) MEM_callocN(30*30*30*sizeof(float), "fc_tmp"); + float tmin=9999999, tmax=-99999999; + Cloth *cloth = clmd->clothObject; + fc *m_fc = NULL; + int i = 0; + + if(!cloth) + return; + + m_fc = cloth->m_fc; + + if (++m_fc->_cur_frame == m_fc->_nframes) { + fseek(m_fc->_fp, 12, SEEK_SET); + m_fc->_cur_frame = 0; + } + + fread(tmp, sizeof(float), 30*30*30, m_fc->_fp); + + for (i=0; i<30*30*30; i++) + { + m_fc->_texture_data[(i<<2)+1] = (unsigned char) (tmp[i]*255.0f); + } + + fread(tmp, sizeof(float), 30*30*30, m_fc->_fp); + + for (i=0; i<30*30*30; i++) + { + m_fc->_texture_data[(i<<2)] = (unsigned char) (tmp[i]*255.0f); + if (tmp[i]tmax) + tmax = tmp[i]; + m_fc->_texture_data[(i<<2)+2] = 0; + m_fc->_texture_data[(i<<2)+3] = 255; + } + + MEM_freeN(tmp); + + // cast_light(_N); DG NOT NEEDED + + glActiveTextureARB(GL_TEXTURE0_ARB); + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 30, 30, 30, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_fc->_texture_data); +} + static void draw_mesh_object_outline(Object *ob, DerivedMesh *dm) { From 8d6bbf763504af934a859573ba45880159bc1828 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 7 Jan 2008 03:20:43 +0000 Subject: [PATCH 070/101] Merged back with last version where collisions worked at least a bit (rev 12296). Also merged fixes (hopefully). --- CMakeLists.txt | 23 +- source/blender/blenkernel/BKE_cloth.h | 188 +- source/blender/blenkernel/BKE_modifier.h | 2 +- source/blender/blenkernel/intern/cloth.c | 1667 +++++++----------- source/blender/blenkernel/intern/collision.c | 900 +++++++++- source/blender/blenkernel/intern/implicit.c | 1200 ++----------- source/blender/blenkernel/intern/modifier.c | 221 +-- source/blender/blenloader/intern/readfile.c | 5 +- source/blender/blenloader/intern/writefile.c | 2 + source/blender/makesdna/DNA_cloth_types.h | 102 +- source/blender/makesdna/DNA_modifier_types.h | 6 +- source/blender/src/buttons_object.c | 193 +- source/blender/src/drawobject.c | 106 -- source/blender/src/vpaint.c | 7 +- 14 files changed, 2043 insertions(+), 2579 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d79c2220104..4eb5e9c659d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,8 +65,9 @@ OPTION(WITH_ELBEEM "Enable Elbeem (Fluid Simulation)" ON) OPTION(WITH_QUICKTIME "Enable Quicktime Support" OFF) OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" OFF) OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF) -OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) -OPTION(YESIAMSTUPID "Enable execution on 64-bit platforms" OFF) +OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) +OPTION(YESIAMSTUPID "Enable execution on 64-bit platforms" OFF) +OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF) IF(NOT WITH_GAMEENGINE AND WITH_PLAYER) MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE") @@ -184,6 +185,13 @@ IF(UNIX) SET(LLIBS "-lXi -lutil -lc -lm -lpthread -lstdc++") + IF(WITH_OPENMP) + SET(LLIBS "${LLIBS} -lgomp ") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp ") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp ") + ENDIF(WITH_OPENMP) + + SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -DXP_UNIX -Wno-char-subscripts") SET(PLATFORM_LINKFLAGS "-pthread") @@ -270,6 +278,11 @@ IF(WIN32) SET(CMAKE_C_FLAGS_MINSIZEREL "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE) SET(CMAKE_C_FLAGS_RELWITHDEBINFO "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE) + IF(WITH_OPENMP) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /openmp ") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp ") + ENDIF(WITH_OPENMP) + SET(SDL ${LIBDIR}/sdl) SET(SDL_INC ${SDL}/include) SET(SDL_LIB SDL) @@ -347,6 +360,12 @@ IF(APPLE) SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") SET(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime") + IF(WITH_OPENMP) + SET(LLIBS "${LLIBS} -lgomp ") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp ") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp ") + ENDIF(WITH_OPENMP) + SET(SDL ${LIBDIR}/sdl) SET(SDL_INC ${SDL}/include) SET(SDL_LIB SDL) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index b122347998d..eb1f33ae600 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -34,14 +34,14 @@ #ifndef BKE_CLOTH_H #define BKE_CLOTH_H -#include "BKE_customdata.h" #include "BLI_linklist.h" +#include "BKE_customdata.h" #include "BKE_DerivedMesh.h" -#include "BKE_object.h" - #include "DNA_cloth_types.h" #include "DNA_customdata_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" struct Object; struct Cloth; @@ -49,8 +49,8 @@ struct MFace; struct DerivedMesh; struct ClothModifierData; -// this is needed for inlining behaviour +// this is needed for inlining behaviour #ifndef _WIN32 #define LINUX #define DO_INLINE inline @@ -60,71 +60,6 @@ struct ClothModifierData; #define CLOTH_MAX_THREAD 2 -typedef struct fc -{ - float *d, *d0; // density - float *T, *T0; // temperature - float *u, *u0; // velocity in x direction - float *v, *v0; // velocity in y direction - float *w, *w0; // velocity in z direction - unsigned char* _texture_data; - float _light_dir[3]; - int _ray_templ[4096][3]; - FILE* _fp; - int _cur_frame; - int _nframes; -} fc; -fc *f_init(void); -void f_free(fc *m_fc); -void step(fc *m_fc, float dt); - - -typedef struct ClothVertex { - int flags; /* General flags per vertex. */ - float mass; /* mass / weight of the vertex */ - float goal; /* goal, from SB */ - float impulse[3]; /* used in collision.c */ - unsigned int impulse_count; /* same as above */ - float collball; - char octantflag; - float weight; -} ClothVertex; - -typedef struct ClothSpring { - unsigned int ij; /* Pij from the paper, one end of the spring. */ - unsigned int kl; /* Pkl from the paper, one end of the spring. */ - float restlen; /* The original length of the spring. */ - unsigned int matrix_index; /* needed for implicit solver (fast lookup) */ - int type; /* types defined in BKE_cloth.h ("springType") */ - int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ - float dfdx[3][3]; - float dfdv[3][3]; - float f[3]; -} ClothSpring; - -typedef struct Cloth { - struct ClothVertex *verts; /* The vertices that represent this cloth. */ - struct LinkNode *springs; /* The springs connecting the mesh. */ - struct BVH *tree; /* collision tree for this cloth object */ - struct BVH *selftree; /* self collision tree for this cloth object */ - struct MFace *mfaces; - struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ - struct EdgeHash *edgehash; /* used for fast checking adjacent points */ - unsigned int numverts; /* The number of verts == m * n. */ - unsigned int numsprings; /* The count of springs. */ - unsigned int numfaces; - unsigned int numothersprings; - unsigned int numspringssave; - unsigned int old_solver_type; - float (*x)[3]; /* The current position of all vertices.*/ - float (*xold)[3]; /* The previous position of all vertices.*/ - float (*current_x)[3]; /* The TEMPORARY current position of all vertices.*/ - float (*current_xold)[3]; /* The TEMPORARY previous position of all vertices.*/ - float (*v)[4]; /* the current velocity of all vertices */ - float (*current_v)[3]; - float (*xconst)[3]; - struct fc *m_fc; -} Cloth; /* goal defines */ #define SOFTGOALSNAP 0.999f @@ -155,9 +90,7 @@ typedef enum CLOTH_SIMSETTINGS_FLAG_COLLOBJ = ( 1 << 2 ), // object is only collision object, no cloth simulation is done CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ), // we have goals enabled CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ), // true if tearing is enabled - CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ), - CLOTH_SIMSETTINGS_FLAG_BIG_FORCE = ( 1 << 6 ), // true if we have big spring force for bending - CLOTH_SIMSETTINGS_FLAG_SLEEP = ( 1 << 7 ), // true if we let the cloth go to sleep + CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ), // true if tearing is enabled } CLOTH_SIMSETTINGS_FLAGS; /* SPRING FLAGS */ @@ -172,7 +105,6 @@ typedef enum CLOTH_SPRING_TYPE_STRUCTURAL = 0, CLOTH_SPRING_TYPE_SHEAR, CLOTH_SPRING_TYPE_BENDING, - CLOTH_SPRING_TYPE_COLLISION, } CLOTH_SPRING_TYPES; /* SPRING FLAGS */ @@ -188,32 +120,91 @@ typedef enum // needed for buttons_object.c -void cloth_clear_cache(struct Object *ob, struct ClothModifierData *clmd, float framenr); -void cloth_free_modifier ( struct ClothModifierData *clmd ); +void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr); // needed for cloth.c -void implicit_set_positions ( struct ClothModifierData *clmd ); +void implicit_set_positions ( ClothModifierData *clmd ); // from cloth.c, needed for modifier.c -DerivedMesh *clothModifier_do(struct ClothModifierData *clmd, struct Object *ob, struct DerivedMesh *dm, int useRenderParams, int isFinalCalc); +void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float ( *vertexCos ) [3], int numverts ); -// needed in implicit.c -int cloth_bvh_objcollision(struct ClothModifierData *clmd, float step, float prevstep, float dt); +// used in collision.c +typedef struct Tree +{ + struct Tree *nodes[4]; // 4 children --> quad-tree + struct Tree *parent; + struct Tree *nextLeaf; + struct Tree *prevLeaf; + float bv[26]; // Bounding volume of all nodes / we have 7 axes on a 14-DOP + unsigned int tri_index; // this saves the index of the face + int count_nodes; // how many nodes are used + int traversed; // how many nodes already traversed until this level? + int isleaf; +} +Tree; + +typedef struct Tree TreeNode; + +typedef struct BVH +{ + unsigned int numfaces; + unsigned int numverts; + ClothVertex *verts; // just a pointer to the original datastructure + MFace *mfaces; // just a pointer to the original datastructure + struct LinkNode *tree; + TreeNode *root; // TODO: saving the root --> is this really needed? YES! + TreeNode *leaf_tree; /* Tail of the leaf linked list. */ + TreeNode *leaf_root; /* Head of the leaf linked list. */ + float epsilon; /* epslion is used for inflation of the k-dop */ + int flags; /* bvhFlags */ +} +BVH; + +typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 ); + + +///////////////////////////////////////////////// +// collision.c +//////////////////////////////////////////////// + +// needed for implicit.c +void bvh_collision_response ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 ); +int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ); //////////////////////////////////////////////// +///////////////////////////////////////////////// +// kdop.c +//////////////////////////////////////////////// + +// needed for cloth.c +void bvh_free ( BVH * bvh ); +BVH *bvh_build ( ClothModifierData *clmd, float epsilon ); +LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr ); + +// needed for collision.c +int bvh_traverse ( ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response ); +void bvh_update ( ClothModifierData * clmd, BVH * bvh, int moving ); + +//////////////////////////////////////////////// + + + ///////////////////////////////////////////////// // cloth.c //////////////////////////////////////////////// -void cloth_free_modifier ( struct ClothModifierData *clmd ); -void cloth_init ( struct ClothModifierData *clmd ); +void cloth_free_modifier ( ClothModifierData *clmd ); +void cloth_init ( ClothModifierData *clmd ); +void cloth_deform_verts ( struct Object *ob, float framenr, float ( *vertexCos ) [3], int numVerts, void *derivedData, ClothModifierData *clmd ); +void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int totface ); + //////////////////////////////////////////////// /* Typedefs for function pointers we need for solvers and collision detection. */ -typedef void ( *CM_COLLISION_SELF ) ( struct ClothModifierData *clmd, int step ); -// typedef void ( *CM_COLLISION_OBJ ) ( ClothModifierData *clmd, int step, CM_COLLISION_RESPONSE collision_response ); +typedef void ( *CM_COLLISION_SELF ) ( ClothModifierData *clmd, int step ); +typedef void ( *CM_COLLISION_OBJ ) ( ClothModifierData *clmd, int step, CM_COLLISION_RESPONSE collision_response ); /* This enum provides the IDs for our solvers. */ @@ -229,26 +220,29 @@ typedef struct { char *name; CM_SOLVER_ID id; - int ( *init ) ( struct Object *ob, struct ClothModifierData *clmd ); - int ( *solver ) ( struct Object *ob, float framenr, struct ClothModifierData *clmd, struct ListBase *effectors ); - int ( *free ) ( struct ClothModifierData *clmd ); + int ( *init ) ( Object *ob, ClothModifierData *clmd ); + int ( *solver ) ( Object *ob, float framenr, ClothModifierData *clmd, ListBase *effectors ); + int ( *free ) ( ClothModifierData *clmd ); } CM_SOLVER_DEF; /* new C implicit simulator */ -int implicit_init ( struct Object *ob, struct ClothModifierData *clmd ); -int implicit_free ( struct ClothModifierData *clmd ); -int implicit_solver ( struct Object *ob, float frame, struct ClothModifierData *clmd, struct ListBase *effectors ); - -/* explicit verlet simulator */ -int verlet_init ( struct Object *ob, struct ClothModifierData *clmd ); -int verlet_free ( struct ClothModifierData *clmd ); -int verlet_solver ( struct Object *ob, float frame, struct ClothModifierData *clmd, struct ListBase *effectors ); +int implicit_init ( Object *ob, ClothModifierData *clmd ); +int implicit_free ( ClothModifierData *clmd ); +int implicit_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors ); +/* used for caching in implicit.c */ +typedef struct Frame +{ + ClothVertex *verts; + ClothSpring *springs; + unsigned int numverts, numsprings; + float time; /* we need float since we want to support sub-frames */ +} +Frame; /* used for collisions in collision.c */ -/* typedef struct CollPair { unsigned int face1; // cloth face @@ -263,7 +257,6 @@ typedef struct CollPair unsigned int pointsb[4]; } CollPair; -*/ /* used for collisions in collision.c */ typedef struct EdgeCollPair @@ -289,8 +282,5 @@ typedef struct FaceCollPair } FaceCollPair; -// function definitions from implicit.c -DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar); - #endif diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 8927584de1b..682eb1a00dd 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -287,7 +287,7 @@ int modifiers_getCageIndex(struct Object *ob, int *lastPossibleCageIndex_r); int modifiers_isSoftbodyEnabled(struct Object *ob); -struct ClothModifierData *modifiers_isClothEnabled(Object *ob); +ModifierData * modifiers_isClothEnabled(Object *ob); int modifiers_isParticleEnabled(struct Object *ob); struct Object *modifiers_isDeformedByArmature(struct Object *ob); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 318d6eac410..fef932174a1 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -39,15 +39,15 @@ /* types */ #include "DNA_curve_types.h" -#include "DNA_cloth_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" +#include "DNA_cloth_types.h" #include "DNA_key_types.h" -#include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" -#include "DNA_modifier_types.h" +#include "DNA_lattice_types.h" #include "DNA_scene_types.h" +#include "DNA_modifier_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -55,8 +55,6 @@ #include "BLI_linklist.h" #include "BKE_curve.h" -#include "BKE_cloth.h" -#include "BKE_collisions.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" #include "BKE_cdderivedmesh.h" @@ -65,11 +63,11 @@ #include "BKE_global.h" #include "BKE_key.h" #include "BKE_mesh.h" -#include "BKE_modifier.h" #include "BKE_object.h" -#include "BKE_pointcache.h" +#include "BKE_cloth.h" +#include "BKE_modifier.h" #include "BKE_utildefines.h" - +#include "BKE_DerivedMesh.h" #include "BIF_editdeform.h" #include "BIF_editkey.h" #include "DNA_screen_types.h" @@ -78,21 +76,7 @@ #include "BIF_space.h" #include "mydevice.h" -#ifdef WIN32 -#include -#endif // WIN32 -#ifdef __APPLE__ -#define GL_GLEXT_LEGACY 1 -#include -#include -#else -#include -#if defined(__sun__) && !defined(__sparc__) -#include -#else -#include -#endif -#endif +#include "BKE_pointcache.h" #ifdef _WIN32 void tstart ( void ) @@ -106,9 +90,9 @@ double tval() } #else #include - static struct timeval _tstart, _tend; - static struct timezone tz; - void tstart ( void ) +static struct timeval _tstart, _tend; +static struct timezone tz; +void tstart ( void ) { gettimeofday ( &_tstart, &tz ); } @@ -128,82 +112,88 @@ double tval() /* Our available solvers. */ // 255 is the magic reserved number, so NEVER try to put 255 solvers in here! // 254 = MAX! -static CM_SOLVER_DEF solvers [] = -{ - { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free }, -}; +static CM_SOLVER_DEF solvers [] = + { + { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free }, + // { "Implicit C++", CM_IMPLICITCPP, implicitcpp_init, implicitcpp_solver, implicitcpp_free }, + }; /* ********** cloth engine ******* */ /* Prototypes for internal functions. */ -static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd); -static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr); -static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr); +static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ); +static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); +static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts, float framenr ); +static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ); +int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ); +static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ); + -int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); -static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup); /****************************************************************************** * * External interface called by modifier.c clothModifier functions. * ******************************************************************************/ /** - * cloth_init - creates a new cloth simulation. - * - * 1. create object - * 2. fill object with standard values or with the GUI settings if given - */ -void cloth_init (ClothModifierData *clmd) +* cloth_init - creates a new cloth simulation. +* +* 1. create object +* 2. fill object with standard values or with the GUI settings if given +*/ +void cloth_init ( ClothModifierData *clmd ) { /* Initialize our new data structure to reasonable values. */ - clmd->sim_parms->gravity [0] = 0.0; - clmd->sim_parms->gravity [1] = 0.0; - clmd->sim_parms->gravity [2] = -9.81; - clmd->sim_parms->structural = 100.0; - clmd->sim_parms->shear = 100.0; - clmd->sim_parms->bending = 1.0; - clmd->sim_parms->Cdis = 5.0; - clmd->sim_parms->Cvi = 1.0; - clmd->sim_parms->mass = 1.0f; - clmd->sim_parms->stepsPerFrame = 5; - clmd->sim_parms->sim_time = 1.0; - clmd->sim_parms->flags = CLOTH_SIMSETTINGS_FLAG_RESET; - clmd->sim_parms->solver_type = 0; - clmd->sim_parms->preroll = 0; - clmd->sim_parms->maxspringlen = 10; - clmd->coll_parms->self_friction = 5.0; - clmd->coll_parms->friction = 10.0; - clmd->coll_parms->loop_count = 1; - clmd->coll_parms->epsilon = 0.01; - clmd->coll_parms->selfepsilon = 0.49; - + clmd->sim_parms.gravity [0] = 0.0; + clmd->sim_parms.gravity [1] = 0.0; + clmd->sim_parms.gravity [2] = -9.81; + clmd->sim_parms.structural = 100.0; + clmd->sim_parms.shear = 100.0; + clmd->sim_parms.bending = 1.0; + clmd->sim_parms.Cdis = 5.0; + clmd->sim_parms.Cvi = 1.0; + clmd->sim_parms.mass = 1.0f; + clmd->sim_parms.stepsPerFrame = 5; + clmd->sim_parms.sim_time = 1.0; + clmd->sim_parms.flags = CLOTH_SIMSETTINGS_FLAG_RESET; + clmd->sim_parms.solver_type = 0; + clmd->sim_parms.preroll = 0; + clmd->sim_parms.maxspringlen = 10; + clmd->sim_parms.firstframe = 1; + clmd->sim_parms.lastframe = 250; + clmd->coll_parms.self_friction = 5.0; + clmd->coll_parms.friction = 10.0; + clmd->coll_parms.loop_count = 1; + clmd->coll_parms.epsilon = 0.01f; + clmd->coll_parms.flags = 0; + /* These defaults are copied from softbody.c's * softbody_calc_forces() function. */ - clmd->sim_parms->eff_force_scale = 1000.0; - clmd->sim_parms->eff_wind_scale = 250.0; + clmd->sim_parms.eff_force_scale = 1000.0; + clmd->sim_parms.eff_wind_scale = 250.0; // also from softbodies - clmd->sim_parms->maxgoal = 1.0; - clmd->sim_parms->mingoal = 0.0; - clmd->sim_parms->defgoal = 0.0; - clmd->sim_parms->goalspring = 100.0; - clmd->sim_parms->goalfrict = 0.0; + clmd->sim_parms.maxgoal = 1.0f; + clmd->sim_parms.mingoal = 0.0f; + clmd->sim_parms.defgoal = 0.7f; + clmd->sim_parms.goalspring = 100.0f; + clmd->sim_parms.goalfrict = 0.0f; + + clmd->sim_parms.cache = NULL; } // unused in the moment, cloth needs quads from mesh -DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) +DerivedMesh *CDDM_convert_to_triangle ( DerivedMesh *dm ) { - /* DerivedMesh *result = NULL; int i; - int numverts = dm->getNumVerts(dm); - int numedges = dm->getNumEdges(dm); - int numfaces = dm->getNumFaces(dm); + int numverts = dm->getNumVerts ( dm ); + int numedges = dm->getNumEdges ( dm ); + int numfaces = dm->getNumFaces ( dm ); - MVert *mvert = CDDM_get_verts(dm); - MEdge *medge = CDDM_get_edges(dm); - MFace *mface = CDDM_get_faces(dm); + MVert *mvert = CDDM_get_verts ( dm ); + MEdge *medge = CDDM_get_edges ( dm ); + MFace *mface = CDDM_get_faces ( dm ); MVert *mvert2; MFace *mface2; @@ -215,121 +205,118 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) float vec1[3], vec2[3], vec3[3], vec4[3], vec5[3]; float mag1=0, mag2=0; - for(i = 0; i < numfaces; i++) + for ( i = 0; i < numfaces; i++ ) { - if(mface[i].v4) - numquads++; - else - numtris++; -} + if ( mface[i].v4 ) + numquads++; + else + numtris++; + } - result = CDDM_from_template(dm, numverts, 0, numtris + 2*numquads); + result = CDDM_from_template ( dm, numverts, 0, numtris + 2*numquads ); - if(!result) - return NULL; + if ( !result ) + return NULL; // do verts - mvert2 = CDDM_get_verts(result); - for(a=0; av1 = mface[a].v2; - mf->v2 = mface[a].v3; - mf->v3 = mface[a].v4; -} - else - { - mf->v1 = mface[a].v1; - mf->v2 = mface[a].v2; - mf->v3 = mface[a].v3; -} + if ( mface[a].v4 && random==1 ) + { + mf->v1 = mface[a].v2; + mf->v2 = mface[a].v3; + mf->v3 = mface[a].v4; + } + else + { + mf->v1 = mface[a].v1; + mf->v2 = mface[a].v2; + mf->v3 = mface[a].v3; + } - mf->v4 = 0; - mf->flag |= ME_SMOOTH; + mf->v4 = 0; + mf->flag |= ME_SMOOTH; - test_index_face(mf, NULL, 0, 3); + test_index_face ( mf, NULL, 0, 3 ); - if(mface[a].v4) - { - MFace *mf2; + if ( mface[a].v4 ) + { + MFace *mf2; - i++; + i++; - mf2 = &mface2[i]; - - // DM_copy_face_data(dm, result, a, i, 1); + mf2 = &mface2[i]; + /* + DM_copy_face_data(dm, result, a, i, 1); - // *mf2 = *inMF; - + *mf2 = *inMF; + */ - if(random==1) - { - mf2->v1 = mface[a].v1; - mf2->v2 = mface[a].v2; - mf2->v3 = mface[a].v4; -} - else - { - mf2->v1 = mface[a].v4; - mf2->v2 = mface[a].v1; - mf2->v3 = mface[a].v3; -} - mf2->v4 = 0; - mf2->flag |= ME_SMOOTH; + if ( random==1 ) + { + mf2->v1 = mface[a].v1; + mf2->v2 = mface[a].v2; + mf2->v3 = mface[a].v4; + } + else + { + mf2->v1 = mface[a].v4; + mf2->v2 = mface[a].v1; + mf2->v3 = mface[a].v3; + } + mf2->v4 = 0; + mf2->flag |= ME_SMOOTH; - test_index_face(mf2, NULL, 0, 3); -} + test_index_face ( mf2, NULL, 0, 3 ); + } - i++; -} + i++; + } - CDDM_calc_edges(result); - CDDM_calc_normals(result); + CDDM_calc_edges ( result ); + CDDM_calc_normals ( result ); return result; - */ - - return NULL; + } -DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) +DerivedMesh *CDDM_create_tearing ( ClothModifierData *clmd, DerivedMesh *dm ) { - /* DerivedMesh *result = NULL; unsigned int i = 0, a = 0, j=0; - int numverts = dm->getNumVerts(dm); - int numedges = dm->getNumEdges(dm); - int numfaces = dm->getNumFaces(dm); + int numverts = dm->getNumVerts ( dm ); + int numedges = dm->getNumEdges ( dm ); + int numfaces = dm->getNumFaces ( dm ); - MVert *mvert = CDDM_get_verts(dm); - MEdge *medge = CDDM_get_edges(dm); - MFace *mface = CDDM_get_faces(dm); + MVert *mvert = CDDM_get_verts ( dm ); + MEdge *medge = CDDM_get_edges ( dm ); + MFace *mface = CDDM_get_faces ( dm ); MVert *mvert2; MFace *mface2; @@ -339,91 +326,90 @@ DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) Cloth *cloth = clmd->clothObject; ClothSpring *springs = cloth->springs; unsigned int numsprings = cloth->numsprings; - + // create spring tearing hash edgehash = BLI_edgehash_new(); - - for(i = 0; i < numsprings; i++) - { - if((springs[i].flags & CSPRING_FLAG_DEACTIVATE) - &&(!BLI_edgehash_haskey(edgehash, springs[i].ij, springs[i].kl))) - { - BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL); - BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL); - j++; -} -} - - // printf("found %d tears\n", j); - - result = CDDM_from_template(dm, numverts, 0, numfaces); - if(!result) - return NULL; + for ( i = 0; i < numsprings; i++ ) + { + if ( ( springs[i].flags & CLOTH_SPRING_FLAG_DEACTIVATE ) + && ( !BLI_edgehash_haskey ( edgehash, springs[i].ij, springs[i].kl ) ) ) + { + BLI_edgehash_insert ( edgehash, springs[i].ij, springs[i].kl, NULL ); + BLI_edgehash_insert ( edgehash, springs[i].kl, springs[i].ij, NULL ); + j++; + } + } + + // printf("found %d tears\n", j); + + result = CDDM_from_template ( dm, numverts, 0, numfaces ); + + if ( !result ) + return NULL; // do verts - mvert2 = CDDM_get_verts(result); - for(a=0; av1 = mface[a].v1; - mf->v2 = mface[a].v2; - mf->v3 = mface[a].v3; - mf->v4 = mface[a].v4; - - test_index_face(mf, NULL, 0, 4); - - i++; -} -} + *mf = *inMF; + */ - CDDM_lower_num_faces(result, i); - CDDM_calc_edges(result); - CDDM_calc_normals(result); - - BLI_edgehash_free(edgehash, NULL); + if ( ( !BLI_edgehash_haskey ( edgehash, mface[a].v1, mface[a].v2 ) ) + && ( !BLI_edgehash_haskey ( edgehash, mface[a].v2, mface[a].v3 ) ) + && ( !BLI_edgehash_haskey ( edgehash, mface[a].v3, mface[a].v4 ) ) + && ( !BLI_edgehash_haskey ( edgehash, mface[a].v4, mface[a].v1 ) ) ) + { + mf->v1 = mface[a].v1; + mf->v2 = mface[a].v2; + mf->v3 = mface[a].v3; + mf->v4 = mface[a].v4; + + test_index_face ( mf, NULL, 0, 4 ); + + i++; + } + } + + CDDM_lower_num_faces ( result, i ); + CDDM_calc_edges ( result ); + CDDM_calc_normals ( result ); + + BLI_edgehash_free ( edgehash, NULL ); return result; - */ - - return NULL; } + + int modifiers_indexInObject(Object *ob, ModifierData *md_seek); void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) { int stack_index = -1; - if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) + if(!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) { stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); @@ -447,9 +433,9 @@ static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr for(a = 0; a < cloth->numverts; a++) { - fwrite(&cloth->x[a], sizeof(float),4,fp); - fwrite(&cloth->xconst[a], sizeof(float),4,fp); - fwrite(&cloth->v[a], sizeof(float),4,fp); + fwrite(&cloth->verts[a].x, sizeof(float),4,fp); + fwrite(&cloth->verts[a].xconst, sizeof(float),4,fp); + fwrite(&cloth->verts[a].v, sizeof(float),4,fp); } fclose(fp); @@ -472,17 +458,17 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) else { for(a = 0; a < cloth->numverts; a++) { - if(fread(&cloth->x[a], sizeof(float), 4, fp) != 4) + if(fread(&cloth->verts[a].x, sizeof(float), 4, fp) != 4) { ret = 0; break; } - if(fread(&cloth->xconst[a], sizeof(float), 4, fp) != 4) + if(fread(&cloth->verts[a].xconst, sizeof(float), 4, fp) != 4) { ret = 0; break; } - if(fread(&cloth->v[a], sizeof(float), 4, fp) != 4) + if(fread(&cloth->verts[a].v, sizeof(float), 4, fp) != 4) { ret = 0; break; @@ -492,182 +478,200 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) fclose(fp); } - if(clmd->sim_parms->solver_type == 0) + if(clmd->sim_parms.solver_type == 0) implicit_set_positions(clmd); return ret; } -int m_fc_open(ClothModifierData *clmd) -{ - Cloth *cloth = clmd->clothObject; - int _N; - fc *m_fc = NULL; - - if(!cloth) - return 0; - - m_fc = cloth->m_fc; - m_fc->_fp = fopen("/home/daniel/Desktop/f32rand.dat", "rb"); - if (!m_fc->_fp) - return 0; - - fread(&_N, sizeof(int), 1, m_fc->_fp); - fread(&_N, sizeof(int), 1, m_fc->_fp); - printf("Resolution: %dx%dx%d\n", _N, _N, _N); - - fread(&m_fc->_nframes, sizeof(int), 1, m_fc->_fp); - printf("Number of frames: %d\n", m_fc->_nframes); - m_fc->_cur_frame = 0; - - return 1; -} - - - -/************************************************ - * clothModifier_do - main simulation function -************************************************/ -DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) +/** +* cloth_deform_verts - simulates one step, framenr is in frames. +* +**/ +void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, + float ( *vertexCos ) [3], int numverts ) { unsigned int i; - unsigned int numverts = -1; unsigned int numedges = -1; unsigned int numfaces = -1; MVert *mvert = NULL; MEdge *medge = NULL; MFace *mface = NULL; - DerivedMesh *result = NULL; + DerivedMesh *result = NULL, *result2 = NULL; Cloth *cloth = clmd->clothObject; - unsigned int framenr = (float)G.scene->r.cfra; - float current_time = bsystem_time(ob, (float)G.scene->r.cfra, 0.0); - ListBase *effectors = NULL; - float deltaTime = current_time - clmd->sim_parms->sim_time; + unsigned int framenr = ( float ) G.scene->r.cfra; + float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); + ListBase *effectors = NULL; + ClothVertex *newframe= NULL, *verts; + Frame *frame = NULL; + LinkNode *search = NULL; + float deltaTime = current_time - clmd->sim_parms.sim_time; + + clmd->sim_parms.ob = ob; - clmd->sim_parms->dt = 1.0f / (clmd->sim_parms->stepsPerFrame * G.scene->r.frs_sec); - result = CDDM_copy(dm); - - if(!result) - { - return dm; - } - - numverts = result->getNumVerts(result); - numedges = result->getNumEdges(result); - numfaces = result->getNumFaces(result); - mvert = CDDM_get_verts(result); - medge = CDDM_get_edges(result); - mface = CDDM_get_faces(result); - - clmd->sim_parms->sim_time = current_time; - - if ( current_time < clmd->sim_parms->firstframe ) - return result; - // only be active during a specific period: // that's "first frame" and "last frame" on GUI /* - if ( clmd->clothObject ) + if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) ) { - if ( clmd->sim_parms->cache ) - { - if ( current_time < clmd->sim_parms->firstframe ) - { - int frametime = cloth_cache_first_frame ( clmd ); - if ( cloth_cache_search_frame ( clmd, frametime ) ) - { - cloth_cache_get_frame ( clmd, frametime ); - cloth_to_object ( ob, result, clmd ); -} - return result; -} - else if ( current_time > clmd->sim_parms->lastframe ) - { - int frametime = cloth_cache_last_frame ( clmd ); - if ( cloth_cache_search_frame ( clmd, frametime ) ) - { - cloth_cache_get_frame ( clmd, frametime ); - cloth_to_object ( ob, result, clmd ); -} - return result; -} - else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed - { - if ( cloth_cache_search_frame ( clmd, framenr ) ) - { - cloth_cache_get_frame ( clmd, framenr ); - cloth_to_object ( ob, result, clmd ); -} - clmd->sim_parms->sim_time = current_time; - return result; -} -} -} - */ - - if(deltaTime == 1.0f) - { - if ((clmd->clothObject == NULL) || (numverts != clmd->clothObject->numverts) ) + if ( clmd->clothObject ) { - cloth_clear_cache(ob, clmd, 0); - - if(!cloth_from_object (ob, clmd, result, dm, framenr)) - return result; + if ( clmd->sim_parms.cache ) + { + if ( current_time < clmd->sim_parms.firstframe ) + { + int frametime = cloth_cache_first_frame ( clmd ); + if ( cloth_cache_search_frame ( clmd, frametime ) ) + { + cloth_cache_get_frame ( clmd, frametime ); + cloth_to_object ( ob, clmd, vertexCos, numverts ); + } + return; + } + else if ( current_time > clmd->sim_parms.lastframe ) + { + int frametime = cloth_cache_last_frame ( clmd ); + if ( cloth_cache_search_frame ( clmd, frametime ) ) + { + cloth_cache_get_frame ( clmd, frametime ); + cloth_to_object ( ob, clmd, vertexCos, numverts ); + } + return; + } + else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed + { + if ( cloth_cache_search_frame ( clmd, framenr ) ) + { + cloth_cache_get_frame ( clmd, framenr ); + cloth_to_object ( ob, clmd, vertexCos, numverts ); + } + clmd->sim_parms.sim_time = current_time; + return; + } + } - if(clmd->clothObject == NULL) - return result; + } + } + */ + + // unused in the moment, calculated seperately in implicit.c + clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame; + + clmd->sim_parms.sim_time = current_time; + + // check if cloth object was some collision object before and needs freeing now + if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) && ( clmd->clothObject != NULL ) && ( clmd->clothObject->old_solver_type == 255 ) ) + { + // temporary set CSIMSETT_FLAG_COLLOBJ flag for proper freeing + clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; + cloth_free_modifier ( clmd ); + clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_COLLOBJ; + } + + // This is for collisions objects: check special case CSIMSETT_FLAG_COLLOBJ + if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) + { + // save next position + time + if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) ) + { + if ( !collobj_from_object ( ob, clmd, dm, vertexCos, framenr ) ) + { + clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; + cloth_free_modifier ( clmd ); + return; + } + + if ( clmd->clothObject == NULL ) + return; cloth = clmd->clothObject; } - /* - deltaTime = 0; - while( deltaTime < 1.0) + + // Save old position + clmd->sim_parms.sim_time_old = clmd->sim_parms.sim_time; + clmd->sim_parms.sim_time = current_time; + + verts = cloth->verts; + + for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) { - step(cloth->m_fc, 0.1); - deltaTime+=0.1; + // Save the previous position. + VECCOPY ( verts->xold, verts->x ); + VECCOPY ( verts->txold, verts->x ); + + // Get the current position. + VECCOPY ( verts->x, vertexCos[i] ); + Mat4MulVecfl ( ob->obmat, verts->x ); + + // Compute the vertices "velocity". + // (no dt correction here because of float error) + VECSUB ( verts->v, verts->x, verts->xold ); } - */ - clmd->clothObject->old_solver_type = clmd->sim_parms->solver_type; + + return; + } + + if ( deltaTime == 1.0f ) + { + if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) ) + { + cloth_clear_cache(ob, clmd, 0); + + if ( !cloth_from_object ( ob, clmd, dm, vertexCos, numverts, framenr ) ) + return; + + if ( clmd->clothObject == NULL ) + return; + + cloth = clmd->clothObject; + } + + clmd->clothObject->old_solver_type = clmd->sim_parms.solver_type; // Insure we have a clmd->clothObject, in case allocation failed. - if (clmd->clothObject != NULL) + if ( clmd->clothObject != NULL ) { if(!cloth_read_cache(ob, clmd, framenr)) { + verts = cloth->verts; + // Force any pinned verts to their constrained location. - // has to be commented for verlet - for ( i = 0; i < clmd->clothObject->numverts; i++ ) + for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) { // Save the previous position. - VECCOPY ( cloth->xold[i], cloth->xconst[i] ); - VECCOPY ( cloth->current_xold[i], cloth->x[i] ); + VECCOPY ( verts->xold, verts->xconst ); + VECCOPY ( verts->txold, verts->x ); + // Get the current position. - VECCOPY ( cloth->xconst[i], mvert[i].co ); - Mat4MulVecfl ( ob->obmat, cloth->xconst[i] ); + VECCOPY ( verts->xconst, vertexCos[i] ); + Mat4MulVecfl ( ob->obmat, verts->xconst ); } - + tstart(); - - /* Call the solver. */ - - if (solvers [clmd->sim_parms->solver_type].solver) - solvers [clmd->sim_parms->solver_type].solver (ob, framenr, clmd, effectors); - + + // Call the solver. + if ( solvers [clmd->sim_parms.solver_type].solver ) + solvers [clmd->sim_parms.solver_type].solver ( ob, framenr, clmd, effectors ); + tend(); - - printf("Cloth simulation time: %f\n", tval()); - + printf ( "Cloth simulation time: %f\n", ( float ) tval() ); + cloth_write_cache(ob, clmd, framenr); + + } + else // just retrieve the cached frame + { + cloth_read_cache(ob, clmd, framenr); } // Copy the result back to the object. - cloth_to_object (ob, result, clmd); - + cloth_to_object ( ob, clmd, vertexCos, numverts ); + // bvh_free(clmd->clothObject->tree); - // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms->epsilon); - } + // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); + } } else if ( ( deltaTime <= 0.0f ) || ( deltaTime > 1.0f ) ) @@ -675,147 +679,85 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d if ( clmd->clothObject != NULL ) { if(cloth_read_cache(ob, clmd, framenr)) - cloth_to_object (ob, result, clmd); + cloth_to_object ( ob, clmd, vertexCos, numverts ); } else { cloth_clear_cache(ob, clmd, 0); } } - - cloth = clmd->clothObject; - /* - if(cloth) - { - if (_texture_data == NULL) - _texture_data = (unsigned char*) malloc((30+2)*(30+2)*(30+2)*4); - - for (i=0; i<(30+2)*(30+2)*(30+2); i++) { - _texture_data[(i<<2)] = (unsigned char) (cloth->m_fc->T[i] * 255.0f); - _texture_data[(i<<2)+1] = (unsigned char) (cloth->m_fc->d[i] * 255.0f); - _texture_data[(i<<2)+2] = 0; - _texture_data[(i<<2)+3] = 255; - } - - // from ligth constructor - _light_dir[0] = -1.0f; - _light_dir[1] = 0.5f; - _light_dir[2] = 0.0f; - - gen_ray_templ(_ray_templ, _light_dir, 30 + 2); - - cast_light(_texture_data, _ray_templ, _light_dir, 30+2); - - glActiveTextureARB(GL_TEXTURE0_ARB); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 30+2, 30+2, 30+2, 0, GL_RGBA, GL_UNSIGNED_BYTE, _texture_data); - free(_texture_data); - } - */ - return result; + } /* frees all */ -void cloth_free_modifier (ClothModifierData *clmd) +void cloth_free_modifier ( ClothModifierData *clmd ) { Cloth *cloth = NULL; - - if(!clmd) + Object *ob = clmd->sim_parms.ob; + + if ( !clmd ) return; cloth = clmd->clothObject; - // free our frame cache - // cloth_clear_cache(ob, clmd, 0); - - /* Calls the solver and collision frees first as they - * might depend on data in clmd->clothObject. */ - - if (cloth) - { - f_free(cloth->m_fc); - - // If our solver provides a free function, call it - if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free) - { - solvers [cloth->old_solver_type].free (clmd); - } - - // Free the verts. - if (cloth->verts != NULL) - MEM_freeN (cloth->verts); - - // Free the faces. - if ( cloth->mfaces != NULL ) - MEM_freeN ( cloth->mfaces ); - - // Free the verts. - if ( cloth->x != NULL ) - MEM_freeN ( cloth->x ); - - // Free the verts. - if ( cloth->xold != NULL ) - MEM_freeN ( cloth->xold ); - - // Free the verts. - if ( cloth->v != NULL ) - MEM_freeN ( cloth->v ); - - // Free the verts. - if ( cloth->current_x != NULL ) - MEM_freeN ( cloth->current_x ); - - // Free the verts. - if ( cloth->current_xold != NULL ) - MEM_freeN ( cloth->current_xold ); - - // Free the verts. - if ( cloth->current_v != NULL ) - MEM_freeN ( cloth->current_v ); - - // Free the verts. - if ( cloth->xconst != NULL ) - MEM_freeN ( cloth->xconst ); - - cloth->verts = NULL; - cloth->numverts = -1; - - // Free the springs. - if ( cloth->springs != NULL ) + if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT ) ) + { + if ( cloth ) { - LinkNode *search = cloth->springs; - while(search) + // free our frame cache, TODO: but get to first position before + if(ob) + cloth_clear_cache ( ob, clmd, 0 ); + + // If our solver provides a free function, call it + if ( cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free ) { - ClothSpring *spring = search->link; - - MEM_freeN ( spring ); - search = search->next; + solvers [cloth->old_solver_type].free ( clmd ); } - BLI_linklist_free(cloth->springs, NULL); - + + // Free the verts. + if ( cloth->verts != NULL ) + MEM_freeN ( cloth->verts ); + + cloth->verts = NULL; + cloth->numverts = 0; + + // Free the springs. + if ( cloth->springs != NULL ) + { + LinkNode *search = cloth->springs; + while(search) + { + ClothSpring *spring = search->link; + + MEM_freeN ( spring ); + search = search->next; + } + BLI_linklist_free(cloth->springs, NULL); + + cloth->springs = NULL; + } + cloth->springs = NULL; + cloth->numsprings = 0; + + // free BVH collision tree + if ( cloth->tree ) + bvh_free ( ( BVH * ) cloth->tree ); + + // we save our faces for collision objects + if ( cloth->mfaces ) + MEM_freeN ( cloth->mfaces ); + /* + if(clmd->clothObject->facemarks) + MEM_freeN(clmd->clothObject->facemarks); + */ + MEM_freeN ( cloth ); + clmd->clothObject = NULL; } - - cloth->numsprings = -1; - - // free BVH collision tree - if(cloth->tree) - bvh_free((BVH *)cloth->tree); - - // free BVH self collision tree - if(cloth->selftree) - bvh_free((BVH *)cloth->selftree); - - if(cloth->edgehash) - BLI_edgehash_free ( cloth->edgehash, NULL ); - - MEM_freeN (cloth); - clmd->clothObject = NULL; } - } - /****************************************************************************** * * Internal functions. @@ -823,44 +765,42 @@ void cloth_free_modifier (ClothModifierData *clmd) ******************************************************************************/ /** - * cloth_to_object - copies the deformed vertices to the object. - * - * This function is a modified version of the softbody.c:softbody_to_object() function. - **/ -static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd) +* cloth_to_object - copies the deformed vertices to the object. +* +* This function is a modified version of the softbody.c:softbody_to_object() function. +**/ +static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ) { + ClothVertex *verts = NULL; unsigned int i = 0; - MVert *mvert = NULL; - unsigned int numverts; - Cloth *cloth = clmd->clothObject; - if (clmd->clothObject) { + if ( clmd->clothObject ) + { + verts = clmd->clothObject->verts; + /* inverse matrix is not uptodate... */ - Mat4Invert (ob->imat, ob->obmat); + Mat4Invert ( ob->imat, ob->obmat ); - mvert = CDDM_get_verts(dm); - numverts = dm->getNumVerts(dm); - - for (i = 0; i < numverts; i++) + for ( i = 0; i < numverts; i++, verts++ ) { - VECCOPY (mvert[i].co, cloth->x[i]); - Mat4MulVecfl (ob->imat, mvert[i].co); /* cloth is in global coords */ + VECCOPY ( vertexCos[i], verts->x ); + Mat4MulVecfl ( ob->imat, vertexCos[i] ); /* softbody is in global coords */ } } } /** - * cloth_apply_vgroup - applies a vertex group as specified by type - * - **/ -static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup) +* cloth_apply_vgroup - applies a vertex group as specified by type +* +**/ +static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ) { unsigned int i = 0; unsigned int j = 0; - MDeformVert *dvert = NULL; + MDeformVert *dvert = NULL; Cloth *clothObj = NULL; - unsigned int numverts = 0; + unsigned int numverts = dm->getNumVerts ( dm ); float goalfac = 0; ClothVertex *verts = NULL; @@ -869,7 +809,7 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v if ( !dm ) return; - numverts = dm->getNumVerts(dm); + numverts = dm->getNumVerts ( dm ); /* vgroup is 1 based, decrement so we can match the right group. */ --vgroup; @@ -879,7 +819,7 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v for ( i = 0; i < numverts; i++, verts++ ) { // LATER ON, support also mass painting here - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) { dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT ); if ( dvert ) @@ -890,7 +830,7 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v { verts->goal = dvert->dw [j].weight; - goalfac= ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); + goalfac= ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal ); verts->goal = ( float ) pow ( verts->goal , 4.0f ); if ( dvert->dw [j].weight >=SOFTGOALSNAP ) @@ -907,194 +847,226 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v } } } - + // only meshes supported at the moment -static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr) +/* collision objects */ +static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ) { unsigned int i; - unsigned int numverts = dm->getNumVerts(dm); - MVert *mvert = CDDM_get_verts(dm); + MVert *mvert = NULL; + ClothVertex *verts = NULL; float tnull[3] = {0,0,0}; - Cloth *cloth = NULL; - + /* If we have a clothObject, free it. */ - if (clmd->clothObject != NULL) - cloth_free_modifier (clmd); + if ( clmd->clothObject != NULL ) + cloth_free_modifier ( clmd ); /* Allocate a new cloth object. */ - clmd->clothObject = MEM_callocN (sizeof(Cloth), "cloth"); - if (clmd->clothObject) + clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" ); + if ( clmd->clothObject ) { clmd->clothObject->old_solver_type = 255; - clmd->clothObject->edgehash = NULL; + // clmd->clothObject->old_collision_type = 255; } - else if (clmd->clothObject == NULL) + else if ( clmd->clothObject == NULL ) { - modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject."); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject." ); return 0; } - - cloth = clmd->clothObject; - - cloth->m_fc = f_init(); - // open file - m_fc_open(clmd); - - switch (ob->type) + switch ( ob->type ) { case OB_MESH: - + // mesh input objects need DerivedMesh if ( !dm ) return 0; - cloth_from_mesh (ob, clmd, dm, framenr); + cloth_from_mesh ( ob, clmd, dm ); + + if ( clmd->clothObject != NULL ) + { + if ( !dm ) return 0; + if ( !dm->getNumVerts ( dm ) || !dm->getNumFaces ( dm ) ) return 0; + + mvert = dm->getVertArray ( dm ); + verts = clmd->clothObject->verts; + numverts = clmd->clothObject->numverts = dm->getNumVerts ( dm ); + + for ( i = 0; i < numverts; i++, verts++ ) + { + VECCOPY ( verts->x, mvert[i].co ); + Mat4MulVecfl ( ob->obmat, verts->x ); + verts->flags = 0; + VECCOPY ( verts->xold, verts->x ); + VECCOPY ( verts->txold, verts->x ); + VECCOPY ( verts->tx, verts->x ); + VecMulf ( verts->v, 0.0f ); + verts->impulse_count = 0; + VECCOPY ( verts->impulse, tnull ); + } + clmd->clothObject->tree = bvh_build ( clmd,clmd->coll_parms.epsilon ); + + } + + return 1; + default: return 0; // TODO - we do not support changing meshes + } +} + +/* +helper function to get proper spring length +when object is rescaled +*/ +float cloth_globallen ( float *v1,float *v2,Object *ob ) +{ + float p1[3],p2[3]; + VECCOPY ( p1,v1 ); + Mat4MulVecfl ( ob->obmat, p1 ); + VECCOPY ( p2,v2 ); + Mat4MulVecfl ( ob->obmat, p2 ); + return VecLenf ( p1,p2 ); +} + +// only meshes supported at the moment +static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts, float framenr ) +{ + unsigned int i = 0; + // dm->getNumVerts(dm); + MVert *mvert = NULL; // CDDM_get_verts(dm); + ClothVertex *verts = NULL; + float tnull[3] = {0,0,0}; + + /* If we have a clothObject, free it. */ + if ( clmd->clothObject != NULL ) + cloth_free_modifier ( clmd ); + + /* Allocate a new cloth object. */ + clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" ); + if ( clmd->clothObject ) + { + clmd->clothObject->old_solver_type = 255; + // clmd->clothObject->old_collision_type = 255; + } + else if ( !clmd->clothObject ) + { + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject." ); + return 0; + } + + clmd->sim_parms.ob = ob; + + switch ( ob->type ) + { + case OB_MESH: + + // mesh input objects need DerivedMesh + if ( !dm ) + return 0; + + cloth_from_mesh ( ob, clmd, dm ); if ( clmd->clothObject != NULL ) { /* create springs */ clmd->clothObject->springs = NULL; clmd->clothObject->numsprings = -1; - + + mvert = CDDM_get_verts ( dm ); + verts = clmd->clothObject->verts; + /* set initial values */ - for (i = 0; i < numverts; ++i) + for ( i = 0; i < numverts; i++, verts++ ) { - VECCOPY (clmd->clothObject->x[i], mvert[i].co); - Mat4MulVecfl(ob->obmat, clmd->clothObject->x[i]); - - clmd->clothObject->verts [i].mass = clmd->sim_parms->mass; - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - clmd->clothObject->verts [i].goal= clmd->sim_parms->defgoal; + VECCOPY ( verts->x, mvert[i].co ); + Mat4MulVecfl ( ob->obmat, verts->x ); + + verts->mass = clmd->sim_parms.mass; + + if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + verts->goal= clmd->sim_parms.defgoal; else - clmd->clothObject->verts [i].goal= 0.0; - clmd->clothObject->verts [i].flags = 0; - VECCOPY(clmd->clothObject->xold[i], clmd->clothObject->x[i]); - VECCOPY(clmd->clothObject->xconst[i], clmd->clothObject->x[i]); - VECCOPY(clmd->clothObject->current_xold[i], clmd->clothObject->x[i]); - VecMulf(clmd->clothObject->v[i], 0.0); - - clmd->clothObject->verts [i].impulse_count = 0; - VECCOPY ( clmd->clothObject->verts [i].impulse, tnull ); + verts->goal= 0.0f; + + verts->flags = 0; + VECCOPY ( verts->xold, verts->x ); + VECCOPY ( verts->xconst, verts->x ); + VECCOPY ( verts->txold, verts->x ); + VecMulf ( verts->v, 0.0f ); + + verts->impulse_count = 0; + VECCOPY ( verts->impulse, tnull ); } - if (!cloth_build_springs (clmd, dm) ) + if ( !cloth_build_springs ( clmd->clothObject, dm ) ) { - modifier_setError (&(clmd->modifier), "Can't build springs."); + modifier_setError ( & ( clmd->modifier ), "Can't build springs." ); return 0; - } - - /* apply / set vertex groups */ - if (clmd->sim_parms->vgroup_mass > 0) - cloth_apply_vgroup (clmd, olddm, clmd->sim_parms->vgroup_mass); - - /* init our solver */ - if (solvers [clmd->sim_parms->solver_type].init) - solvers [clmd->sim_parms->solver_type].init (ob, clmd); - - clmd->clothObject->tree = bvh_build_from_float3(CDDM_get_faces(dm), dm->getNumFaces(dm), clmd->clothObject->x, numverts, clmd->coll_parms->epsilon); - - clmd->clothObject->selftree = bvh_build_from_float3(NULL, 0, clmd->clothObject->x, numverts, clmd->coll_parms->selfepsilon); - - // save initial state + } + + // apply / set vertex groups + if ( clmd->sim_parms.vgroup_mass > 0 ) + cloth_apply_vgroup ( clmd, dm, clmd->sim_parms.vgroup_mass ); + + // init our solver + if ( solvers [clmd->sim_parms.solver_type].init ) + solvers [clmd->sim_parms.solver_type].init ( ob, clmd ); + + clmd->clothObject->tree = bvh_build ( clmd, clmd->coll_parms.epsilon ); + cloth_write_cache(ob, clmd, framenr-1); } + return 1; - default: return 0; // TODO - we do not support changing meshes + case OB_LATTICE: + printf ( "Not supported: OB_LATTICE\n" ); + // lattice_to_softbody(ob); + return 1; + case OB_CURVE: + case OB_SURF: + printf ( "Not supported: OB_SURF| OB_CURVE\n" ); + return 1; + default: return 0; // TODO - we do not support changing meshes } - + return 0; } -static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr) +static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) { - unsigned int numverts = dm->getNumVerts(dm); - unsigned int numfaces = dm->getNumFaces(dm); - MFace *mface = CDDM_get_faces(dm); + unsigned int numverts = dm->getNumVerts ( dm ); + unsigned int numfaces = dm->getNumFaces ( dm ); + MFace *mface = dm->getFaceArray ( dm ); + unsigned int i = 0; /* Allocate our vertices. */ clmd->clothObject->numverts = numverts; - clmd->clothObject->verts = MEM_callocN (sizeof (ClothVertex) * clmd->clothObject->numverts, "clothVertex"); - if (clmd->clothObject->verts == NULL) - { - cloth_free_modifier (clmd); - modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts."); - return; - } - - clmd->clothObject->x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_x" ); - if ( clmd->clothObject->x == NULL ) + clmd->clothObject->verts = MEM_callocN ( sizeof ( ClothVertex ) * clmd->clothObject->numverts, "clothVertex" ); + if ( clmd->clothObject->verts == NULL ) { cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->x." ); - return; - } - - clmd->clothObject->xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_xold" ); - if ( clmd->clothObject->xold == NULL ) - { - cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xold." ); - return; - } - - clmd->clothObject->v = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_v" ); - if ( clmd->clothObject->v == NULL ) - { - cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->v." ); - return; - } - - clmd->clothObject->current_x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_current_x" ); - if ( clmd->clothObject->current_x == NULL ) - { - cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_x." ); - return; - } - - clmd->clothObject->current_xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_current_xold" ); - if ( clmd->clothObject->current_xold == NULL ) - { - cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_xold." ); - return; - } - - clmd->clothObject->current_v = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_current_v" ); - if ( clmd->clothObject->current_v == NULL ) - { - cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_v." ); - return; - } - - clmd->clothObject->xconst = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_xconst" ); - if ( clmd->clothObject->xconst == NULL ) - { - cloth_free_modifier ( clmd ); - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xconst." ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." ); return; } // save face information clmd->clothObject->numfaces = numfaces; - clmd->clothObject->mfaces = MEM_callocN (sizeof (MFace) * clmd->clothObject->numfaces, "clothMFaces"); - if (clmd->clothObject->mfaces == NULL) + clmd->clothObject->mfaces = MEM_callocN ( sizeof ( MFace ) * clmd->clothObject->numfaces, "clothMFaces" ); + if ( clmd->clothObject->mfaces == NULL ) { - cloth_free_modifier (clmd); - modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->mfaces."); + cloth_free_modifier ( clmd ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->mfaces." ); return; } - memcpy(clmd->clothObject->mfaces, mface, sizeof(MFace)*numfaces); + for ( i = 0; i < numfaces; i++ ) + memcpy ( &clmd->clothObject->mfaces[i], &mface[i], sizeof ( MFace ) ); /* Free the springs since they can't be correct if the vertices * changed. */ - if (clmd->clothObject->springs != NULL) - MEM_freeN (clmd->clothObject->springs); + if ( clmd->clothObject->springs != NULL ) + MEM_freeN ( clmd->clothObject->springs ); } @@ -1103,7 +1075,6 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d ***************************************************************************************/ // be carefull: implicit solver has to be resettet when using this one! -// --> only for implicit handling of this spring! int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type) { Cloth *cloth = clmd->clothObject; @@ -1130,12 +1101,11 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in return 0; } -int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) +int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) { - Cloth *cloth = clmd->clothObject; ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0; - unsigned int i = 0, j = 0, akku_count; + unsigned int i = 0; unsigned int numverts = dm->getNumVerts ( dm ); unsigned int numedges = dm->getNumEdges ( dm ); unsigned int numfaces = dm->getNumFaces ( dm ); @@ -1145,9 +1115,9 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) LinkNode **edgelist = NULL; EdgeHash *edgehash = NULL; LinkNode *search = NULL, *search2 = NULL; - float temp[3], akku, min, max; - LinkNode *node = NULL, *node2 = NULL; - + float temp[3]; + ClothVertex *verts = NULL; + // error handling if ( numedges==0 ) return 0; @@ -1162,6 +1132,8 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) if ( cloth->springs ) MEM_freeN ( cloth->springs ); + + verts = cloth->verts; // create spring network hash edgehash = BLI_edgehash_new(); @@ -1175,54 +1147,16 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) { spring->ij = medge[i].v1; spring->kl = medge[i].v2; - VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] ); + VECSUB ( temp, verts[spring->kl].x, verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; spring->flags = 0; struct_springs++; - - if(!i) - node2 = BLI_linklist_append_fast ( &cloth->springs, spring ); - else - node2 = BLI_linklist_append_fast ( &node->next, spring ); - node = node2; - } - } - - // calc collision balls *slow* - // better: use precalculated list with O(1) index access to all springs of a vertex - // missing for structural since it's not needed for building bending springs - for ( i = 0; i < numverts; i++ ) - { - akku_count = 0; - akku = 0.0; - cloth->verts[i].collball=0; - min = 1e22f; - max = -1e22f; - - search = cloth->springs; - for ( j = 0; j < struct_springs; j++ ) - { - if ( !search ) - break; - tspring = search->link; - - if((tspring->ij == i) || (tspring->kl == i)) - { - akku += spring->restlen; - akku_count++; - min = MIN2(spring->restlen,min); - max = MAX2(spring->restlen,max); - } + BLI_linklist_append ( &cloth->springs, spring ); } - - if (akku_count > 0) { - cloth->verts[i].collball = akku/(float)akku_count*clmd->coll_parms->selfepsilon; - } - else cloth->verts[i].collball=0; } - + // shear springs for ( i = 0; i < numfaces; i++ ) { @@ -1230,7 +1164,7 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring->ij = mface[i].v1; spring->kl = mface[i].v3; - VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] ); + VECSUB ( temp, verts[spring->kl].x, verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_SHEAR; @@ -1238,8 +1172,7 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) BLI_linklist_append ( &edgelist[spring->kl], spring ); shear_springs++; - node2 = BLI_linklist_append_fast ( &node->next, spring ); - node = node2; + BLI_linklist_append ( &cloth->springs, spring ); if ( mface[i].v4 ) { @@ -1247,19 +1180,18 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring->ij = mface[i].v2; spring->kl = mface[i].v4; - VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] ); - spring->restlen = sqrt ( INPR ( temp, temp ) ); - spring->type = CLOTH_SPRING_TYPE_SHEAR; + VECSUB ( temp, verts[spring->kl].x, verts[spring->ij].x ); + spring->restlen = sqrt ( INPR ( temp, temp ) ); + spring->type = CLOTH_SPRING_TYPE_SHEAR; - BLI_linklist_append ( &edgelist[spring->ij], spring ); - BLI_linklist_append ( &edgelist[spring->kl], spring ); - shear_springs++; + BLI_linklist_append ( &edgelist[spring->ij], spring ); + BLI_linklist_append ( &edgelist[spring->kl], spring ); + shear_springs++; - node2 = BLI_linklist_append_fast ( &node->next, spring ); - node = node2; + BLI_linklist_append ( &cloth->springs, spring ); } } - + // bending springs search2 = cloth->springs; for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) @@ -1277,38 +1209,36 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) // check for existing spring // check also if startpoint is equal to endpoint if ( !BLI_edgehash_haskey ( edgehash, index2, tspring2->ij ) - && !BLI_edgehash_haskey ( edgehash, tspring2->ij, index2 ) - && ( index2!=tspring2->ij ) ) + && !BLI_edgehash_haskey ( edgehash, tspring2->ij, index2 ) + && ( index2!=tspring2->ij ) ) { spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); spring->ij = tspring2->ij; spring->kl = index2; - VECSUB ( temp, cloth->x[index2], cloth->x[tspring2->ij] ); + VECSUB ( temp, verts[index2].x, verts[tspring2->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_BENDING; BLI_edgehash_insert ( edgehash, spring->ij, index2, NULL ); bend_springs++; - node2 = BLI_linklist_append_fast ( &node->next, spring ); - node = node2; + BLI_linklist_append ( &cloth->springs, spring ); } search = search->next; } search2 = search2->next; } - - cloth->numspringssave = cloth->numsprings = struct_springs + shear_springs + bend_springs; - cloth->numothersprings = struct_springs + shear_springs; - + + cloth->numsprings = struct_springs + shear_springs + bend_springs; + for ( i = 0; i < numverts; i++ ) { BLI_linklist_free ( edgelist[i],NULL ); } if ( edgelist ) MEM_freeN ( edgelist ); - - cloth->edgehash = edgehash; + + BLI_edgehash_free ( edgehash, NULL ); return 1; @@ -1317,344 +1247,3 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) * SPRING NETWORK BUILDING IMPLEMENTATION END ***************************************************************************************/ -#define F_ITER 20 -#define m_diffusion 0.00001f -#define m_viscosity 0.000f -#define m_buoyancy 1.5f -#define m_cooling 1.0f -#define m_vc_eps 4.0f - -#define GRID_SIZE 30 -#define SIZE ((GRID_SIZE+2)*(GRID_SIZE+2)*(GRID_SIZE+2)) -#define _I(x,y,z) (((z)<<10)+((y)<<5)+x) - -#define SWAPFPTR(x,y) {float *t=x;x=y;y=t;} - -float buffers[10][SIZE]; -float sd[SIZE], su[SIZE], sv[SIZE], sw[SIZE], sT[SIZE]; - - -// nothing to do in this mode -// add code for 2nd mode -void set_bnd(int b, float* x, int N) -{ -} - -void lin_solve(int b, float *x, float *x0, float a, float c, int N) -{ - float cRecip = 1.0 / c; - int i, j, k, l; - for (l=0; lN+0.5) xx=N+0.5f; i0=(int)xx; i1=i0+1; - if (yy<0.5) yy=0.5f; if (yy>N+0.5) yy=N+0.5f; j0=(int)yy; j1=j0+1; - if (zz<0.5) zz=0.5f; if (zz>N+0.5) zz=N+0.5f; k0=(int)zz; k1=k0+1; - sx1 = xx-i0; sx0 = 1-sx1; - sy1 = yy-j0; sy0 = 1-sy1; - sz1 = zz-k0; sz0 = 1-sz1; - v0 = sx0*(sy0*x0[_I(i0,j0,k0)]+sy1*x0[_I(i0,j1,k0)])+sx1*(sy0*x0[_I(i1,j0,k0)]+sy1*x0[_I(i1,j1,k0)]); - v1 = sx0*(sy0*x0[_I(i0,j0,k1)]+sy1*x0[_I(i0,j1,k1)])+sx1*(sy0*x0[_I(i1,j0,k1)]+sy1*x0[_I(i1,j1,k1)]); - x[_I(i,j,k)] = sz0*v0 + sz1*v1; - } - } - } - set_bnd(b,x, N); -} - -void advect_cool(int b, float* x0, float* x, float* y0, float* y, float* uu, float* vv, float* ww, float dt, float cooling, int N) -{ - int i, j, k, i0, j0, k0, i1, j1, k1; - float sx0, sx1, sy0, sy1, sz0, sz1, v0, v1; - float xx, yy, zz, dt0, c0; - dt0 = dt*N; - c0 = 1.0f - cooling*dt; - for (k=1; k<=N; k++) - { - for (j=1; j<=N; j++) - { - for (i=1; i<=N; i++) - { - xx = i-dt0*uu[_I(i,j,k)]; - yy = j-dt0*vv[_I(i,j,k)]; - zz = k-dt0*ww[_I(i,j,k)]; - if (xx<0.5) xx=0.5f; if (xx>N+0.5) xx=N+0.5f; i0=(int)xx; i1=i0+1; - if (yy<0.5) yy=0.5f; if (yy>N+0.5) yy=N+0.5f; j0=(int)yy; j1=j0+1; - if (zz<0.5) zz=0.5f; if (zz>N+0.5) zz=N+0.5f; k0=(int)zz; k1=k0+1; - sx1 = xx-i0; sx0 = 1-sx1; - sy1 = yy-j0; sy0 = 1-sy1; - sz1 = zz-k0; sz0 = 1-sz1; - v0 = sx0*(sy0*x0[_I(i0,j0,k0)]+sy1*x0[_I(i0,j1,k0)])+sx1*(sy0*x0[_I(i1,j0,k0)]+sy1*x0[_I(i1,j1,k0)]); - v1 = sx0*(sy0*x0[_I(i0,j0,k1)]+sy1*x0[_I(i0,j1,k1)])+sx1*(sy0*x0[_I(i1,j0,k1)]+sy1*x0[_I(i1,j1,k1)]); - x[_I(i,j,k)] = sz0*v0 + sz1*v1; - v0 = sx0*(sy0*y0[_I(i0,j0,k0)]+sy1*y0[_I(i0,j1,k0)])+sx1*(sy0*y0[_I(i1,j0,k0)]+sy1*y0[_I(i1,j1,k0)]); - v1 = sx0*(sy0*y0[_I(i0,j0,k1)]+sy1*y0[_I(i0,j1,k1)])+sx1*(sy0*y0[_I(i1,j0,k1)]+sy1*y0[_I(i1,j1,k1)]); - y[_I(i,j,k)] = (sz0*v0 + sz1*v1)*c0; - } - } - } - set_bnd(b,x, N); - set_bnd(b,y, N); -} - -void fproject(float* u, float* u0, float* v, float* v0, float* w, float* w0, int N) -{ - float* p = u0; float* div = v0; // temporary buffers, use old velocity buffers - int i, j, k; - float h; - h = 1.0f/N; - for (k=1; k<=N; k++) { - for (j=1; j<=N; j++) { - for (i=1; i<=N; i++) { - div[_I(i,j,k)] = -h*( - u[_I(i+1,j,k)]-u[_I(i-1,j,k)]+ - v[_I(i,j+1,k)]-v[_I(i,j-1,k)]+ - w[_I(i,j,k+1)]-w[_I(i,j,k-1)])*0.5; - p[_I(i,j,k)] = 0; - } - } - } - set_bnd(0, div, N); - set_bnd(0, p, N); - lin_solve(0, p, div, 1, 6, N); - - for (k=1; k<=N; k++) { - for (j=1; j<=N; j++) { - for (i=1; i<=N; i++) { - u[_I(i,j,k)] -= (p[_I(i+1,j,k)]-p[_I(i-1,j,k)])*0.5*N; - v[_I(i,j,k)] -= (p[_I(i,j+1,k)]-p[_I(i,j-1,k)])*0.5*N; - w[_I(i,j,k)] -= (p[_I(i,j,k+1)]-p[_I(i,j,k-1)])*0.5*N; - } - } - } - set_bnd(1, u, N); - set_bnd(2, v, N); - set_bnd(3, w, N); -} - -void vorticity_confinement(float *T0, float* u, float* u0, float* v, float* v0, float* w, float* w0, float dt, float vc_eps, int N) -{ - int i,j,k,ijk; - float *curlx = u0, *curly = v0, *curlz=w0, *curl=T0; // temp buffers - float dt0 = dt * vc_eps; - float x,y,z; - - - for (k=1; ku, m_fc->u0, m_fc->v, m_fc->v0, m_fc->w, m_fc->w0, m_fc->T, m_fc->T0, dt, GRID_SIZE); - dens_temp_step(sd, sT, m_fc->T, m_fc->T0, m_fc->d, m_fc->d0, m_fc->u, m_fc->v, m_fc->w, dt, GRID_SIZE); -} - - - -void clear_buffer(float* x) -{ - int i; - for (i=0; id=buffers[i++]; m_fc->d0=buffers[i++]; - m_fc->T=buffers[i++]; m_fc->T0=buffers[i++]; - m_fc->u=buffers[i++]; m_fc->u0=buffers[i++]; - m_fc->v=buffers[i++]; m_fc->v0=buffers[i++]; - m_fc->w=buffers[i++]; m_fc->w0=buffers[i++]; - - clear_sources(sd, su, sv); - - size=(GRID_SIZE+2)*(GRID_SIZE+2)*(GRID_SIZE+2); - for (i=0; iv[i] = -0.5f; - - m_fc->_texture_data = (unsigned char*) MEM_callocN((30+2)*(30+2)*(30+2)*4, "fc_texture_data"); - - m_fc->_fp = 0; - - return m_fc; -} - -void f_free(fc *m_fc) -{ - if(m_fc) - { - if(m_fc->_texture_data) - MEM_freeN(m_fc->_texture_data); - - if(m_fc->_fp) - fclose(m_fc->_fp); - - MEM_freeN(m_fc); - } -} - diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 4bc1efc1e70..4a03f579fe8 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -49,7 +49,6 @@ #include "BLI_arithb.h" #include "BLI_edgehash.h" #include "BLI_linklist.h" -#include "BKE_collisions.h" #include "BKE_curve.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" @@ -71,20 +70,6 @@ #include "Bullet-C-Api.h" -// step is limited from 0 (frame start position) to 1 (frame end position) -void collision_move_object(CollisionModifierData *collmd, float step, float prevstep) -{ - float tv[3] = {0,0,0}; - unsigned int i = 0; - - for ( i = 0; i < collmd->numverts; i++ ) - { - VECSUB(tv, collmd->xnew[i].co, collmd->x[i].co); - VECADDS(collmd->current_x[i].co, collmd->x[i].co, tv, prevstep); - VECADDS(collmd->current_xnew[i].co, collmd->x[i].co, tv, step); - VECSUB(collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co); - } -} /** @@ -232,7 +217,7 @@ int gsl_poly_solve_quadratic (float a, float b, float c, float *x0, float *x1) * page 4, left column */ -int collisions_get_collision_time(float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3]) +int cloth_get_collision_time(float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3]) { int num_sols = 0; @@ -333,7 +318,7 @@ int collisions_get_collision_time(float a[3], float b[3], float c[3], float d[3] } // w3 is not perfect -void collisions_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) +void cloth_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) { double tempV1[3], tempV2[3], tempV4[3]; double a,b,c,d,e,f; @@ -376,3 +361,884 @@ DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], floa VECADDMUL(to, v3, w3); } +// unused in the moment, has some bug in +DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal[3], double normalVelocity, + double frictionConstant, double delta_V_n) +{ + float vrel_t_pre[3]; + float vrel_t[3]; + VECSUBS(vrel_t_pre, vrel, normal, normalVelocity); + VECCOPY(to, vrel_t_pre); + VecMulf(to, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); +} + +int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + unsigned int i = 0; + int result = 0; + LinkNode *search = NULL; + CollPair *collpair = NULL; + Cloth *cloth1, *cloth2; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + search = clmd->coll_parms.collision_list; + + while(search) + { + collpair = search->link; + + // compute barycentric coordinates for both collision points + cloth_compute_barycentric(collpair->pa, + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3); + + cloth_compute_barycentric(collpair->pb, + cloth2->verts[collpair->bp1].txold, + cloth2->verts[collpair->bp2].txold, + cloth2->verts[collpair->bp3].txold, + &u1, &u2, &u3); + + // Calculate relative "velocity". + interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3); + + interpolateOnTriangle(v2, cloth2->verts[collpair->bp1].tv, cloth2->verts[collpair->bp2].tv, cloth2->verts[collpair->bp3].tv, u1, u2, u3); + + VECSUB(relativeVelocity, v1, v2); + + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). + magrelVel = INPR(relativeVelocity, collpair->normal); + + // printf("magrelVel: %f\n", magrelVel); + + // Calculate masses of points. + + // If v_n_mag < 0 the edges are approaching each other. + if(magrelVel < -ALMOST_ZERO) + { + // Calculate Impulse magnitude to stop all motion in normal direction. + // const double I_mag = v_n_mag / (1/m1 + 1/m2); + float magnitude_i = magrelVel / 2.0f; // TODO implement masses + float tangential[3], magtangent, magnormal, collvel[3]; + float vrel_t_pre[3]; + float vrel_t[3]; + double impulse; + float epsilon = clmd->coll_parms.epsilon; + float overlap = (epsilon + ALMOST_ZERO-collpair->distance); + + // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); + + // magtangent = INPR(tangential, tangential); + + // Apply friction impulse. + if (magtangent < -ALMOST_ZERO) + { + + // printf("friction applied: %f\n", magtangent); + // TODO check original code + /* + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential); + */ + } + + + impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + // printf("impulse: %f\n", impulse); + + VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); + cloth1->verts[collpair->ap1].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); + cloth1->verts[collpair->ap2].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); + cloth1->verts[collpair->ap3].impulse_count++; + + result = 1; + + /* + if (overlap > ALMOST_ZERO) { + double I_mag = overlap * 0.1; + + impulse = -I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); + cloth1->verts[collpair->ap1].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); + cloth1->verts[collpair->ap2].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); + cloth1->verts[collpair->ap3].impulse_count++; + } + */ + + // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case + + // Apply the impulse and increase impulse counters. + + /* + // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent); + VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); + // VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); + magtangent = Normalize(vrel_t_pre); + VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent)); + + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre); + */ + + + + } + + search = search->next; + } + + + return result; +} + +int cloth_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + +} + + +int cloth_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + +} + +void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +{ + CollPair *collpair = NULL; + Cloth *cloth1=NULL, *cloth2=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL, *verts2=NULL; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0; + + for(i = 0; i < 4; i++) + { + collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + // check all possible pairs of triangles + if(i == 0) + { + collpair->ap1 = face1->v1; + collpair->ap2 = face1->v2; + collpair->ap3 = face1->v3; + + collpair->bp1 = face2->v1; + collpair->bp2 = face2->v2; + collpair->bp3 = face2->v3; + + } + + if(i == 1) + { + if(face1->v4) + { + collpair->ap1 = face1->v3; + collpair->ap2 = face1->v4; + collpair->ap3 = face1->v1; + + collpair->bp1 = face2->v1; + collpair->bp2 = face2->v2; + collpair->bp3 = face2->v3; + } + else + i++; + } + + if(i == 2) + { + if(face2->v4) + { + collpair->ap1 = face1->v1; + collpair->ap2 = face1->v2; + collpair->ap3 = face1->v3; + + collpair->bp1 = face2->v3; + collpair->bp2 = face2->v4; + collpair->bp3 = face2->v1; + } + else + i+=2; + } + + if(i == 3) + { + if((face1->v4)&&(face2->v4)) + { + collpair->ap1 = face1->v3; + collpair->ap2 = face1->v4; + collpair->ap3 = face1->v1; + + collpair->bp1 = face2->v3; + collpair->bp2 = face2->v4; + collpair->bp3 = face2->v1; + } + else + i++; + } + + // calc SIPcode (?) + + if(i < 4) + { + // calc distance + normal + distance = plNearestPoints( + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, collpair->pa,collpair->pb,collpair->vector); + + if (distance <= (epsilon + ALMOST_ZERO)) + { + // printf("dist: %f\n", (float)distance); + + // collpair->face1 = tree1->tri_index; + // collpair->face2 = tree2->tri_index; + + VECCOPY(collpair->normal, collpair->vector); + Normalize(collpair->normal); + + collpair->distance = distance; + BLI_linklist_append(&clmd->coll_parms.collision_list, collpair); + } + else + { + MEM_freeN(collpair); + } + } + else + { + MEM_freeN(collpair); + } + } +} + +int cloth_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) +{ + Cloth *cloth1, *cloth2; + ClothVertex *verts1, *verts2; + float temp[3]; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + return 0; +} + +void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +{ + EdgeCollPair edgecollpair; + Cloth *cloth1=NULL, *cloth2=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL, *verts2=NULL; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0, j = 0, k = 0; + int numsolutions = 0; + float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + for( i = 0; i < 5; i++) + { + if(i == 0) + { + edgecollpair.p11 = face1->v1; + edgecollpair.p12 = face1->v2; + } + else if(i == 1) + { + edgecollpair.p11 = face1->v2; + edgecollpair.p12 = face1->v3; + } + else if(i == 2) + { + if(face1->v4) + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v4; + } + else + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v1; + i+=5; // get out of here after this edge pair is handled + } + } + else if(i == 3) + { + if(face1->v4) + { + edgecollpair.p11 = face1->v4; + edgecollpair.p12 = face1->v1; + } + else + continue; + } + else + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v1; + } + + + for( j = 0; j < 5; j++) + { + if(j == 0) + { + edgecollpair.p21 = face2->v1; + edgecollpair.p22 = face2->v2; + } + else if(j == 1) + { + edgecollpair.p21 = face2->v2; + edgecollpair.p22 = face2->v3; + } + else if(j == 2) + { + if(face2->v4) + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v4; + } + else + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v1; + } + } + else if(j == 3) + { + if(face2->v4) + { + edgecollpair.p21 = face2->v4; + edgecollpair.p22 = face2->v1; + } + else + continue; + } + else + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v1; + } + + + if(!cloth_are_edges_adjacent(clmd, coll_clmd, &edgecollpair)) + { + VECSUB(a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold); + VECSUB(b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v); + VECSUB(c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold); + VECSUB(d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v); + VECSUB(e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold); + VECSUB(f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v); + + numsolutions = cloth_get_collision_time(a, b, c, d, e, f, solution); + + for (k = 0; k < numsolutions; k++) + { + if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) + { + float out_collisionTime = solution[k]; + + // TODO: check for collisions + + // TODO: put into (edge) collision list + + // printf("Moving edge found!\n"); + } + } + } + } + } +} + +void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +{ + CollPair collpair; + Cloth *cloth1=NULL, *cloth2=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL, *verts2=NULL; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0, j = 0, k = 0; + int numsolutions = 0; + float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; + + for(i = 0; i < 2; i++) + { + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + // check all possible pairs of triangles + if(i == 0) + { + collpair.ap1 = face1->v1; + collpair.ap2 = face1->v2; + collpair.ap3 = face1->v3; + + collpair.pointsb[0] = face2->v1; + collpair.pointsb[1] = face2->v2; + collpair.pointsb[2] = face2->v3; + collpair.pointsb[3] = face2->v4; + } + + if(i == 1) + { + if(face1->v4) + { + collpair.ap1 = face1->v3; + collpair.ap2 = face1->v4; + collpair.ap3 = face1->v1; + + collpair.pointsb[0] = face2->v1; + collpair.pointsb[1] = face2->v2; + collpair.pointsb[2] = face2->v3; + collpair.pointsb[3] = face2->v4; + } + else + i++; + } + + // calc SIPcode (?) + + if(i < 2) + { + VECSUB(a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold); + VECSUB(b, verts1[collpair.ap2].v, verts1[collpair.ap1].v); + VECSUB(c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold); + VECSUB(d, verts1[collpair.ap3].v, verts1[collpair.ap1].v); + + for(j = 0; j < 4; j++) + { + if((j==3) && !(face2->v4)) + break; + + VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold); + VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v); + + numsolutions = cloth_get_collision_time(a, b, c, d, e, f, solution); + + for (k = 0; k < numsolutions; k++) + { + if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) + { + float out_collisionTime = solution[k]; + + // TODO: check for collisions + + // TODO: put into (point-face) collision list + + // printf("Moving found!\n"); + + } + } + + // TODO: check borders for collisions + } + + } + } +} + +void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +{ + // TODO: check for adjacent + cloth_collision_moving_edges(clmd, coll_clmd, tree1, tree2); + + cloth_collision_moving_tris(clmd, coll_clmd, tree1, tree2); + cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); +} + +// move collision objects forward in time and update static bounding boxes +void cloth_update_collision_objects(float step) +{ + Base *base=NULL; + ClothModifierData *coll_clmd=NULL; + Object *coll_ob=NULL; + unsigned int i=0; + + // search all objects for collision object + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + Cloth *coll_cloth = coll_clmd->clothObject; + BVH *coll_bvh = coll_clmd->clothObject->tree; + unsigned int coll_numverts = coll_cloth->numverts; + + // update position of collision object + for(i = 0; i < coll_numverts; i++) + { + VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx); + + VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step); + + // no dt here because of float rounding errors + VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold); + } + + // update BVH of collision object + bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING + } + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } +} + +// CLOTH_MAX_THRESHOLD defines how much collision rounds/loops should be taken +#define CLOTH_MAX_THRESHOLD 10 + +// cloth - object collisions +int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) +{ + Base *base=NULL; + ClothModifierData *coll_clmd=NULL; + Cloth *cloth=NULL; + Object *coll_ob=NULL; + BVH *cloth_bvh=NULL; + unsigned int i=0, j = 0, numfaces = 0, numverts = 0; + unsigned int result = 0, ic = 0, rounds = 0; // result counts applied collisions; ic is for debug output; + ClothVertex *verts = NULL; + float tnull[3] = {0,0,0}; + int ret = 0; + + if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) + { + return 0; + } + cloth = clmd->clothObject; + verts = cloth->verts; + cloth_bvh = (BVH *) cloth->tree; + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + + //////////////////////////////////////////////////////////// + // static collisions + //////////////////////////////////////////////////////////// + + // update cloth bvh + bvh_update(clmd, cloth_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function) + + // update collision objects + cloth_update_collision_objects(step); + + do + { + result = 0; + ic = 0; + clmd->coll_parms.collision_list = NULL; + + // check all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + BVH *coll_bvh = coll_clmd->clothObject->tree; + + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static); + } + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence + { + result = 0; + + // handle all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject) + result += cloth_collision_response_static(clmd, coll_clmd); + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } + } + } + + // free collision list + if(clmd->coll_parms.collision_list) + { + LinkNode *search = clmd->coll_parms.collision_list; + while(search) + { + CollPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(clmd->coll_parms.collision_list,NULL); + + clmd->coll_parms.collision_list = NULL; + } + + printf("ic: %d\n", ic); + rounds++; + } + while(result && (CLOTH_MAX_THRESHOLD>rounds)); + + printf("\n"); + + //////////////////////////////////////////////////////////// + // update positions + // this is needed for bvh_calc_DOP_hull_moving() [kdop.c] + //////////////////////////////////////////////////////////// + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // moving collisions + //////////////////////////////////////////////////////////// + + + // update cloth bvh + bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING + + // update moving bvh for collision object once + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + if(!coll_clmd->clothObject) + continue; + + // if collision object go on + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + BVH *coll_bvh = coll_clmd->clothObject->tree; + + bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING + } + } + + + do + { + result = 0; + ic = 0; + clmd->coll_parms.collision_list = NULL; + + // check all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + BVH *coll_bvh = coll_clmd->clothObject->tree; + + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving); + } + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence + { + result = 0; + + // handle all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject) + result += cloth_collision_response_moving_tris(clmd, coll_clmd); + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } + } + } + + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + + // update cloth bvh + bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING + + + // free collision list + if(clmd->coll_parms.collision_list) + { + LinkNode *search = clmd->coll_parms.collision_list; + while(search) + { + CollPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(clmd->coll_parms.collision_list,NULL); + + clmd->coll_parms.collision_list = NULL; + } + + printf("ic: %d\n", ic); + rounds++; + } + while(result && (CLOTH_MAX_THRESHOLD>rounds)); + + + //////////////////////////////////////////////////////////// + // update positions + velocities + //////////////////////////////////////////////////////////// + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + //////////////////////////////////////////////////////////// + + return MIN2(ret, 1); +} diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index a1d60b34125..b154cb0e755 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -46,11 +46,9 @@ #include "DNA_lattice_types.h" #include "DNA_scene_types.h" #include "DNA_modifier_types.h" -#include "BLI_arithb.h" #include "BLI_blenlib.h" -#include "BLI_edgehash.h" +#include "BLI_arithb.h" #include "BLI_threads.h" -#include "BKE_collisions.h" #include "BKE_curve.h" #include "BKE_displist.h" #include "BKE_effect.h" @@ -63,7 +61,6 @@ #include "BKE_global.h" #include "BIF_editdeform.h" -#include "Bullet-C-Api.h" #ifdef _WIN32 #include @@ -85,14 +82,18 @@ void itend(void) double itval() { return ((double)_itend.QuadPart - - (double)_itstart.QuadPart)/((double)ifreq.QuadPart); + (double)_itstart.QuadPart)/((double)ifreq.QuadPart); } #else #include +// intrinsics need better compile flag checking +// #include +// #include +// #include - static struct timeval _itstart, _itend; - static struct timezone itz; - void itstart(void) +static struct timeval _itstart, _itend; +static struct timezone itz; +void itstart(void) { gettimeofday(&_itstart, &itz); } @@ -108,7 +109,14 @@ double itval() return t2-t1; } #endif - +/* +#define C99 +#ifdef C99 +#defineDO_INLINE inline +#else +#defineDO_INLINE static +#endif +*/ struct Cloth; ////////////////////////////////////////// @@ -172,7 +180,7 @@ void print_fvector(float m3[3]) // long float vector float (*)[3] /////////////////////////// /* print long vector on console: for debug output */ -DO_INLINE void print_lfvector(lfVector *fLongVector, unsigned int verts) +DO_INLINE void print_lfvector(float (*fLongVector)[3], unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -188,7 +196,7 @@ DO_INLINE lfVector *create_lfvector(unsigned int verts) // return (lfVector *)cloth_aligned_malloc(&MEMORY_BASE, verts * sizeof(lfVector)); } /* delete long vector */ -DO_INLINE void del_lfvector(lfVector *fLongVector) +DO_INLINE void del_lfvector(float (*fLongVector)[3]) { if (fLongVector != NULL) { @@ -202,7 +210,7 @@ DO_INLINE void cp_lfvector(float (*to)[3], float (*from)[3], unsigned int verts) memcpy(to, from, verts * sizeof(lfVector)); } /* init long vector with float[3] */ -DO_INLINE void init_lfvector(lfVector *fLongVector, float vector[3], unsigned int verts) +DO_INLINE void init_lfvector(float (*fLongVector)[3], float vector[3], unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -216,7 +224,7 @@ DO_INLINE void zero_lfvector(float (*to)[3], unsigned int verts) memset(to, 0.0f, verts * sizeof(lfVector)); } /* multiply long vector with scalar*/ -DO_INLINE void mul_lfvectorS(float (*to)[3], lfVector *fLongVector, float scalar, unsigned int verts) +DO_INLINE void mul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts) { unsigned int i = 0; @@ -227,7 +235,7 @@ DO_INLINE void mul_lfvectorS(float (*to)[3], lfVector *fLongVector, float scalar } /* multiply long vector with scalar*/ /* A -= B * float */ -DO_INLINE void submul_lfvectorS(float (*to)[3], lfVector *fLongVector, float scalar, unsigned int verts) +DO_INLINE void submul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -236,12 +244,12 @@ DO_INLINE void submul_lfvectorS(float (*to)[3], lfVector *fLongVector, float sca } } /* dot product for big vector */ -DO_INLINE float dot_lfvector(lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) +DO_INLINE float dot_lfvector(float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) { unsigned int i = 0; float temp = 0.0; // schedule(guided, 2) -#pragma omp parallel for reduction(+: temp) private(i) +#pragma omp parallel for reduction(+: temp) for(i = 0; i < verts; i++) { temp += INPR(fLongVectorA[i], fLongVectorB[i]); @@ -249,7 +257,7 @@ DO_INLINE float dot_lfvector(lfVector *fLongVectorA, lfVector *fLongVectorB, uns return temp; } /* A = B + C --> for big vector */ -DO_INLINE void add_lfvector_lfvector(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) +DO_INLINE void add_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) { unsigned int i = 0; @@ -260,7 +268,7 @@ DO_INLINE void add_lfvector_lfvector(float (*to)[3], lfVector *fLongVectorA, lfV } /* A = B + C * float --> for big vector */ -DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, float bS, unsigned int verts) +DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts) { unsigned int i = 0; @@ -271,7 +279,7 @@ DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], lfVector *fLongVectorA, lf } } /* A = B * float + C * float --> for big vector */ -DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], lfVector *fLongVectorA, float aS, lfVector *fLongVectorB, float bS, unsigned int verts) +DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float aS, float (*fLongVectorB)[3], float bS, unsigned int verts) { unsigned int i = 0; @@ -281,7 +289,7 @@ DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], lfVector *fLongVectorA, f } } /* A = B - C * float --> for big vector */ -DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, float bS, unsigned int verts) +DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -291,7 +299,7 @@ DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], lfVector *fLongVectorA, lf } /* A = B - C --> for big vector */ -DO_INLINE void sub_lfvector_lfvector(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) +DO_INLINE void sub_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) { unsigned int i = 0; @@ -323,7 +331,7 @@ DO_INLINE void cp_fmatrix(float to[3][3], float from[3][3]) DO_INLINE float det_fmatrix(float m[3][3]) { return m[0][0]*m[1][1]*m[2][2] + m[1][0]*m[2][1]*m[0][2] + m[0][1]*m[1][2]*m[2][0] - -m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2]; + -m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2]; } DO_INLINE void inverse_fmatrix(float to[3][3], float from[3][3]) { @@ -561,37 +569,34 @@ DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) /* SPARSE SYMMETRIC multiply big matrix with long vector*/ /* STATUS: verified */ -DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector) +DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (*fLongVector)[3]) { unsigned int i = 0; - lfVector *temp = create_lfvector(from[0].vcount); - zero_lfvector(to, from[0].vcount); - -#pragma omp parallel sections private(i) + /* process diagonal elements */ + for(i = 0; i < from[0].vcount; i++) { -#pragma omp section - { - for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) - { - muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); - } - } -#pragma omp section - { - for(i = 0; i < from[0].vcount+from[0].scount; i++) - { - muladd_fmatrix_fvector(temp[from[i].r], from[i].m, fLongVector[from[i].c]); - } - } + muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); } - add_lfvector_lfvector(to, to, temp, from[0].vcount); - - del_lfvector(temp); - - -} + /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */ + // TODO: pragma below is wrong, correct it! + // #pragma omp parallel for shared(to,from, fLongVector) private(i) + for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) + { + // muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); + + to[from[i].c][0] += INPR(from[i].m[0],fLongVector[from[i].r]); + to[from[i].c][1] += INPR(from[i].m[1],fLongVector[from[i].r]); + to[from[i].c][2] += INPR(from[i].m[2],fLongVector[from[i].r]); + + // muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); + + to[from[i].r][0] += INPR(from[i].m[0],fLongVector[from[i].c]); + to[from[i].r][1] += INPR(from[i].m[1],fLongVector[from[i].c]); + to[from[i].r][2] += INPR(from[i].m[2],fLongVector[from[i].c]); + } +} /* SPARSE SYMMETRIC multiply big matrix with long vector (for diagonal preconditioner) */ /* STATUS: verified */ @@ -699,7 +704,7 @@ static float I[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; static float ZERO[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}; typedef struct Implicit_Data { - lfVector *X, *V, *Xnew, *Vnew, *F, *B, *dV, *z; + lfVector *X, *V, *Xnew, *Vnew, *olddV, *F, *B, *dV, *z; fmatrix3x3 *A, *dFdV, *dFdX, *S, *P, *Pinv, *bigI; } Implicit_Data; @@ -735,6 +740,8 @@ int implicit_init (Object *ob, ClothModifierData *clmd) id->Xnew = create_lfvector(cloth->numverts); id->V = create_lfvector(cloth->numverts); id->Vnew = create_lfvector(cloth->numverts); + id->olddV = create_lfvector(cloth->numverts); + zero_lfvector(id->olddV, cloth->numverts); id->F = create_lfvector(cloth->numverts); id->B = create_lfvector(cloth->numverts); id->dV = create_lfvector(cloth->numverts); @@ -767,7 +774,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) // dFdV_start[i].c = big_I[i].c = big_zero[i].c = id->A[i+cloth->numverts].c = id->dFdV[i+cloth->numverts].c = id->dFdX[i+cloth->numverts].c = - id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = spring->kl; + id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = spring->kl; spring->matrix_index = i + cloth->numverts; @@ -776,7 +783,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) for(i = 0; i < cloth->numverts; i++) { - VECCOPY(id->X[i], cloth->x[i]); + VECCOPY(id->X[i], verts[i].x); } return 1; @@ -805,6 +812,7 @@ int implicit_free (ClothModifierData *clmd) del_lfvector(id->Xnew); del_lfvector(id->V); del_lfvector(id->Vnew); + del_lfvector(id->olddV); del_lfvector(id->F); del_lfvector(id->B); del_lfvector(id->dV); @@ -817,31 +825,6 @@ int implicit_free (ClothModifierData *clmd) return 1; } -void cloth_bending_mode(ClothModifierData *clmd, int enabled) -{ - Cloth *cloth = clmd->clothObject; - Implicit_Data *id; - - if(cloth) - { - id = cloth->implicit; - - if(id) - { - if(enabled) - { - cloth->numsprings = cloth->numspringssave; - } - else - { - cloth->numsprings = cloth->numothersprings; - } - - id->A[0].scount = id->dFdV[0].scount = id->dFdX[0].scount = id->P[0].scount = id->Pinv[0].scount = id->bigI[0].scount = cloth->numsprings; - } - } -} - DO_INLINE float fb(float length, float L) { float x = length/L; @@ -892,7 +875,7 @@ DO_INLINE void filter(lfVector *V, fmatrix3x3 *S) } } -int cg_filtered(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) +int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) { // Solves for unknown X in equation AX=B unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100; @@ -905,14 +888,14 @@ int cg_filtered(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix tmp = create_lfvector(numverts); r = create_lfvector(numverts); - // zero_lfvector(dv, CLOTHPARTICLES); - filter(dv, S); + // zero_lfvector(ldV, CLOTHPARTICLES); + filter(ldV, S); - add_lfvector_lfvector(dv, dv, z, numverts); + add_lfvector_lfvector(ldV, ldV, z, numverts); // r = B - Mul(tmp,A,X); // just use B if X known to be zero cp_lfvector(r, lB, numverts); - mul_bfmatrix_lfvector(tmp, lA, dv); + mul_bfmatrix_lfvector(tmp, lA, ldV); sub_lfvector_lfvector(r, r, tmp, numverts); filter(r,S); @@ -932,7 +915,7 @@ int cg_filtered(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix a = s/dot_lfvector(d, q, numverts); // X = X + d*a; - add_lfvector_lfvectorS(dv, dv, d, a, numverts); + add_lfvector_lfvectorS(ldV, ldV, d, a, numverts); // r = r - q*a; sub_lfvector_lfvectorS(r, r, q, a, numverts); @@ -947,16 +930,12 @@ int cg_filtered(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix conjgrad_loopcount++; } - // itend(); - // printf("cg_filtered time: %f\n", (float)itval()); - conjgrad_lasterror = s; del_lfvector(q); del_lfvector(d); del_lfvector(tmp); del_lfvector(r); - // printf("W/O conjgrad_loopcount: %d\n", conjgrad_loopcount); return conjgrad_loopcountrestlen; - float cb = clmd->sim_parms->structural; + float cb = clmd->sim_parms.structural; float nullf[3] = {0,0,0}; float stretch_force[3] = {0,0,0}; float bending_force[3] = {0,0,0}; float damping_force[3] = {0,0,0}; float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; + Cloth *cloth = clmd->clothObject; + ClothVertex *verts = cloth->verts; VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); @@ -1125,13 +1106,13 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, /* if(length>L) { - if((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) - && ((((length-L)*100.0f/L) > clmd->sim_parms->maxspringlen))) // cut spring! - { - s->flags |= CSPRING_FLAG_DEACTIVATE; - return; - } - } + if((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) + && ((((length-L)*100.0f/L) > clmd->sim_parms.maxspringlen))) // cut spring! + { + s->flags |= CSPRING_FLAG_DEACTIVATE; + return; + } + } */ mul_fvector_S(dir, extent, 1.0f/length); } @@ -1141,19 +1122,6 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, } - /* - if(s->type == CLOTH_SPRING_TYPE_COLLISION) - { - if(length < L) - { - mul_fvector_S(stretch_force, dir, (100.0*(length-L))); - - VECADD(s->f, s->f, stretch_force); - } - return; - } - */ - // calculate force of structural + shear springs if(s->type != CLOTH_SPRING_TYPE_BENDING) { @@ -1161,72 +1129,56 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, { s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = clmd->sim_parms->structural; + k = clmd->sim_parms.structural; mul_fvector_S(stretch_force, dir, (k*(length-L))); VECADD(s->f, s->f, stretch_force); // Ascher & Boxman, p.21: Damping only during elonglation - mul_fvector_S(damping_force, extent, clmd->sim_parms->Cdis * 0.01 * ((INPR(vel,extent)/length))); + mul_fvector_S(damping_force, extent, clmd->sim_parms.Cdis * ((INPR(vel,extent)/length))); VECADD(s->f, s->f, damping_force); dfdx_spring_type1(s->dfdx, dir,length,L,k); - dfdv_damp(s->dfdv, dir,clmd->sim_parms->Cdis); + dfdv_damp(s->dfdv, dir,clmd->sim_parms.Cdis); } } else // calculate force of bending springs { if(length < L) { - // clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; - s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = clmd->sim_parms->bending; + k = clmd->sim_parms.bending; mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); VECADD(s->f, s->f, bending_force); - - // if(INPR(bending_force,bending_force) > 0.13*0.13) - { - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; - } - - + dfdx_spring_type2(s->dfdx, dir,length,L,k, cb); - /* - if(s->ij == 300 || s->kl == 300) - printf("id->F[0]: %f, id->F[1]: %f, id->F[2]: %f\n", s->f[0], s->f[1], s->f[2]); - */ } } } -DO_INLINE int cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) +DO_INLINE void cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) { if(s->flags & CLOTH_SPRING_FLAG_NEEDED) { - VECADD(lF[s->ij], lF[s->ij], s->f); - VECSUB(lF[s->kl], lF[s->kl], s->f); - if(s->type != CLOTH_SPRING_TYPE_BENDING) { sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, s->dfdv); sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv); - add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); + add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); } - else if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE)) - return 0; - + + VECADD(lF[s->ij], lF[s->ij], s->f); + VECSUB(lF[s->kl], lF[s->kl], s->f); + sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx); sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, s->dfdx); add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, s->dfdx); - } - - return 1; + } } DO_INLINE void calculateTriangleNormal(float to[3], lfVector *X, MFace mface) @@ -1275,7 +1227,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec /* Collect forces and derivatives: F,dFdX,dFdV */ Cloth *cloth = clmd->clothObject; unsigned int i = 0; - float spring_air = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */ + float spring_air = clmd->sim_parms.Cvi * 0.01f; /* viscosity of air scaled in percent */ float gravity[3]; float tm2[3][3] = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}}; ClothVertex *verts = cloth->verts; @@ -1286,7 +1238,8 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec float kd, ks; LinkNode *search = cloth->springs; - VECCOPY(gravity, clmd->sim_parms->gravity); + + VECCOPY(gravity, clmd->sim_parms.gravity); mul_fvector_S(gravity, gravity, 0.001f); /* scale gravity force */ /* set dFdX jacobi matrix to zero */ @@ -1299,24 +1252,24 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec submul_lfvectorS(lF, lV, spring_air, numverts); /* do goal stuff */ - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { for(i = 0; i < numverts; i++) { if(verts [i].goal < SOFTGOALSNAP) { // current_position = xold + t * (newposition - xold) - VECSUB(tvect, cloth->xconst[i], cloth->xold[i]); + VECSUB(tvect, verts[i].xconst, verts[i].xold); mul_fvector_S(tvect, tvect, time); - VECADD(tvect, tvect, cloth->xold[i]); + VECADD(tvect, tvect, verts[i].xold); VECSUB(auxvect, tvect, lX[i]); - ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms->goalspring)-1.0f ; + ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms.goalspring)-1.0f ; VECADDS(lF[i], lF[i], auxvect, -ks); // calulate damping forces generated by goals - VECSUB(velgoal, cloth->xold[i], cloth->xconst[i]); - kd = clmd->sim_parms->goalfrict * 0.01f; // friction force scale taken from SB + VECSUB(velgoal,verts[i].xold, verts[i].xconst); + kd = clmd->sim_parms.goalfrict * 0.01f; // friction force scale taken from SB VECSUBADDSS(lF[i], velgoal, kd, lV[i], kd); } @@ -1329,7 +1282,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec float speed[3] = {0.0f, 0.0f,0.0f}; float force[3]= {0.0f, 0.0f, 0.0f}; -// #pragma omp parallel for private (i) shared(lF) + #pragma omp parallel for private (i) shared(lF) for(i = 0; i < cloth->numverts; i++) { float vertexnormal[3]={0,0,0}; @@ -1353,42 +1306,24 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec while(search) { // only handle active springs - // if(((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)){} + // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)){} cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); search = search->next; } - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE) - { - if(cloth->numspringssave != cloth->numsprings) - { - cloth_bending_mode(clmd, 1); - } - } - else - { - if(cloth->numspringssave == cloth->numsprings) - { - cloth_bending_mode(clmd, 0); - } - } - // apply spring forces search = cloth->springs; while(search) { // only handle active springs - // if(((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)) - if(!cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX)) - break; + // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) + cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); search = search->next; } - - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; } -void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, fmatrix3x3 *P, fmatrix3x3 *Pinv) +void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv) { unsigned int numverts = dFdV[0].vcount; @@ -1396,46 +1331,48 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto initdiag_bfmatrix(A, I); zero_lfvector(dV, numverts); - subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); + subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); + mul_bfmatrix_lfvector(dFdXmV, dFdX, lV); + add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts); - // TODO: unstable with quality=5 + stiffness=7000 + no zero_lfvector() + itstart(); + cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */ + // cg_filtered_pre(dV, A, B, z, olddV, P, Pinv, dt); - // TODO: unstable with quality=5 + stiffness=7000 - // cg_filtered_pre(dV, A, B, z, S, P, Pinv); + itend(); + // printf("cg_filtered calc time: %f\n", (float)itval()); + cp_lfvector(olddV, dV, numverts); + // advance velocities add_lfvector_lfvector(Vnew, lV, dV, numverts); + del_lfvector(dFdXmV); } int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) -{ - unsigned int i=0; +{ + unsigned int i=0, j; float step=0.0f, tf=1.0f; Cloth *cloth = clmd->clothObject; ClothVertex *verts = cloth->verts; unsigned int numverts = cloth->numverts; - float dt = 1.0f / clmd->sim_parms->stepsPerFrame; + float dt = 1.0f / clmd->sim_parms.stepsPerFrame; Implicit_Data *id = cloth->implicit; int result = 0; - float force = 0, lastforce = 0; - // lfVector *dx; - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { for(i = 0; i < numverts; i++) { // update velocities with constrained velocities from pinned verts if(verts [i].goal >= SOFTGOALSNAP) { - float temp[3]; - VECSUB(temp, cloth->xconst[i], cloth->xold[i]); - VECSUB(id->z[i], temp, id->V[i]); - + VECSUB(id->V[i], verts[i].xconst, verts[i].xold); // VecMulf(id->V[i], 1.0 / dt); } } @@ -1445,43 +1382,13 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase { effectors= pdInitEffectors(ob,NULL); - // clear constraint matrix from collisions - if(clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) - { - for(i = 0; i < id->S[0].vcount; i++) - { - if(!(verts [id->S[i].r].goal >= SOFTGOALSNAP)) - { - id->S[0].vcount = i-1; - break; - } - } - } - // calculate - cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); + cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); - // check for sleeping - // if(!(clmd->coll_parms->flags & CLOTH_SIMSETTINGS_FLAG_SLEEP)) - { - simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->P, id->Pinv); + add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); - add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); - } - /* - dx = create_lfvector(numverts); - sub_lfvector_lfvector(dx, id->Xnew, id->X, numverts); - force = dot_lfvector(dx, dx, numverts); - del_lfvector(dx); - - if((force < 0.00001) && (lastforce >= force)) - clmd->coll_parms->flags |= CLOTH_SIMSETTINGS_FLAG_SLEEP; - else if((lastforce*2 < force)) - clmd->coll_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_SLEEP; - */ - lastforce = force; - - if(clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + if(clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) { // collisions // itstart(); @@ -1489,42 +1396,46 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // update verts to current positions for(i = 0; i < numverts; i++) { - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { if(verts [i].goal >= SOFTGOALSNAP) { float tvect[3] = {.0,.0,.0}; // VECSUB(tvect, id->Xnew[i], verts[i].xold); mul_fvector_S(tvect, id->V[i], step+dt); - VECADD(tvect, tvect, cloth->xold[i]); + VECADD(tvect, tvect, verts[i].xold); VECCOPY(id->Xnew[i], tvect); } } - VECCOPY(cloth->current_x[i], id->Xnew[i]); - VECSUB(cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i]); - VECCOPY(cloth->v[i], cloth->current_v[i]); - } - - // call collision function - result = cloth_bvh_objcollision(clmd, step + dt, step, dt); - - // copy corrected positions back to simulation - if(result) - { - memcpy(cloth->current_xold, cloth->current_x, sizeof(lfVector) * numverts); - memcpy(id->Xnew, cloth->current_x, sizeof(lfVector) * numverts); + VECCOPY(verts[i].tx, id->Xnew[i]); - for(i = 0; i < numverts; i++) - { - VECCOPY(id->Vnew[i], cloth->current_v[i]); + VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + VECCOPY(verts[i].v, verts[i].tv); + } + + // call collision function + result = cloth_bvh_objcollision(clmd, step + dt, dt); + + // copy corrected positions back to simulation + for(i = 0; i < numverts; i++) + { + if(result) + { + // VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + + VECCOPY(verts[i].txold, verts[i].tx); + + VECCOPY(id->Xnew[i], verts[i].tx); + + VECCOPY(id->Vnew[i], verts[i].tv); VecMulf(id->Vnew[i], 1.0f / dt); } - } - else - { - memcpy(cloth->current_xold, id->Xnew, sizeof(lfVector) * numverts); + else + { + VECCOPY(verts[i].txold, id->Xnew[i]); + } } // X = Xnew; @@ -1538,9 +1449,8 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // calculate cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); - simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->P, id->Pinv); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); } - } else { @@ -1553,817 +1463,49 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // V = Vnew; cp_lfvector(id->V, id->Vnew, numverts); - + step += dt; if(effectors) pdEndEffectors(effectors); } - - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - { - for(i = 0; i < numverts; i++) + + for(i = 0; i < numverts; i++) + { + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { if(verts [i].goal < SOFTGOALSNAP) { - VECCOPY(cloth->current_xold[i], id->X[i]); - VECCOPY(cloth->x[i], id->X[i]); + VECCOPY(verts[i].txold, id->X[i]); + VECCOPY(verts[i].x, id->X[i]); + VECCOPY(verts[i].v, id->V[i]); } else { - VECCOPY(cloth->current_xold[i], cloth->xconst[i]); - VECCOPY(cloth->x[i], cloth->xconst[i]); + VECCOPY(verts[i].txold, verts[i].xconst); + VECCOPY(verts[i].x, verts[i].xconst); + VECCOPY(verts[i].v, id->V[i]); } } + else + { + VECCOPY(verts[i].txold, id->X[i]); + VECCOPY(verts[i].x, id->X[i]); + VECCOPY(verts[i].v, id->V[i]); + } } - else - { - memcpy(cloth->current_xold, id->X, sizeof(lfVector) * numverts); - memcpy(cloth->x, id->X, sizeof(lfVector) * numverts); - } - - memcpy(cloth->v, id->V, sizeof(lfVector) * numverts); - return 1; } void implicit_set_positions (ClothModifierData *clmd) { Cloth *cloth = clmd->clothObject; - unsigned int numverts = cloth->numverts; + ClothVertex *verts = cloth->verts; + unsigned int numverts = cloth->numverts, i; Implicit_Data *id = cloth->implicit; - memcpy(id->X, cloth->x, sizeof(lfVector) * numverts); - memcpy(id->V, cloth->v, sizeof(lfVector) * numverts); -} - -unsigned int implicit_getcreate_S_index(ClothModifierData *clmd, unsigned int index) -{ - Cloth *cloth = clmd->clothObject; - Implicit_Data *id = cloth->implicit; - unsigned int i = 0, pinned = 0; - - pinned = id->S[0].vcount; - - for(i = 0; i < pinned; i++) - { - if(id->S[i].r == index) - { - return index; - } - } - - // create new PINNED entry in constraint matrix - id->S[0].vcount++; - id->S[pinned].c = id->S[pinned].r = index; - return pinned; -} - -int collisions_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollisionPair *collpair ) -{ - - unsigned int i = 0; - int result = 0; - LinkNode *search = NULL; - Cloth *cloth1 = NULL; - float w1, w2, w3, u1, u2, u3; - float v1[3], v2[3], relativeVelocity[3]; - float magrelVel = 0.0; - float epsilon = clmd->coll_parms->epsilon; - - - cloth1 = clmd->clothObject; - - if(!collpair) - { - return 0; - } - - // TODO: check distance & calc normal - // calc distance + normal - collpair->distance = plNearestPoints( - cloth1->current_xold[collpair->point_indexA[0]], - cloth1->current_xold[collpair->point_indexA[1]], - cloth1->current_xold[collpair->point_indexA[2]], - collmd->current_x[collpair->point_indexB[0]].co, - collmd->current_x[collpair->point_indexB[1]].co, - collmd->current_x[collpair->point_indexB[2]].co, - collpair->pa,collpair->pb,collpair->vector); - - if (collpair->distance > (epsilon + ALMOST_ZERO)) - { - printf("collpair->distance > (epsilon + ALMOST_ZERO)\n"); - return 0; - } - - printf("IN1\n"); - - // compute barycentric coordinates for both collision points - collisions_compute_barycentric (collpair->pa, - cloth1->current_xold[collpair->point_indexA[0]], - cloth1->current_xold[collpair->point_indexA[1]], - cloth1->current_xold[collpair->point_indexA[2]], - &w1, &w2, &w3 ); - - collisions_compute_barycentric (collpair->pb, - collmd->current_x[collpair->point_indexB[0]].co, - collmd->current_x[collpair->point_indexB[1]].co, - collmd->current_x[collpair->point_indexB[2]].co, - &u1, &u2, &u3 ); - - // Calculate relative "velocity". - interpolateOnTriangle ( v1, cloth1->current_v[collpair->point_indexA[0]], cloth1->current_v[collpair->point_indexA[1]], cloth1->current_v[collpair->point_indexA[2]], w1, w2, w3 ); - - interpolateOnTriangle ( v2, collmd->current_v[collpair->point_indexB[0]].co, collmd->current_v[collpair->point_indexB[1]].co, collmd->current_v[collpair->point_indexB[2]].co, u1, u2, u3 ); - - VECSUB ( relativeVelocity, v1, v2 ); - - // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). - magrelVel = INPR ( relativeVelocity, collpair->normal ); - - // printf("magrelVel: %f\n", magrelVel); - - // Calculate masses of points. - - // If v_n_mag < 0 the edges are approaching each other. - if ( magrelVel < -ALMOST_ZERO ) - { - - // Calculate Impulse magnitude to stop all motion in normal direction. - // const double I_mag = v_n_mag / (1/m1 + 1/m2); - float magnitude_i = magrelVel / 2.0f; // TODO implement masses - float tangential[3], magtangent, magnormal, collvel[3]; - float vrel_t_pre[3]; - float vrel_t[3]; - double impulse; - float overlap = ( epsilon + ALMOST_ZERO-collpair->distance ); - - printf("magrelVel < -ALMOST_ZERO\n"); - - // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); - - // magtangent = INPR(tangential, tangential); - - // Apply friction impulse. - if ( magtangent < -ALMOST_ZERO ) - { - - // printf("friction applied: %f\n", magtangent); - // TODO check original code - } - - - impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); - - // printf("impulse: %f\n", impulse); - - // face A - VECADDMUL ( cloth1->verts[collpair->point_indexA[0]].impulse, collpair->normal, w1 * impulse ); - cloth1->verts[collpair->point_indexA[0]].impulse_count++; - - VECADDMUL ( cloth1->verts[collpair->point_indexA[1]].impulse, collpair->normal, w2 * impulse ); - cloth1->verts[collpair->point_indexA[1]].impulse_count++; - - VECADDMUL ( cloth1->verts[collpair->point_indexA[2]].impulse, collpair->normal, w3 * impulse ); - cloth1->verts[collpair->point_indexA[2]].impulse_count++; - - // face B - /* - VECADDMUL ( collmd->verts[collpair->point_indexB[0]].impulse, collpair->normal, u1 * impulse ); - collmd->verts[collpair->point_indexB[0]].impulse_count++; - - VECADDMUL ( collmd->verts[collpair->point_indexB[1]].impulse, collpair->normal, u2 * impulse ); - collmd->verts[collpair->point_indexB[1]].impulse_count++; - - VECADDMUL ( collmd->verts[collpair->point_indexB[2]].impulse, collpair->normal, u3 * impulse ); - collmd->verts[collpair->point_indexB[2]].impulse_count++; - */ - - - result = 1; - - // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case - - // Apply the impulse and increase impulse counters. - - } - - return result; -} - - -int collisions_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) -{ - return 0; -} - - -int collisions_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) -{ - return 0; -} - -void cloth_collision_static(ClothModifierData *clmd, LinkNode *collision_list) -{ - /* - CollPair *collpair = NULL; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; - double distance = 0; - float epsilon = clmd->coll_parms->epsilon; - unsigned int i = 0; - - for(i = 0; i < 4; i++) - { - collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); - - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(cloth2->mfaces[tree2->tri_index]); - - // check all possible pairs of triangles - if(i == 0) - { - collpair->ap1 = face1->v1; - collpair->ap2 = face1->v2; - collpair->ap3 = face1->v3; - - collpair->bp1 = face2->v1; - collpair->bp2 = face2->v2; - collpair->bp3 = face2->v3; - -} - - if(i == 1) - { - if(face1->v4) - { - collpair->ap1 = face1->v3; - collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; - - collpair->bp1 = face2->v1; - collpair->bp2 = face2->v2; - collpair->bp3 = face2->v3; -} - else - i++; -} - - if(i == 2) - { - if(face2->v4) - { - collpair->ap1 = face1->v1; - collpair->ap2 = face1->v2; - collpair->ap3 = face1->v3; - - collpair->bp1 = face2->v3; - collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; -} - else - i+=2; -} - - if(i == 3) - { - if((face1->v4)&&(face2->v4)) - { - collpair->ap1 = face1->v3; - collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; - - collpair->bp1 = face2->v3; - collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; -} - else - i++; -} - - - if(i < 4) - { - // calc distance + normal - distance = plNearestPoints( - verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, collpair->pa,collpair->pb,collpair->vector); - - if (distance <= (epsilon + ALMOST_ZERO)) - { - // printf("dist: %f\n", (float)distance); - - // collpair->face1 = tree1->tri_index; - // collpair->face2 = tree2->tri_index; - - // VECCOPY(collpair->normal, collpair->vector); - // Normalize(collpair->normal); - - // collpair->distance = distance; - -} - else - { - MEM_freeN(collpair); -} -} - else - { - MEM_freeN(collpair); -} -} - */ -} - -int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) -{ - Cloth *cloth1, *cloth2; - ClothVertex *verts1, *verts2; - float temp[3]; - /* - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - - VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - - VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - - VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - */ - return 0; -} - - -void collisions_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) -{ - /* - EdgeCollPair edgecollpair; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; - double distance = 0; - float epsilon = clmd->coll_parms->epsilon; - unsigned int i = 0, j = 0, k = 0; - int numsolutions = 0; - float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; - - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(cloth2->mfaces[tree2->tri_index]); - - for( i = 0; i < 5; i++) - { - if(i == 0) - { - edgecollpair.p11 = face1->v1; - edgecollpair.p12 = face1->v2; -} - else if(i == 1) - { - edgecollpair.p11 = face1->v2; - edgecollpair.p12 = face1->v3; -} - else if(i == 2) - { - if(face1->v4) - { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v4; -} - else - { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v1; - i+=5; // get out of here after this edge pair is handled -} -} - else if(i == 3) - { - if(face1->v4) - { - edgecollpair.p11 = face1->v4; - edgecollpair.p12 = face1->v1; -} - else - continue; -} - else - { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v1; -} - - - for( j = 0; j < 5; j++) - { - if(j == 0) - { - edgecollpair.p21 = face2->v1; - edgecollpair.p22 = face2->v2; -} - else if(j == 1) - { - edgecollpair.p21 = face2->v2; - edgecollpair.p22 = face2->v3; -} - else if(j == 2) - { - if(face2->v4) - { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v4; -} - else - { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v1; -} -} - else if(j == 3) - { - if(face2->v4) - { - edgecollpair.p21 = face2->v4; - edgecollpair.p22 = face2->v1; -} - else - continue; -} - else - { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v1; -} - - - if(!collisions_are_edges_adjacent(clmd, coll_clmd, &edgecollpair)) - { - VECSUB(a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold); - VECSUB(b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v); - VECSUB(c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold); - VECSUB(d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v); - VECSUB(e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold); - VECSUB(f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v); - - numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution); - - for (k = 0; k < numsolutions; k++) - { - if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) - { - float out_collisionTime = solution[k]; - - // TODO: check for collisions - - // TODO: put into (edge) collision list - - printf("Moving edge found!\n"); -} -} -} -} -} - */ -} - -void collisions_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) -{ - /* - CollPair collpair; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; - double distance = 0; - float epsilon = clmd->coll_parms->epsilon; - unsigned int i = 0, j = 0, k = 0; - int numsolutions = 0; - float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; - - for(i = 0; i < 2; i++) - { - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(cloth2->mfaces[tree2->tri_index]); - - // check all possible pairs of triangles - if(i == 0) - { - collpair.ap1 = face1->v1; - collpair.ap2 = face1->v2; - collpair.ap3 = face1->v3; - - collpair.pointsb[0] = face2->v1; - collpair.pointsb[1] = face2->v2; - collpair.pointsb[2] = face2->v3; - collpair.pointsb[3] = face2->v4; -} - - if(i == 1) - { - if(face1->v4) - { - collpair.ap1 = face1->v3; - collpair.ap2 = face1->v4; - collpair.ap3 = face1->v1; - - collpair.pointsb[0] = face2->v1; - collpair.pointsb[1] = face2->v2; - collpair.pointsb[2] = face2->v3; - collpair.pointsb[3] = face2->v4; -} - else - i++; -} - - // calc SIPcode (?) - - if(i < 2) - { - VECSUB(a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold); - VECSUB(b, verts1[collpair.ap2].v, verts1[collpair.ap1].v); - VECSUB(c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold); - VECSUB(d, verts1[collpair.ap3].v, verts1[collpair.ap1].v); - - for(j = 0; j < 4; j++) - { - if((j==3) && !(face2->v4)) - break; - - VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold); - VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v); - - numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution); - - for (k = 0; k < numsolutions; k++) - { - if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) - { - float out_collisionTime = solution[k]; - - // TODO: check for collisions - - // TODO: put into (point-face) collision list - - printf("Moving found!\n"); - -} -} - - // TODO: check borders for collisions -} - -} -} - */ -} - -void collisions_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) -{ - /* - // TODO: check for adjacent - collisions_collision_moving_edges(clmd, coll_clmd, tree1, tree2); - - collisions_collision_moving_tris(clmd, coll_clmd, tree1, tree2); - collisions_collision_moving_tris(coll_clmd, clmd, tree2, tree1); - */ -} - -// cloth - object collisions -int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, float dt) -{ - - Base *base = NULL; - CollisionModifierData *collmd = NULL; - Cloth *cloth = NULL; - Object *ob2 = NULL; - BVH *bvh1 = NULL, *bvh2 = NULL, *self_bvh; - LinkNode *collision_list = NULL; - unsigned int i = 0, j = 0, index; - int collisions = 0, count = 0; - float (*current_x)[3]; - Implicit_Data *id = NULL; - int ret = 0; - - if (!(((Cloth *)clmd->clothObject)->tree)) - { - printf("No BVH found\n"); - return 0; - } - - cloth = clmd->clothObject; - bvh1 = cloth->tree; - self_bvh = cloth->selftree; - id = cloth->implicit; - - //////////////////////////////////////////////////////////// - // static collisions - //////////////////////////////////////////////////////////// - - // update cloth bvh - bvh_update_from_float3 ( bvh1, cloth->current_xold, cloth->numverts, cloth->current_x, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) - - // check all collision objects - for ( base = G.scene->base.first; base; base = base->next ) - { - ob2 = base->object; - collmd = ( CollisionModifierData * ) modifiers_findByType ( ob2, eModifierType_Collision ); - - if ( !collmd ) - continue; - - // check if there is a bounding volume hierarchy - if ( collmd->tree ) - { - bvh2 = collmd->tree; - - // update position + bvh of collision object - collision_move_object ( collmd, step, prevstep ); - bvh_update_from_mvert ( collmd->tree, collmd->current_x, collmd->numverts, NULL, 0 ); - - // fill collision list - collisions += bvh_traverse ( bvh1->root, bvh2->root, &collision_list ); - - // call static collision response - if ( collision_list ) - { - LinkNode *search = collision_list; - - while ( search ) - { - collisions_collision_response_static(clmd, collmd, (CollisionPair *)search->link); - - search = search->next; - } - } - - // free collision list - if ( collision_list ) - { - LinkNode *search = collision_list; - - while ( search ) - { - CollisionPair *coll_pair = search->link; - - MEM_freeN ( coll_pair ); - search = search->next; - } - BLI_linklist_free ( collision_list,NULL ); - - collision_list = NULL; - } - } - } - - // vertex weight = 2 - - for(i = 0; i < cloth->numverts; i++) - if ((cloth->verts[i].impulse_count > 0) && !(cloth->verts[i].flags & CVERT_FLAG_PINNED)) - { - printf("applying impulse\n"); - - VECADDS(cloth->current_v[i], cloth->current_v[i], cloth->verts[i].impulse, 1.0 / (cloth->verts[i].impulse_count * 2.0)); - - // reset - cloth->verts[i].impulse_count = 0; - cloth->verts[i].impulse[0] = 0.0; - cloth->verts[i].impulse[1] = 0.0; - cloth->verts[i].impulse[2] = 0.0; - - ret = 1; - } - - ////////////////////////////////////////////// - // update velocities + positions - ////////////////////////////////////////////// - for(i = 0; i < cloth->numverts; i++) - { - VECADD(cloth->current_x[i], cloth->current_xold[i], cloth->current_v[i]); - } - ////////////////////////////////////////////// - - - // Test on *simple* selfcollisions - collisions = 1; - count = 0; - current_x = cloth->current_x; // needed for openMP - /* - // #pragma omp parallel for private(i,j, collisions) shared(current_x) - // for ( count = 0; count < 6; count++ ) - { - collisions = 0; - - for ( i = 0; i < cloth->numverts; i++ ) - { - float mindistance1 = cloth->verts[i].collball; - - for ( j = i + 1; j < cloth->numverts; j++ ) - { - float temp[3]; - float length = 0; - - float mindistance2 = cloth->verts[j].collball; - - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - { - if ( ( cloth->verts [i].goal >= SOFTGOALSNAP ) - && ( cloth->verts [j].goal >= SOFTGOALSNAP ) ) - { - continue; - } - } - - // check for adjacent points - if ( BLI_edgehash_haskey ( cloth->edgehash, i, j ) ) - { - continue; - } - - VECSUB ( temp, current_x[i], current_x[j] ); - - length = Normalize ( temp ); - - if ( length < ((mindistance1 + mindistance2)) ) - { - float correction = ((mindistance1 + mindistance2)) - length; - - if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) && ( cloth->verts [i].goal >= SOFTGOALSNAP ) ) - { - VecMulf ( temp, -correction ); - VECADD ( current_x[j], current_x[j], temp ); - } - else if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) && ( cloth->verts [j].goal >= SOFTGOALSNAP ) ) - { - VecMulf ( temp, correction ); - VECADD ( current_x[i], current_x[i], temp ); - } - else - { - unsigned int pinned = id->S[0].vcount; - - printf("correction: %f\n", correction); - - VecMulf ( temp, -correction*0.5 ); - VECADD ( current_x[j], current_x[j], temp ); - VECSUB ( cloth->current_v[j], cloth->current_x[j], cloth->current_xold[j] ); - - index = implicit_getcreate_S_index(clmd, j); - id->S[index].pinned = 1; - - VECSUB ( current_x[i], current_x[i], temp ); - VECSUB ( cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i] ); - - index = implicit_getcreate_S_index(clmd, i); - id->S[index].pinned = 1; - - cloth_add_spring (clmd, i, j, mindistance1 + mindistance2, CLOTH_SPRING_TYPE_COLLISION); - } - - collisions = 1; - } - } - } - } - */ - - ////////////////////////////////////////////// - // SELFCOLLISIONS: update velocities - ////////////////////////////////////////////// - /* - for ( i = 0; i < cloth->numverts; i++ ) - { - VECSUB ( cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i] ); - } - */ - ////////////////////////////////////////////// - - return ret; + for(i = 0; i < numverts; i++) + { + VECCOPY(id->X[i], verts[i].x); + VECCOPY(id->V[i], verts[i].v); + } } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index e7ce752424d..3b69f47b1f4 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -75,7 +75,6 @@ #include "BKE_main.h" #include "BKE_anim.h" #include "BKE_bad_level_calls.h" -#include "BKE_collisions.h" #include "BKE_curve.h" #include "BKE_customdata.h" #include "BKE_global.h" @@ -2727,7 +2726,7 @@ static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob, { DisplaceModifierData *dmd = (DisplaceModifierData*) md; - walk(userData, ob, (ID **)&dmd->texture); + walk(userData, ob, &dmd->texture); displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc) walk, userData); } @@ -4947,15 +4946,9 @@ static void softbodyModifier_deformVerts( static void clothModifier_initData(ModifierData *md) { ClothModifierData *clmd = (ClothModifierData*) md; - - clmd->sim_parms = MEM_callocN(sizeof(SimulationSettings), - "cloth sim parms"); - clmd->coll_parms = MEM_callocN(sizeof(CollisionSettings), - "cloth coll parms"); - cloth_init (clmd); } -/* + static void clothModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) @@ -4978,23 +4971,6 @@ static void clothModifier_deformVerts( if(dm) dm->release(dm); } -*/ - -static DerivedMesh *clothModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) -{ - ClothModifierData *clmd = (ClothModifierData*) md; - DerivedMesh *result=NULL; - - result = clothModifier_do(clmd, ob, derivedData, useRenderParams, isFinalCalc); - - if(result) - { - return result; - } - return derivedData; -} static void clothModifier_updateDepgraph( ModifierData *md, DagForest *forest, Object *ob, @@ -5011,13 +4987,14 @@ static void clothModifier_updateDepgraph( Object *ob1= base->object; if(ob1 != ob) { - CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision); - if(collmd) - { - DagNode *curNode = dag_get_node(forest, ob1); - - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA); - + ClothModifierData *coll_clmd = (ClothModifierData *)modifiers_findByType(ob1, eModifierType_Cloth); + if(coll_clmd) + { + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + DagNode *curNode = dag_get_node(forest, ob1); + dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA); + } } } } @@ -5026,12 +5003,12 @@ static void clothModifier_updateDepgraph( CustomDataMask clothModifier_requiredDataMask(ModifierData *md) { - ClothModifierData *clmd = (ClothModifierData *)md; + ClothModifierData *clmd = (HookModifierData *)md; CustomDataMask dataMask = 0; /* ask for vertexgroups if we need them */ - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - if (clmd->sim_parms->vgroup_mass > 0) + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + if (clmd->sim_parms.vgroup_mass > 0) dataMask |= (1 << CD_MDEFORMVERT); return dataMask; @@ -5049,156 +5026,11 @@ static void clothModifier_freeData(ModifierData *md) if (clmd) { - - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; + clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; cloth_free_modifier (clmd); - - MEM_freeN(clmd->sim_parms); - MEM_freeN(clmd->coll_parms); } } -/* Collision */ - -static void collisionModifier_initData(ModifierData *md) -{ - CollisionModifierData *collmd = (CollisionModifierData*) md; - - collmd->x = NULL; - collmd->xnew = NULL; - collmd->current_x = NULL; - collmd->current_xnew = NULL; - collmd->current_v = NULL; - collmd->time = -1; - collmd->numverts = 0; - collmd->tree = NULL; -} - -static void collisionModifier_freeData(ModifierData *md) -{ - CollisionModifierData *collmd = (CollisionModifierData*) md; - - if (collmd) - { - if(collmd->tree) - bvh_free(collmd->tree); - if(collmd->x) - MEM_freeN(collmd->x); - if(collmd->xnew) - MEM_freeN(collmd->xnew); - if(collmd->current_x) - MEM_freeN(collmd->current_x); - if(collmd->current_xnew) - MEM_freeN(collmd->current_xnew); - if(collmd->current_v) - MEM_freeN(collmd->current_v); - - collmd->x = NULL; - collmd->xnew = NULL; - collmd->current_x = NULL; - collmd->current_xnew = NULL; - collmd->current_v = NULL; - collmd->time = -1; - collmd->numverts = 0; - collmd->tree = NULL; - } -} - -static int collisionModifier_dependsOnTime(ModifierData *md) -{ - return 1; -} - -static void collisionModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) -{ - CollisionModifierData *collmd = (CollisionModifierData*) md; - DerivedMesh *dm = NULL; - float current_time = 0; - unsigned int numverts = 0, i = 0; - MVert *tempVert = NULL; - - // if possible use/create DerivedMesh - - if(derivedData) dm = CDDM_copy(derivedData); - else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); - - if(!ob->pd) - { - printf("collisionModifier_deformVerts: Should not happen!\n"); - return; - } - - if(dm) - { - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); - - - current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); - - if(current_time > collmd->time) - { - numverts = dm->getNumVerts ( dm ); - - // check if mesh has changed - if(collmd->x && (numverts != collmd->numverts)) - collisionModifier_freeData((ModifierData *)collmd); - - if(collmd->time == -1) // first time - { - collmd->x = dm->dupVertArray(dm); // frame start position - - for ( i = 0; i < numverts; i++ ) - { - // we save global positions - Mat4MulVecfl ( ob->obmat, collmd->x[i].co ); - } - - collmd->xnew = MEM_dupallocN(collmd->x); // frame end position - collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame - collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame - collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame - - collmd->numverts = numverts; - - // TODO: epsilon - // create bounding box hierarchy - collmd->tree = bvh_build_from_mvert(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->current_x, numverts, ob->pd->pdef_sbift); - } - else if(numverts == collmd->numverts) - { - // put positions to old positions - tempVert = collmd->x; - collmd->x = collmd->xnew; - collmd->xnew = tempVert; - - memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); - - for ( i = 0; i < numverts; i++ ) - { - // we save global positions - Mat4MulVecfl ( ob->obmat, collmd->xnew[i].co ); - } - - memcpy(collmd->current_xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); - memcpy(collmd->current_x, dm->getVertArray(dm), numverts*sizeof(MVert)); - - // recalc static bounding boxes - bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0); - - printf("bvh_update_from_mvert\n"); - } - - collmd->time = current_time; - } - } - - if(dm) - dm->release(dm); -} - /* Boolean */ static void booleanModifier_copyData(ModifierData *md, ModifierData *target) @@ -7010,10 +6842,10 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->deformVerts = softbodyModifier_deformVerts; mti = INIT_TYPE(Cloth); - mti->type = eModifierTypeType_Nonconstructive; + mti->type = eModifierTypeType_OnlyDeform; mti->initData = clothModifier_initData; - mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_RequiresOriginalData; + mti->flags = eModifierTypeFlag_AcceptsCVs; + // | eModifierTypeFlag_RequiresOriginalData; // | eModifierTypeFlag_SupportsMapping // | eModifierTypeFlag_SupportsEditmode // | eModifierTypeFlag_EnableInEditmode; @@ -7021,19 +6853,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->freeData = clothModifier_freeData; mti->requiredDataMask = clothModifier_requiredDataMask; // mti->copyData = clothModifier_copyData; - // mti->deformVerts = clothModifier_deformVerts; - mti->applyModifier = clothModifier_applyModifier; + mti->deformVerts = clothModifier_deformVerts; mti->updateDepgraph = clothModifier_updateDepgraph; - - mti = INIT_TYPE(Collision); - mti->type = eModifierTypeType_OnlyDeform; - mti->initData = collisionModifier_initData; - mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_RequiresOriginalData; - mti->dependsOnTime = collisionModifier_dependsOnTime; - mti->freeData = collisionModifier_freeData; - mti->deformVerts = collisionModifier_deformVerts; - // mti->copyData = collisionModifier_copyData; mti = INIT_TYPE(Boolean); mti->type = eModifierTypeType_Nonconstructive; @@ -7293,11 +7114,11 @@ int modifiers_isSoftbodyEnabled(Object *ob) return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -ClothModifierData *modifiers_isClothEnabled(Object *ob) +ModifierData * modifiers_isClothEnabled(Object *ob) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); - return clmd; + return md; } int modifiers_isParticleEnabled(Object *ob) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index d215bdf67cd..37d15b65de5 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2986,12 +2986,14 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) ClothModifierData *clmd = (ClothModifierData*) md; clmd->clothObject = NULL; - + /* clmd->sim_parms= newdataadr(fd, clmd->sim_parms); clmd->coll_parms= newdataadr(fd, clmd->coll_parms); + */ } else if (md->type==eModifierType_Collision) { + /* CollisionModifierData *collmd = (CollisionModifierData*) md; collmd->x = NULL; @@ -3001,6 +3003,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) collmd->time = -1; collmd->numverts = 0; collmd->tree = NULL; + */ } else if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 275e3b18c4c..3326d38c56f 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -827,8 +827,10 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) } else if(md->type==eModifierType_Cloth) { ClothModifierData *clmd = (ClothModifierData*) md; + /* writestruct(wd, DATA, "SimulationSettings", 1, clmd->sim_parms); writestruct(wd, DATA, "CollisionSettings", 1, clmd->coll_parms); + */ } else if (md->type==eModifierType_MeshDeform) { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 4d8fbf1a6fc..2bbe328d170 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -32,7 +32,64 @@ #ifndef DNA_CLOTH_TYPES_H #define DNA_CLOTH_TYPES_H -typedef struct SimulationSettings { +#include "DNA_listBase.h" + + +/** +* Pin and unpin frames are the frames on which the vertices stop moving. +* They will assume the position they had prior to pinFrame until unpinFrame +* is reached. +*/ +typedef struct ClothVertex +{ + int flags; /* General flags per vertex. */ + float v [3]; /* The velocity of the point. */ + float xconst [3]; /* constrained position */ + float x [3]; /* The current position of this vertex. */ + float xold [3]; /* The previous position of this vertex.*/ + float tx [3]; /* temporary position */ + float txold [3]; /* temporary old position */ + float tv[3]; /* temporary "velocity", mostly used as tv = tx-txold */ + float mass; /* mass / weight of the vertex */ + float goal; /* goal, from SB */ + float impulse[3]; /* used in collision.c */ + unsigned int impulse_count; /* same as above */ +} +ClothVertex; + + +/** +* The definition of a spring. +*/ +typedef struct ClothSpring +{ + int ij; /* Pij from the paper, one end of the spring. */ + int kl; /* Pkl from the paper, one end of the spring. */ + float restlen; /* The original length of the spring. */ + int matrix_index; /* needed for implicit solver (fast lookup) */ + int type; /* types defined in BKE_cloth.h ("springType") */ + int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ + float dfdx[3][3]; + float dfdv[3][3]; + float f[3]; +} +ClothSpring; + + + +/** +* This struct contains all the global data required to run a simulation. +* At the time of this writing, this structure contains data appropriate +* to run a simulation as described in Deformation Constraints in a +* Mass-Spring Model to Describe Rigid Cloth Behavior by Xavier Provot. +* +* I've tried to keep similar, if not exact names for the variables as +* are presented in the paper. Where I've changed the concept slightly, +* as in stepsPerFrame comapred to the time step in the paper, I've used +* variables with different names to minimize confusion. +**/ +typedef struct SimulationSettings +{ short vgroup_mass; /* optional vertexgroup name for assigning weight. */ short pad; float mingoal; /* see SB */ @@ -55,23 +112,56 @@ typedef struct SimulationSettings { float eff_force_scale;/* Scaling of effector forces (see softbody_calc_forces).*/ float eff_wind_scale; /* Scaling of effector wind (see softbody_calc_forces). */ float sim_time_old; + struct LinkNode *cache; float defgoal; - float goalfrict; + int goalfrict; float goalspring; int maxspringlen; /* in percent!; if tearing enabled, a spring will get cut */ int lastframe; /* frame on which simulation stops */ int firstframe; /* frame on which simulation starts */ -} SimulationSettings; + struct Object *ob; +} +SimulationSettings; -typedef struct CollisionSettings { + +typedef struct CollisionSettings +{ float epsilon; /* The radius of a particle in the cloth. */ float self_friction; /* Fiction/damping with self contact. */ float friction; /* Friction/damping applied on contact with other object.*/ short collision_type; /* which collision system is used. */ short loop_count; /* How many iterations for the collision loop. */ + struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */ int flags; /* collision flags defined in BKE_cloth.h */ - float selfepsilon; -} CollisionSettings; + int pad; +} +CollisionSettings; +/** +* This structure describes a cloth object against which the +* simulation can run. +* +* The m and n members of this structure represent the assumed +* rectangular ordered grid for which the original paper is written. +* At some point they need to disappear and we need to determine out +* own connectivity of the mesh based on the actual edges in the mesh. +* +**/ +typedef struct Cloth +{ + struct ClothVertex *verts; /* The vertices that represent this cloth. */ + struct LinkNode *springs; /* The springs connecting the mesh. */ + unsigned int numverts; /* The number of verts == m * n. */ + unsigned int numsprings; /* The count of springs. */ + unsigned int numfaces; + unsigned char old_solver_type; + unsigned char pad2; + short pad3; + void *tree; /* collision tree for this cloth object */ + struct MFace *mfaces; + void *implicit; /* our implicit solver connects to this pointer */ +} +Cloth; + #endif diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 384ac37484d..f8b6f4202a5 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -7,6 +7,8 @@ #define MODSTACK_DEBUG 1 +#include "DNA_cloth_types.h" + /* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE! */ typedef enum ModifierType { @@ -347,8 +349,8 @@ typedef struct ClothModifierData { ModifierData modifier; struct Cloth *clothObject; /* The internal data structure for cloth. */ - struct SimulationSettings *sim_parms; /* definition is in DNA_cloth_types.h */ - struct CollisionSettings *coll_parms; /* definition is in DNA_cloth_types.h */ + struct SimulationSettings sim_parms; /* definition is in DNA_cloth_types.h */ + struct CollisionSettings coll_parms; /* definition is in DNA_cloth_types.h */ } ClothModifierData; typedef struct CollisionModifierData { diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index f71f6adb051..662e0df093b 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -48,7 +48,6 @@ #include "BKE_action.h" #include "BKE_cloth.h" -#include "BKE_collisions.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_library.h" @@ -2989,29 +2988,66 @@ void do_effects_panels(unsigned short event) allqueue(REDRAWVIEW3D, 0); break; case B_CLOTH_CLEARCACHEALL: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - if(clmd) + CFRA= 1; + update_for_newframe_muted(); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + cloth_clear_cache(ob, clmd, 2); + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); + } + } + break; + case B_CLOTH_CLEARCACHEFRAME: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + cloth_clear_cache(ob, clmd, MAX2(2.0,G.scene->r.cfra + 1.0)); + allqueue(REDRAWBUTSOBJECT, 0); + } + } + break; + case B_CLOTH_CHANGEPREROLL: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + if(clmd->sim_parms.cache) { CFRA= 1; update_for_newframe_muted(); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - cloth_clear_cache(ob, clmd, 2); allqueue(REDRAWBUTSOBJECT, 0); allqueue(REDRAWVIEW3D, 0); - } - } - break; - case B_CLOTH_RENEW: - { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - if(clmd) - { - do_object_panels(B_CLOTH_CLEARCACHEALL); - cloth_free_modifier (clmd); } } - break; + } + break; + case B_CLOTH_DEL_VG: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + clmd->sim_parms.vgroup_mass = 0; + do_object_panels(B_CLOTH_RENEW); + } + allqueue(REDRAWBUTSOBJECT, 0); + } + break; + case B_CLOTH_RENEW: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + do_object_panels(B_CLOTH_CLEARCACHEALL); + cloth_free_modifier (clmd); + } + } + break; default: if(event>=B_SELEFFECT && eventsim_parms->flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); + but = uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object", 170,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); - if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) + if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { Cloth *cloth = clmd->clothObject; int defCount; @@ -4798,18 +4834,18 @@ static void object_panel_cloth(Object *ob) val2=0; - // uiDefButBitI(block, TOG, CSIMSETT_FLAG_ADVANCED, REDRAWBUTSOBJECT, "Advanced", 180,200,130,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Enable advanced mode"); + // uiDefButBitI(block, TOG, CSIMSETT_FLAG_ADVANCED, REDRAWBUTSOBJECT, "Advanced", 180,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Enable advanced mode"); /* GENERAL STUFF */ uiClearButLock(); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms->structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms->bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility"); - uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,150,150,20, &clmd->sim_parms->stepsPerFrame, 3.0, 10.0, 5, 0, "Quality of the simulation (higher=>better=>slower)"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility"); + uiDefButI(block, NUM, B_CLOTH_RENEW, "Steps per Frame:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms->Cdis, 0.0, 10.0, 10, 0, "Spring damping"); - uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms->Cvi, 0.0, 10.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Spring damping"); + uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms.Cvi, 0.0, 10.0, 10, 0, "Apply gravitation to point movement"); uiBlockEndAlign(block); uiClearButLock(); @@ -4818,15 +4854,15 @@ static void object_panel_cloth(Object *ob) uiDefBut(block, LABEL, 0, "Gravity:", 10,100,60,20, NULL, 0.0, 0, 0, 0, ""); // uiClearButLock(); - uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,100,80,20, &clmd->sim_parms->gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,100,80,20, &clmd->sim_parms->gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:", 230,100,80,20, &clmd->sim_parms->gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,100,80,20, &clmd->sim_parms.gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,100,80,20, &clmd->sim_parms.gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:", 230,100,80,20, &clmd->sim_parms.gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); uiBlockEndAlign(block); /* GOAL STUFF */ uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Use Goal", 10,70,130,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); - if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Use Goal", 10,70,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); + if (clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { if(ob->type==OB_MESH) { @@ -4841,17 +4877,17 @@ static void object_panel_cloth(Object *ob) defCount = BLI_countlist (&ob->defbase); if (defCount == 0) { - clmd->sim_parms->vgroup_mass = 0; + clmd->sim_parms.vgroup_mass = 0; } sprintf (clvg2, "%s%s", clmvg, clvg1); - uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 140,70,20,20, &clmd->sim_parms->vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups"); + uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups"); MEM_freeN (clvg1); MEM_freeN (clvg2); - if(clmd->sim_parms->vgroup_mass) + if(clmd->sim_parms.vgroup_mass) { - bDeformGroup *defGroup = BLI_findlink(&ob->defbase, clmd->sim_parms->vgroup_mass-1); + bDeformGroup *defGroup = BLI_findlink(&ob->defbase, clmd->sim_parms.vgroup_mass-1); if(defGroup) uiDefBut(block, BUT, B_DIFF, defGroup->name, 160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group"); else @@ -4861,31 +4897,31 @@ static void object_panel_cloth(Object *ob) } else - uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); } else { - uiDefButS(block, TOG, B_CLOTH_RENEW, "W", 140,70,20,20, &clmd->sim_parms->vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + uiDefButS(block, TOG, B_CLOTH_RENEW, "W", 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); } - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Stiff:", 10,50,150,20, &clmd->sim_parms->goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Damp:", 160,50,150,20, &clmd->sim_parms->goalfrict, 0.0, 50.0, 10, 0, "Goal (vertex target position) friction"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Min:", 10,30,150,20, &clmd->sim_parms->mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Max:", 160,30,150,20, &clmd->sim_parms->maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Damp:", 160,50,150,20, &clmd->sim_parms.goalfrict , 0.0, 50.0, 10, 0, "Goal (vertex target position) friction"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Min:", 10,30,150,20, &clmd->sim_parms.mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Max:", 160,30,150,20, &clmd->sim_parms.maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); } uiBlockEndAlign(block); /* // no tearing supported anymore since modifier stack restrictions uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CSIMSETT_FLAG_TEARING_ENABLED, B_EFFECT_DEP, "Tearing", 10,0,150,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); + uiDefButBitI(block, TOG, CSIMSETT_FLAG_TEARING_ENABLED, B_EFFECT_DEP, "Tearing", 10,0,150,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); - if (clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) + if (clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) { - uiDefButI(block, NUM, B_DIFF, "Max extent:", 160,0,150,20, &clmd->sim_parms->maxspringlen, 1.0, 1000.0, 10, 0, "Maximum extension before spring gets cut"); - } + uiDefButI(block, NUM, B_DIFF, "Max extent:", 160,0,150,20, &clmd->sim_parms.maxspringlen, 1.0, 1000.0, 10, 0, "Maximum extension before spring gets cut"); + } uiBlockEndAlign(block); */ @@ -4904,7 +4940,7 @@ static void object_panel_cloth_II(Object *ob) clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) + if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { Cloth *cloth = clmd->clothObject; char str[128]; @@ -4915,18 +4951,18 @@ static void object_panel_cloth_II(Object *ob) uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - uiDefButI(block, NUM, B_DIFF, "First Frame:", 10,160,150,20, &clmd->sim_parms->firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts"); - uiDefButI(block, NUM, B_DIFF, "Last Frame:", 160,160,150,20, &clmd->sim_parms->lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops"); - /* - if(clmd->sim_parms->cache) + uiDefButI(block, NUM, B_DIFF, "First Frame:", 10,160,150,20, &clmd->sim_parms.firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts"); + uiDefButI(block, NUM, B_DIFF, "Last Frame:", 160,160,150,20, &clmd->sim_parms.lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops"); + + if(clmd->sim_parms.cache) { - int length = BLI_linklist_length(clmd->sim_parms->cache); + int length = BLI_linklist_length(clmd->sim_parms.cache); - // correct spelling if only 1 frame cacheed --> only gimmick - if(length-clmd->sim_parms->preroll>1) - sprintf (str, "Frame 1 - %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length); + /* correct spelling if only 1 frame cacheed --> only gimmick */ + if(length-clmd->sim_parms.preroll>1) + sprintf (str, "Frame 1 - %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms.preroll, clmd->sim_parms.preroll, length); else - sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length); + sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms.preroll, clmd->sim_parms.preroll, length); uiDefBut(block, LABEL, 0, str, 10,140,290,20, NULL, 0.0, 0, 0, 0, ""); uiDefBut(block, LABEL, 0, "Clear cache:", 10,120,290,20, NULL, 0.0, 0, 0, 0, ""); @@ -4934,15 +4970,15 @@ static void object_panel_cloth_II(Object *ob) uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 10, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache without preroll"); uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache"); if(length>1) // B_CLOTH_CHANGEPREROLL - uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms->preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); + uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); else uiDefBut(block, LABEL, 0, " ", 10,80,145,20, NULL, 0.0, 0, 0, 0, ""); } - else + else { uiDefBut(block, LABEL, 0, "No frames cached.", 10,120,290,20, NULL, 0.0, 0, 0, 0, ""); - }*/ - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,50,145,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); + } + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,50,145,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); uiBlockEndAlign(block); } } @@ -4952,32 +4988,41 @@ static void object_panel_cloth_II(Object *ob) static void object_panel_cloth_III(Object *ob) { uiBlock *block; + static int val; + uiBut *but; ClothModifierData *clmd = NULL; clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) - { - block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_III", UI_EMBOSS, UI_HELV, curarea->win); - uiNewPanelTabbed("Cloth", "Physics"); - if(uiNewPanel(curarea, block, "Cloth Collisions", "Physics", 651, 0, 318, 204)==0) return; - - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,160,130,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable collisions with this object"); - if (clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + { + if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { - // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ - uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,140,150,20, &clmd->coll_parms->epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); - uiDefBut(block, LABEL, 0, "",160,140,150,20, NULL, 0.0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Selfcoll balls:", 10,120,150,20, &clmd->coll_parms->selfepsilon, 0.001f, 1.0, 0.49f, 0, "Minimum distance between two selfcollision points"); + Cloth *cloth = clmd->clothObject; + char str[128]; + + block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_III", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Cloth", "Physics"); + if(uiNewPanel(curarea, block, "Cloth Collisions", "Physics", 651, 0, 318, 204)==0) return; + + uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,70,130,20, &clmd->coll_parms.flags, 0, 0, 0, 0, "Enable collisions with this object"); + if (clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + { + // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ + uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,30,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); + uiDefBut(block, LABEL, 0, "",160,30,150,20, NULL, 0.0, 0, 0, 0, ""); + } + else + uiDefBut(block, LABEL, 0, "",140,10,170,20, NULL, 0.0, 0, 0, 0, ""); + uiBlockEndAlign(block); } - else - uiDefBut(block, LABEL, 0, "",140,10,170,20, NULL, 0.0, 0, 0, 0, ""); - uiBlockEndAlign(block); } + // uiBlockEndAlign(block); } + void object_panels() { Object *ob; diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 111f0789ee9..61e4c6d5660 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -2454,112 +2454,6 @@ void draw_slices ( float m[][4] ) } } - -void draw_fl(ClothModifierData *clmd) -{ - int i; - float m[4][4]; - Cloth *cloth = clmd->clothObject; - fc *m_fc = NULL; - - if(!cloth) - return; - - m_fc = cloth->m_fc; - - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - // gluLookAt(0, 0, -_dist, 0, 0, 0, 0, 1, 0); - - // build_rotmatrix(m, _quat); - - glMultMatrixf(&m[0][0]); - - // ---------------------------------------- - // from ligth constructor - m_fc->_light_dir[0] = -1.0f; - m_fc->_light_dir[1] = 0.5f; - m_fc->_light_dir[2] = 0.0f; - - gen_ray_templ(m_fc->_ray_templ, m_fc->_light_dir, 30 + 2); - - cast_light(m_fc->_texture_data, m_fc->_ray_templ, m_fc->_light_dir, 30+2); - - glActiveTextureARB(GL_TEXTURE0_ARB); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 30+2, 30+2, 30+2, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_fc->_texture_data); - // ---------------------------------------- - - draw_slices(m); -/* - if (_dispstring != NULL) { - glMatrixMode(GL_PROJECTION); - glLoadMatrixd(_ortho_m); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glDisable(GL_TEXTURE_3D); - glDisable(GL_FRAGMENT_PROGRAM_ARB); - glColor4f(1.0, 1.0, 1.0, 1.0); - glRasterPos2i(-_sx/2 + 10, _sy/2 - 15); - - print_string(_dispstring); - - glMatrixMode(GL_PROJECTION); - glLoadMatrixd(_persp_m); - glMatrixMode(GL_MODELVIEW); - } -*/ -} - -void fc_load_frame(ClothModifierData *clmd) -{ - float* tmp = (float*) MEM_callocN(30*30*30*sizeof(float), "fc_tmp"); - float tmin=9999999, tmax=-99999999; - Cloth *cloth = clmd->clothObject; - fc *m_fc = NULL; - int i = 0; - - if(!cloth) - return; - - m_fc = cloth->m_fc; - - if (++m_fc->_cur_frame == m_fc->_nframes) { - fseek(m_fc->_fp, 12, SEEK_SET); - m_fc->_cur_frame = 0; - } - - fread(tmp, sizeof(float), 30*30*30, m_fc->_fp); - - for (i=0; i<30*30*30; i++) - { - m_fc->_texture_data[(i<<2)+1] = (unsigned char) (tmp[i]*255.0f); - } - - fread(tmp, sizeof(float), 30*30*30, m_fc->_fp); - - for (i=0; i<30*30*30; i++) - { - m_fc->_texture_data[(i<<2)] = (unsigned char) (tmp[i]*255.0f); - if (tmp[i]tmax) - tmax = tmp[i]; - m_fc->_texture_data[(i<<2)+2] = 0; - m_fc->_texture_data[(i<<2)+3] = 255; - } - - MEM_freeN(tmp); - - // cast_light(_N); DG NOT NEEDED - - glActiveTextureARB(GL_TEXTURE0_ARB); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 30, 30, 30, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_fc->_texture_data); -} - static void draw_mesh_object_outline(Object *ob, DerivedMesh *dm) { diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c index 615a9566b97..2e4ecd95709 100644 --- a/source/blender/src/vpaint.c +++ b/source/blender/src/vpaint.c @@ -51,6 +51,7 @@ #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_brush_types.h" +#include "DNA_cloth_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -747,7 +748,7 @@ static int sample_backbuf_area(VPaint *vp, int *indexar, int totface, int x, int struct ImBuf *ibuf; int x1, y1, x2, y2, a, tot=0, index; - if(totface>=MAXINDEX) return 0; + if(totface+4>=MAXINDEX) return 0; if(size>64.0) size= 64.0; @@ -777,7 +778,7 @@ static int sample_backbuf_area(VPaint *vp, int *indexar, int totface, int x, int size= (y2-y1)*(x2-x1); if(size<=0) return 0; - memset(indexar, 0, sizeof(int)*totface+2); /* plus 2! first element is total */ + memset(indexar, 0, sizeof(int)*totface+4); /* plus 2! first element is total, +2 was giving valgrind errors, +4 seems ok */ while(size--) { @@ -1350,7 +1351,7 @@ void weight_paint(void) // same goes for cloth if(modifiers_isClothEnabled(ob)) { - cloth_free_modifier(modifiers_isClothEnabled(ob)); + cloth_free_modifier((ClothModifierData *)modifiers_isClothEnabled(ob)); } BIF_undo_push("Weight Paint"); From 530039a4297d93998202391caedfbbbc2558499d Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 21 Jan 2008 02:23:03 +0000 Subject: [PATCH 071/101] Restructured many collision things again, GUI cleanup --- source/blender/blenkernel/BKE_cloth.h | 45 +- source/blender/blenkernel/BKE_collisions.h | 1 + source/blender/blenkernel/intern/cloth.c | 107 +++- source/blender/blenkernel/intern/collision.c | 90 +++- source/blender/blenkernel/intern/kdop.c | 533 +++++-------------- source/blender/blenkernel/intern/modifier.c | 150 ++++++ source/blender/makesdna/DNA_cloth_types.h | 2 +- source/blender/src/buttons_object.c | 38 +- 8 files changed, 488 insertions(+), 478 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index eb1f33ae600..592c34ad28e 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -129,38 +129,39 @@ void implicit_set_positions ( ClothModifierData *clmd ); void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float ( *vertexCos ) [3], int numverts ); // used in collision.c -typedef struct Tree +typedef struct CollisionTree { - struct Tree *nodes[4]; // 4 children --> quad-tree - struct Tree *parent; - struct Tree *nextLeaf; - struct Tree *prevLeaf; + 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; } -Tree; - -typedef struct Tree TreeNode; +CollisionTree; typedef struct BVH { unsigned int numfaces; unsigned int numverts; - ClothVertex *verts; // just a pointer to the original datastructure + // ClothVertex *verts; // just a pointer to the original datastructure + 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; - TreeNode *root; // TODO: saving the root --> is this really needed? YES! - TreeNode *leaf_tree; /* Tail of the leaf linked list. */ - TreeNode *leaf_root; /* Head of the leaf linked list. */ + 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; -typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 ); +typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree * tree1, CollisionTree * tree2 ); ///////////////////////////////////////////////// @@ -168,9 +169,15 @@ typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, ClothModifier //////////////////////////////////////////////// // needed for implicit.c -void bvh_collision_response ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 ); +void bvh_collision_response ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree * tree1, CollisionTree * tree2 ); int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ); +// needed for modifier.c +BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon); + +// needed for collision.c +void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving); + //////////////////////////////////////////////// @@ -180,13 +187,12 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ); // needed for cloth.c void bvh_free ( BVH * bvh ); -BVH *bvh_build ( ClothModifierData *clmd, float epsilon ); +void bvh_build (BVH *bvh); LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr ); // needed for collision.c -int bvh_traverse ( ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response ); -void bvh_update ( ClothModifierData * clmd, BVH * bvh, int moving ); - +int bvh_traverse ( ClothModifierData * clmd, ClothModifierData * coll_clmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response ); +void bvh_update(BVH * bvh, int moving); //////////////////////////////////////////////// @@ -199,6 +205,9 @@ void cloth_init ( ClothModifierData *clmd ); void cloth_deform_verts ( struct Object *ob, float framenr, float ( *vertexCos ) [3], int numVerts, void *derivedData, ClothModifierData *clmd ); void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int totface ); +// needed for collision.c +void bvh_update_from_cloth(ClothModifierData *clmd, int moving); + //////////////////////////////////////////////// diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h index e38662fdf95..f0f6212d3f5 100644 --- a/source/blender/blenkernel/BKE_collisions.h +++ b/source/blender/blenkernel/BKE_collisions.h @@ -79,6 +79,7 @@ typedef struct BVH } BVH; + /* used for collisions in kdop.c and also collision.c*/ typedef struct CollisionPair { diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index fef932174a1..c68fb983fc9 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -160,6 +160,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms.maxspringlen = 10; clmd->sim_parms.firstframe = 1; clmd->sim_parms.lastframe = 250; + clmd->sim_parms.vgroup_mass = 0; clmd->coll_parms.self_friction = 5.0; clmd->coll_parms.friction = 10.0; clmd->coll_parms.loop_count = 1; @@ -175,13 +176,91 @@ void cloth_init ( ClothModifierData *clmd ) // also from softbodies clmd->sim_parms.maxgoal = 1.0f; clmd->sim_parms.mingoal = 0.0f; - clmd->sim_parms.defgoal = 0.7f; + clmd->sim_parms.defgoal = 0.0f; clmd->sim_parms.goalspring = 100.0f; clmd->sim_parms.goalfrict = 0.0f; clmd->sim_parms.cache = NULL; } + +BVH *bvh_build_from_cloth (ClothModifierData *clmd, float epsilon) +{ + unsigned int i = 0; + BVH *bvh=NULL; + Cloth *cloth = clmd->clothObject; + ClothVertex *verts = NULL; + + if(!clmd) + return NULL; + + cloth = clmd->clothObject; + + if(!cloth) + return NULL; + + verts = cloth->verts; + + bvh = MEM_callocN(sizeof(BVH), "BVH"); + if (bvh == NULL) + { + printf("bvh: Out of memory.\n"); + return NULL; + } + + // springs = cloth->springs; + // numsprings = cloth->numsprings; + + bvh->flags = 0; + bvh->leaf_tree = NULL; + bvh->leaf_root = NULL; + bvh->tree = NULL; + + bvh->epsilon = epsilon; + bvh->numfaces = cloth->numfaces; + bvh->mfaces = cloth->mfaces; + + bvh->numverts = cloth->numverts; + + bvh->current_x = MEM_callocN ( sizeof ( MVert ) * bvh->numverts, "bvh->current_x" ); + bvh->current_xold = MEM_callocN ( sizeof ( MVert ) * bvh->numverts, "bvh->current_xold" ); + + for(i = 0; i < bvh->numverts; i++) + { + VECCOPY(bvh->current_x[i].co, verts[i].tx); + VECCOPY(bvh->current_xold[i].co, verts[i].txold); + } + + bvh_build (bvh); + + return bvh; +} + +void bvh_update_from_cloth(ClothModifierData *clmd, int moving) +{ + unsigned int i = 0; + Cloth *cloth = clmd->clothObject; + BVH *bvh = cloth->tree; + ClothVertex *verts = cloth->verts; + + if(!bvh) + return; + + if(cloth->numverts!=bvh->numverts) + return; + + if(cloth->verts) + { + for(i = 0; i < bvh->numverts; i++) + { + VECCOPY(bvh->current_x[i].co, verts[i].tx); + VECCOPY(bvh->current_xold[i].co, verts[i].txold); + } + } + + bvh_update(bvh, moving); +} + // unused in the moment, cloth needs quads from mesh DerivedMesh *CDDM_convert_to_triangle ( DerivedMesh *dm ) { @@ -433,9 +512,9 @@ static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr for(a = 0; a < cloth->numverts; a++) { - fwrite(&cloth->verts[a].x, sizeof(float),4,fp); - fwrite(&cloth->verts[a].xconst, sizeof(float),4,fp); - fwrite(&cloth->verts[a].v, sizeof(float),4,fp); + fwrite(&cloth->verts[a].x, sizeof(float),3,fp); + fwrite(&cloth->verts[a].xconst, sizeof(float),3,fp); + fwrite(&cloth->verts[a].v, sizeof(float),3,fp); } fclose(fp); @@ -458,17 +537,17 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) else { for(a = 0; a < cloth->numverts; a++) { - if(fread(&cloth->verts[a].x, sizeof(float), 4, fp) != 4) + if(fread(&cloth->verts[a].x, sizeof(float), 3, fp) != 3) { ret = 0; break; } - if(fread(&cloth->verts[a].xconst, sizeof(float), 4, fp) != 4) + if(fread(&cloth->verts[a].xconst, sizeof(float), 3, fp) != 3) { ret = 0; break; } - if(fread(&cloth->verts[a].v, sizeof(float), 4, fp) != 4) + if(fread(&cloth->verts[a].v, sizeof(float), 3, fp) != 3) { ret = 0; break; @@ -656,7 +735,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, solvers [clmd->sim_parms.solver_type].solver ( ob, framenr, clmd, effectors ); tend(); - printf ( "Cloth simulation time: %f\n", ( float ) tval() ); + // printf ( "Cloth simulation time: %f\n", ( float ) tval() ); cloth_write_cache(ob, clmd, framenr); @@ -830,7 +909,13 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short { verts->goal = dvert->dw [j].weight; - goalfac= ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal ); + goalfac= 1.0f; + + /* + // Kicking goal factor to simplify things...who uses that anyway? + // ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal ); + */ + verts->goal = ( float ) pow ( verts->goal , 4.0f ); if ( dvert->dw [j].weight >=SOFTGOALSNAP ) @@ -905,7 +990,7 @@ static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMes verts->impulse_count = 0; VECCOPY ( verts->impulse, tnull ); } - clmd->clothObject->tree = bvh_build ( clmd,clmd->coll_parms.epsilon ); + clmd->clothObject->tree = bvh_build_from_cloth ( clmd,clmd->coll_parms.epsilon ); } @@ -1012,7 +1097,7 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh if ( solvers [clmd->sim_parms.solver_type].init ) solvers [clmd->sim_parms.solver_type].init ( ob, clmd ); - clmd->clothObject->tree = bvh_build ( clmd, clmd->coll_parms.epsilon ); + clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms.epsilon ); cloth_write_cache(ob, clmd, framenr-1); } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 4a03f579fe8..4ab436b2936 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -70,7 +70,72 @@ #include "Bullet-C-Api.h" +// step is limited from 0 (frame start position) to 1 (frame end position) +void collision_move_object(CollisionModifierData *collmd, float step, float prevstep) +{ + float tv[3] = {0,0,0}; + unsigned int i = 0; + + for ( i = 0; i < collmd->numverts; i++ ) + { + VECSUB(tv, collmd->xnew[i].co, collmd->x[i].co); + VECADDS(collmd->current_x[i].co, collmd->x[i].co, tv, prevstep); + VECADDS(collmd->current_xnew[i].co, collmd->x[i].co, tv, step); + VECSUB(collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co); + } +} +BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon) +{ + BVH *bvh=NULL; + + bvh = MEM_callocN(sizeof(BVH), "BVH"); + if (bvh == NULL) + { + printf("bvh: Out of memory.\n"); + return NULL; + } + + bvh->flags = 0; + bvh->leaf_tree = NULL; + bvh->leaf_root = NULL; + bvh->tree = NULL; + + bvh->epsilon = epsilon; + bvh->numfaces = numfaces; + bvh->mfaces = mfaces; + + // we have no faces, we save seperate points + if(!mfaces) + { + bvh->numfaces = numverts; + } + + bvh->numverts = numverts; + bvh->current_x = MEM_dupallocN(x); + bvh->current_xold = MEM_dupallocN(x); + + bvh_build(bvh); + + return bvh; +} + +void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving) +{ + if(!bvh) + return; + + if(numverts!=bvh->numverts) + return; + + if(x) + memcpy(bvh->current_xold, x, sizeof(MVert) * numverts); + + if(xnew) + memcpy(bvh->current_x, xnew, sizeof(MVert) * numverts); + + bvh_update(bvh, moving); +} /** * gsl_poly_solve_cubic - @@ -519,7 +584,7 @@ int cloth_collision_response_moving_edges(ClothModifierData *clmd, ClothModifier } -void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) { CollPair *collpair = NULL; Cloth *cloth1=NULL, *cloth2=NULL; @@ -667,7 +732,7 @@ int cloth_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_cl return 0; } -void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) { EdgeCollPair edgecollpair; Cloth *cloth1=NULL, *cloth2=NULL; @@ -802,7 +867,7 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co } } -void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) { CollPair collpair; Cloth *cloth1=NULL, *cloth2=NULL; @@ -896,7 +961,7 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col } } -void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) { // TODO: check for adjacent cloth_collision_moving_edges(clmd, coll_clmd, tree1, tree2); @@ -943,7 +1008,7 @@ void cloth_update_collision_objects(float step) } // update BVH of collision object - bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING + bvh_update_from_cloth(coll_clmd, 0); // 0 means STATIC, 1 means MOVING } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); @@ -972,6 +1037,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { return 0; } + cloth = clmd->clothObject; verts = cloth->verts; cloth_bvh = (BVH *) cloth->tree; @@ -983,7 +1049,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) //////////////////////////////////////////////////////////// // update cloth bvh - bvh_update(clmd, cloth_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function) + bvh_update_from_cloth(clmd, 0); // 0 means STATIC, 1 means MOVING (see later in this function) // update collision objects cloth_update_collision_objects(step); @@ -1075,12 +1141,12 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) clmd->coll_parms.collision_list = NULL; } - printf("ic: %d\n", ic); + // printf("ic: %d\n", ic); rounds++; } while(result && (CLOTH_MAX_THRESHOLD>rounds)); - printf("\n"); + // printf("\n"); //////////////////////////////////////////////////////////// // update positions @@ -1100,7 +1166,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) // update cloth bvh - bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING + bvh_update_from_cloth(clmd, 1); // 0 means STATIC, 1 means MOVING // update moving bvh for collision object once for (base = G.scene->base.first; base; base = base->next) @@ -1119,7 +1185,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { BVH *coll_bvh = coll_clmd->clothObject->tree; - bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING + bvh_update_from_cloth(coll_clmd, 1); // 0 means STATIC, 1 means MOVING } } @@ -1204,7 +1270,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) } // update cloth bvh - bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING + bvh_update_from_cloth(clmd, 1); // 0 means STATIC, 1 means MOVING // free collision list @@ -1223,7 +1289,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) clmd->coll_parms.collision_list = NULL; } - printf("ic: %d\n", ic); + // printf("ic: %d\n", ic); rounds++; } while(result && (CLOTH_MAX_THRESHOLD>rounds)); diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index 74b5b3d7b7f..ed1da4d19f9 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -1,4 +1,4 @@ -/* collision.c +/* kdop.c * * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** @@ -38,6 +38,7 @@ #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" @@ -58,7 +59,7 @@ #include "BKE_key.h" #include "BKE_mesh.h" #include "BKE_object.h" -#include "BKE_collisions.h" +#include "BKE_cloth.h" #include "BKE_modifier.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" @@ -164,13 +165,13 @@ static int size_threshold = 16; /* * Common methods for all algorithms */ -void bvh_exchange(CollisionTree **a, int i, int j) +DO_INLINE void bvh_exchange(CollisionTree **a, int i, int j) { CollisionTree *t=a[i]; a[i]=a[j]; a[j]=t; } -int floor_lg(int a) +DO_INLINE int floor_lg(int a) { return (int)(floor(log(a)/log(2))); } @@ -195,7 +196,7 @@ static void bvh_insertionsort(CollisionTree **a, int lo, int hi, int axis) } } -static int bvh_partition(CollisionTree **a, int lo, int hi, CollisionTree *x, int axis) +static int bvh_partition(CollisionTree **a, int lo, int hi, CollisionTree * x, int axis) { int i=lo, j=hi; while (1) @@ -215,7 +216,7 @@ static int bvh_partition(CollisionTree **a, int lo, int hi, CollisionTree *x, in */ static void bvh_downheap(CollisionTree **a, int i, int n, int lo, int axis) { - CollisionTree *d = a[lo+i-1]; + CollisionTree * d = a[lo+i-1]; int child; while (i<=n/2) { @@ -293,7 +294,7 @@ static void bvh_introsort_loop (CollisionTree **a, int lo, int hi, int depth_lim } } -void bvh_sort(CollisionTree **a0, int begin, int end, int axis) +DO_INLINE void bvh_sort(CollisionTree **a0, int begin, int end, int axis) { if (begin < end) { @@ -302,7 +303,7 @@ void bvh_sort(CollisionTree **a0, int begin, int end, int axis) bvh_insertionsort(a, begin, end, axis); } } -void bvh_sort_along_axis(CollisionTree **face_list, int start, int end, int axis) +DO_INLINE void bvh_sort_along_axis(CollisionTree **face_list, int start, int end, int axis) { bvh_sort(face_list, start, end, axis); } @@ -330,11 +331,11 @@ void bvh_free(BVH * bvh) BLI_linklist_free(bvh->tree,NULL); bvh->tree = NULL; - if(bvh->x) - MEM_freeN(bvh->x); - if(bvh->xnew) - MEM_freeN(bvh->xnew); - + if(bvh->current_x) + MEM_freeN(bvh->current_x); + if(bvh->current_xold) + MEM_freeN(bvh->current_xold); + MEM_freeN(bvh); bvh = NULL; } @@ -342,7 +343,7 @@ void bvh_free(BVH * bvh) // only supports x,y,z axis in the moment // but we should use a plain and simple function here for speed sake -int bvh_largest_axis(float *bv) +DO_INLINE int bvh_largest_axis(float *bv) { float middle_point[3]; @@ -366,7 +367,7 @@ int bvh_largest_axis(float *bv) } // depends on the fact that the BVH's for each face is already build -void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces, float *bv) +DO_INLINE void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces, float *bv) { float newmin,newmax; int i, j; @@ -390,62 +391,35 @@ void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces, } } -void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv) +DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv) { - MVert *tempMVert = bvh->x; - float *tempBV = bv; - float newminmax; - int i, j, k; - for (j = 0; j < numfaces; j++) - { - // 1 up to 4 vertices per leaf. - for (k = 0; k < 4; k++) - { - int temp = tri[j]->point_index[k]; - - if(temp < 0) - continue; - - // for all Axes. - for (i = KDOP_START; i < KDOP_END; i++) - { - newminmax = INPR(tempMVert[temp].co, KDOP_AXES[i]); - if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0)) - tempBV[(2 * i)] = newminmax; - if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0)) - tempBV[(2 * i) + 1] = newminmax; - } - } - } -} - -void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv) -{ - MVert *tempMVert = bvh->x; - MVert *tempMVert2 = bvh->xnew; + 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 = tri[j]->point_index[k]; - - if(temp < 0) + 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(tempMVert[temp].co, KDOP_AXES[i]); - if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0)) - tempBV[(2 * i)] = newminmax; - if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0)) - tempBV[(2 * i) + 1] = newminmax; - - newminmax = INPR(tempMVert2[temp].co, KDOP_AXES[i]); + 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)) @@ -455,7 +429,51 @@ void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, floa } } -static void bvh_div_env_node(BVH * bvh, TreeNode *tree, CollisionTree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink) +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; @@ -523,17 +541,26 @@ static void bvh_div_env_node(BVH * bvh, TreeNode *tree, CollisionTree **face_lis return; } -// mfaces is allowed to be null -// just vertexes are used if mfaces=NULL -BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces) +/* function cannot be directly called - needs alloced bvh */ +void bvh_build (BVH *bvh) { - unsigned int i = 0, j = 0; + 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; @@ -541,25 +568,7 @@ BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces) if(bvh->numfaces<=1) { - // Why that? --> only one face there - if(bvh->mfaces) - { - bvh->root->point_index[0] = mfaces[0].v1; - bvh->root->point_index[1] = mfaces[0].v2; - bvh->root->point_index[2] = mfaces[0].v3; - if(mfaces[0].v4) - bvh->root->point_index[3] = mfaces[0].v4; - else - bvh->root->point_index[3] = -1; - } - else - { - bvh->root->point_index[0] = 0; - bvh->root->point_index[1] = -1; - bvh->root->point_index[2] = -1; - bvh->root->point_index[3] = -1; - } - + bvh->root->tri_index = 0; // Why that? --> only one face there bvh->root->isleaf = 1; bvh->root->traversed = 0; bvh->root->count_nodes = 0; @@ -569,46 +578,28 @@ BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces) bvh->root->prevLeaf = NULL; } else - { + { // create face boxes face_list = MEM_callocN (bvh->numfaces * sizeof (CollisionTree *), "CollisionTree"); if (face_list == NULL) { printf("bvh_build: Out of memory for face_list.\n"); bvh_free(bvh); - return NULL; + return; } // create face boxes - for(i = 0; i < bvh->numfaces; i++) + for(i = 0, k = 0; i < bvh->numfaces; i++) { - LinkNode *tnlink = NULL; - + 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; - - if(bvh->mfaces) - { - tree->point_index[0] = mfaces[i].v1; - tree->point_index[1] = mfaces[i].v2; - tree->point_index[2] = mfaces[i].v3; - if(mfaces[i].v4) - tree->point_index[3] = mfaces[i].v4; - else - tree->point_index[3] = -1; - } - else - { - tree->point_index[0] = i; - tree->point_index[1] = -1; - tree->point_index[2] = -1; - tree->point_index[3] = -1; - } - + tree->tri_index = i; tree->isleaf = 1; tree->nextLeaf = NULL; tree->prevLeaf = bvh->leaf_tree; @@ -641,170 +632,18 @@ BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces) // build root bvh bvh_calc_DOP_hull_from_faces(bvh, face_list, bvh->numfaces, bvh->root->bv); - + // This is the traversal function. bvh_div_env_node(bvh, bvh->root, face_list, 0, bvh->numfaces-1, 0, nlink); if (face_list) MEM_freeN(face_list); - // BLI_edgehash_free(edgehash, NULL); } - - return bvh; -} - -BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon) -{ - BVH *bvh=NULL; - CollisionTree *tree=NULL; - - bvh = MEM_callocN(sizeof(BVH), "BVH"); - if (bvh == NULL) - { - printf("bvh: Out of memory.\n"); - return NULL; - } - - bvh->flags = 0; - bvh->leaf_tree = NULL; - bvh->leaf_root = NULL; - bvh->tree = NULL; - - bvh->epsilon = epsilon; - bvh->numfaces = numfaces; - bvh->mfaces = mfaces; - - // we have no faces, we save seperate points - if(!mfaces) - { - bvh->numfaces = numverts; - } - - bvh->numverts = numverts; - bvh->xnew = MEM_dupallocN(x); - bvh->x = MEM_dupallocN(x); - tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree"); - - if (tree == NULL) - { - printf("bvh_build: Out of memory for nodes.\n"); - bvh_free(bvh); - return NULL; - } - - BLI_linklist_append(&bvh->tree, tree); - - return bvh_build(bvh, mfaces, numfaces); -} - - -BVH *bvh_build_from_float3 (MFace *mfaces, unsigned int numfaces, float (*x)[3], unsigned int numverts, float epsilon) -{ - BVH *bvh=NULL; - CollisionTree *tree=NULL; - unsigned int i = 0; - - bvh = MEM_callocN(sizeof(BVH), "BVH"); - if (bvh == NULL) - { - printf("bvh: Out of memory.\n"); - return NULL; - } - - bvh->flags = 0; - bvh->leaf_tree = NULL; - bvh->leaf_root = NULL; - bvh->tree = NULL; - - bvh->epsilon = epsilon; - bvh->numfaces = numfaces; - bvh->mfaces = mfaces; - - // we have no faces, we save seperate points - if(!mfaces) - { - bvh->numfaces = numverts; - } - - bvh->numverts = numverts; - bvh->xnew = (MVert *)MEM_callocN(sizeof(MVert)*numverts, "BVH MVert"); - - for(i = 0; i < numverts; i++) - { - VECCOPY(bvh->xnew[i].co, x[i]); - } - - bvh->x = MEM_dupallocN(bvh->xnew); - - tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree"); - - if (tree == NULL) - { - printf("bvh_build: Out of memory for nodes.\n"); - bvh_free(bvh); - return NULL; - } - - BLI_linklist_append(&bvh->tree, tree); - - return bvh_build(bvh, mfaces, numfaces); -} - -BVH *bvh_build_from_float4 (MFace *mfaces, unsigned int numfaces, float (*x)[4], unsigned int numverts, float epsilon) -{ - BVH *bvh=NULL; - CollisionTree *tree=NULL; - unsigned int i = 0; - - bvh = MEM_callocN(sizeof(BVH), "BVH"); - if (bvh == NULL) - { - printf("bvh: Out of memory.\n"); - return NULL; - } - - bvh->flags = 0; - bvh->leaf_tree = NULL; - bvh->leaf_root = NULL; - bvh->tree = NULL; - - bvh->epsilon = epsilon; - bvh->numfaces = numfaces; - bvh->mfaces = mfaces; - - // we have no faces, we save seperate points - if(!mfaces) - { - bvh->numfaces = numverts; - } - - bvh->numverts = numverts; - bvh->xnew = (MVert *)MEM_callocN(sizeof(MVert)*numverts, "BVH MVert"); - - for(i = 0; i < numverts; i++) - { - VECCOPY(bvh->xnew[i].co, x[i]); - } - - bvh->x = MEM_dupallocN(bvh->xnew); - - tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree"); - - if (tree == NULL) - { - printf("bvh_build: Out of memory for nodes.\n"); - bvh_free(bvh); - return NULL; - } - - BLI_linklist_append(&bvh->tree, tree); - - return bvh_build(bvh, mfaces, numfaces); } // bvh_overlap - is it possbile for 2 bv's to collide ? -int bvh_overlap(float *bv1, float *bv2) +DO_INLINE int bvh_overlap(float *bv1, float *bv2) { int i = 0; for (i = KDOP_START; i < KDOP_END; i++) @@ -823,6 +662,7 @@ int bvh_overlap(float *bv1, float *bv2) return 1; } + /** * bvh_traverse - traverse two bvh trees looking for potential collisions. * @@ -830,9 +670,18 @@ int bvh_overlap(float *bv1, float *bv2) * every other triangle that doesn't require any realloc, but uses * much memory */ -int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collision_list) +int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response) { - int i = 0, ret = 0; + 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 @@ -841,85 +690,11 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio // Check if this node in the second tree a leaf if (tree2->isleaf) { - ////////////////////////////////// - // TODO: check for 3rd point if zero (triangle)!!! - ////////////////////////////////// + // Provide the collision response. - CollisionPair *collpair = NULL; - - if(tree1 != tree2) // do not collide same points - { - //////////////////////////////////////// - // FIRST FACE - //////////////////////////////////////// - - // save potential colliding triangles - collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); - - VECCOPY(collpair->point_indexA, tree1->point_index); - VECCOPY(collpair->point_indexB, tree2->point_index); - - // we use prepend because lots of insertions at end - // of list are horrible slow! - BLI_linklist_prepend(&collision_list[0], collpair); - - //////////////////////////////////////// - // SECOND FACE - //////////////////////////////////////// - if(tree1->point_index[3]) // check for quad face - { - // save potential colliding triangles - collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); - - VECCOPY(collpair->point_indexA, tree1->point_index); - collpair->point_indexA[2] = tree1->point_index[3]; - - VECCOPY(collpair->point_indexB, tree2->point_index); - - // we use prepend because lots of insertions at end - // of list are horrible slow! - BLI_linklist_prepend(&collision_list[0], collpair); - } - //////////////////////////////////////// - // THIRD FACE - //////////////////////////////////////// - if(tree2->point_index[3]) // check for quad face - { - // save potential colliding triangles - collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); - - VECCOPY(collpair->point_indexA, tree1->point_index); - - VECCOPY(collpair->point_indexB, tree2->point_index); - collpair->point_indexB[2] = tree2->point_index[3]; - - // we use prepend because lots of insertions at end - // of list are horrible slow! - BLI_linklist_prepend(&collision_list[0], collpair); - } - //////////////////////////////////////// - // FOURTH FACE - //////////////////////////////////////// - if(tree1->point_index[3] && tree1->point_index[3]) // check for quad face - { - // save potential colliding triangles - collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair"); - - VECCOPY(collpair->point_indexA, tree1->point_index); - collpair->point_indexA[2] = tree1->point_index[3]; - - VECCOPY(collpair->point_indexB, tree2->point_index); - collpair->point_indexB[2] = tree2->point_index[3]; - - // we use prepend because lots of insertions at end - // of list are horrible slow! - BLI_linklist_prepend(&collision_list[0], collpair); - } - - return 1; - } - else - return 0; + if(collision_response) + collision_response (clmd, coll_clmd, tree1, tree2); + return 1; } else { @@ -927,7 +702,7 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree2->nodes[i] && (bvh_traverse (tree1, tree2->nodes[i], collision_list))) + if (tree2->nodes[i] && bvh_traverse (clmd, coll_clmd, tree1, tree2->nodes[i], step, collision_response)) ret = 1; } } @@ -938,7 +713,7 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree1->nodes [i] && (bvh_traverse (tree1->nodes[i], tree2, collision_list))) + if (tree1->nodes [i] && bvh_traverse (clmd, coll_clmd, tree1->nodes[i], tree2, step, collision_response)) ret = 1; } } @@ -949,7 +724,7 @@ int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode **collisio // bottom up update of bvh tree: // join the 4 children here -void bvh_join(CollisionTree *tree) +void bvh_join(CollisionTree * tree) { int i = 0, j = 0; if (!tree) @@ -979,10 +754,10 @@ void bvh_join(CollisionTree *tree) } // update static bvh -// needs new positions in bvh->x, bvh->xnew +/* you have to update the bvh position before calling this function */ void bvh_update(BVH * bvh, int moving) { - TreeNode *leaf, *parent; + CollisionTree *leaf, *parent; int traversecheck = 1; // if this is zero we don't go further unsigned int j = 0; @@ -993,7 +768,6 @@ void bvh_update(BVH * bvh, int moving) { leaf->parent->traversed = 0; } - if(!moving) bvh_calc_DOP_hull_static(bvh, &leaf, 1, leaf->bv); else @@ -1034,70 +808,3 @@ void bvh_update(BVH * bvh, int moving) } } -void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving) -{ - if(!bvh) - return; - - if(numverts!=bvh->numverts) - return; - - if(x) - memcpy(bvh->x, x, sizeof(MVert) * numverts); - - if(xnew) - memcpy(bvh->xnew, xnew, sizeof(MVert) * numverts); - - bvh_update(bvh, moving); -} - -void bvh_update_from_float3(BVH * bvh, float (*x)[3], unsigned int numverts, float (*xnew)[3], int moving) -{ - unsigned int i = 0; - - if(!bvh) - return; - - if(numverts!=bvh->numverts) - return; - - if(x) - { - for(i = 0; i < numverts; i++) - VECCOPY(bvh->x[i].co, x[i]); - } - - if(xnew) - { - for(i = 0; i < numverts; i++) - VECCOPY(bvh->xnew[i].co, xnew[i]); - } - - bvh_update(bvh, moving); -} - -void bvh_update_from_float4(BVH * bvh, float (*x)[4], unsigned int numverts, float (*xnew)[4], int moving) -{ - unsigned int i = 0; - - if(!bvh) - return; - - if(numverts!=bvh->numverts) - return; - - if(x) - { - for(i = 0; i < numverts; i++) - VECCOPY(bvh->x[i].co, x[i]); - } - - if(xnew) - { - for(i = 0; i < numverts; i++) - VECCOPY(bvh->xnew[i].co, xnew[i]); - } - - bvh_update(bvh, moving); -} - diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 3b69f47b1f4..8fdfbb71dc9 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -75,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" @@ -5031,6 +5032,145 @@ static void clothModifier_freeData(ModifierData *md) } } +/* Collision */ + +static void collisionModifier_initData(ModifierData *md) +{ + CollisionModifierData *collmd = (CollisionModifierData*) md; + + collmd->x = NULL; + collmd->xnew = NULL; + collmd->current_x = NULL; + collmd->current_xnew = NULL; + collmd->current_v = NULL; + collmd->time = -1; + collmd->numverts = 0; + collmd->tree = NULL; +} + +static void collisionModifier_freeData(ModifierData *md) +{ + CollisionModifierData *collmd = (CollisionModifierData*) md; + + if (collmd) + { + if(collmd->tree) + bvh_free(collmd->tree); + if(collmd->x) + MEM_freeN(collmd->x); + if(collmd->xnew) + MEM_freeN(collmd->xnew); + if(collmd->current_x) + MEM_freeN(collmd->current_x); + if(collmd->current_xnew) + MEM_freeN(collmd->current_xnew); + if(collmd->current_v) + MEM_freeN(collmd->current_v); + + collmd->x = NULL; + collmd->xnew = NULL; + collmd->current_x = NULL; + collmd->current_xnew = NULL; + collmd->current_v = NULL; + collmd->time = -1; + collmd->numverts = 0; + collmd->tree = NULL; + } +} + +static int collisionModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + +static void collisionModifier_deformVerts( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) +{ + CollisionModifierData *collmd = (CollisionModifierData*) md; + DerivedMesh *dm = NULL; + float current_time = 0; + unsigned int numverts = 0, i = 0; + MVert *tempVert = NULL; + + // if possible use/create DerivedMesh + + if(derivedData) dm = CDDM_copy(derivedData); + else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); + + if(!ob->pd) + { + printf("collisionModifier_deformVerts: Should not happen!\n"); + return; + } + + if(dm) + { + CDDM_apply_vert_coords(dm, vertexCos); + CDDM_calc_normals(dm); + + + current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); + + if(current_time > collmd->time) + { + numverts = dm->getNumVerts ( dm ); + + // check if mesh has changed + if(collmd->x && (numverts != collmd->numverts)) + collisionModifier_freeData((ModifierData *)collmd); + + if(collmd->time == -1) // first time + { + collmd->x = dm->dupVertArray(dm); // frame start position + + for ( i = 0; i < numverts; i++ ) + { + // we save global positions + Mat4MulVecfl ( ob->obmat, collmd->x[i].co ); + } + + collmd->xnew = MEM_dupallocN(collmd->x); // frame end position + collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame + collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame + collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame + + collmd->numverts = numverts; + + // TODO: epsilon + // create bounding box hierarchy + collmd->tree = bvh_build_from_mvert(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->current_x, numverts, ob->pd->pdef_sbift); + } + else if(numverts == collmd->numverts) + { + // put positions to old positions + tempVert = collmd->x; + collmd->x = collmd->xnew; + collmd->xnew = tempVert; + + memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); + + for ( i = 0; i < numverts; i++ ) + { + // we save global positions + Mat4MulVecfl ( ob->obmat, collmd->xnew[i].co ); + } + + memcpy(collmd->current_xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); + memcpy(collmd->current_x, dm->getVertArray(dm), numverts*sizeof(MVert)); + + // recalc static bounding boxes + bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0); + } + + collmd->time = current_time; + } + } + + if(dm) + dm->release(dm); +} + /* Boolean */ static void booleanModifier_copyData(ModifierData *md, ModifierData *target) @@ -6855,6 +6995,16 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) // mti->copyData = clothModifier_copyData; mti->deformVerts = clothModifier_deformVerts; mti->updateDepgraph = clothModifier_updateDepgraph; + + mti = INIT_TYPE(Collision); + mti->type = eModifierTypeType_OnlyDeform; + mti->initData = collisionModifier_initData; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_RequiresOriginalData; + mti->dependsOnTime = collisionModifier_dependsOnTime; + mti->freeData = collisionModifier_freeData; + mti->deformVerts = collisionModifier_deformVerts; + // mti->copyData = collisionModifier_copyData; mti = INIT_TYPE(Boolean); mti->type = eModifierTypeType_Nonconstructive; diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 2bbe328d170..ce942f5bbb0 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -106,7 +106,7 @@ typedef struct SimulationSettings float bending; /* Flexion spring stiffness. */ float sim_time; int flags; /* flags, see CSIMSETT_FLAGS enum above. */ - short solver_type; /* which solver should be used? */ + short solver_type; /* which solver should be used? txold */ short pad2; float maxgoal; /* see SB */ float eff_force_scale;/* Scaling of effector forces (see softbody_calc_forces).*/ diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 581ff63a987..abc45e70183 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3184,7 +3184,7 @@ static void object_panel_deflection(Object *ob) PartDeflect *pd= ob->pd; 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); + 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, ""); @@ -4928,7 +4928,7 @@ static void object_panel_cloth(Object *ob) Cloth *cloth = clmd->clothObject; int defCount; char *clvg1, *clvg2; - char clmvg [] = "Mass Vertex Group%t|None%x0|"; + char clmvg [] = "Weight Paint Groups%t|"; val2=0; @@ -4938,12 +4938,12 @@ static void object_panel_cloth(Object *ob) uiClearButLock(); uiBlockBeginAlign(block); uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility"); - uiDefButI(block, NUM, B_CLOTH_RENEW, "Steps per Frame:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); + 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, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); uiBlockEndAlign(block); uiBlockBeginAlign(block); uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Spring damping"); - uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms.Cvi, 0.0, 10.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_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"); uiBlockEndAlign(block); uiClearButLock(); @@ -4959,7 +4959,7 @@ static void object_panel_cloth(Object *ob) /* GOAL STUFF */ uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Use Goal", 10,70,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "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) { if(ob->type==OB_MESH) @@ -4977,26 +4977,15 @@ static void object_panel_cloth(Object *ob) { clmd->sim_parms.vgroup_mass = 0; } + else + if(!clmd->sim_parms.vgroup_mass) + clmd->sim_parms.vgroup_mass = 1; + sprintf (clvg2, "%s%s", clmvg, clvg1); - uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups"); + uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 160,70,150,20, &clmd->sim_parms.vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups"); MEM_freeN (clvg1); MEM_freeN (clvg2); - - if(clmd->sim_parms.vgroup_mass) - { - bDeformGroup *defGroup = BLI_findlink(&ob->defbase, clmd->sim_parms.vgroup_mass-1); - if(defGroup) - uiDefBut(block, BUT, B_DIFF, defGroup->name, 160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group"); - else - uiDefBut(block, BUT, B_DIFF, "(no group)", 160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Vertex Group doesn't exist anymore"); - - uiDefIconBut(block, BUT, B_CLOTH_DEL_VG, ICON_X, 290,70,20,20, 0, 0, 0, 0, 0, "Disable use of vertex group"); - - } - else - uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); - } else { @@ -5004,10 +4993,13 @@ static void object_panel_cloth(Object *ob) uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); } - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Pin Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Pin (vertex target position) spring stiffness"); + /* + // 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"); + */ } uiBlockEndAlign(block); From 3759c772fdafa008965e702098edeb8a2cae373b Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 21 Jan 2008 10:55:46 +0000 Subject: [PATCH 072/101] Speedup spring creation again, was lost during merge --- source/blender/blenkernel/intern/cloth.c | 60 +++++++++++++----------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index c68fb983fc9..3fa99279435 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -1160,6 +1160,7 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh * ***************************************************************************************/ // be carefull: implicit solver has to be resettet when using this one! +// --> only for implicit handling of this spring! int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type) { Cloth *cloth = clmd->clothObject; @@ -1190,7 +1191,7 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) { ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0; - unsigned int i = 0; + unsigned int i = 0, j = 0, akku_count; unsigned int numverts = dm->getNumVerts ( dm ); unsigned int numedges = dm->getNumEdges ( dm ); unsigned int numfaces = dm->getNumFaces ( dm ); @@ -1200,9 +1201,9 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) LinkNode **edgelist = NULL; EdgeHash *edgehash = NULL; LinkNode *search = NULL, *search2 = NULL; - float temp[3]; - ClothVertex *verts = NULL; - + float temp[3], akku, min, max; + LinkNode *node = NULL, *node2 = NULL; + // error handling if ( numedges==0 ) return 0; @@ -1217,8 +1218,6 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) if ( cloth->springs ) MEM_freeN ( cloth->springs ); - - verts = cloth->verts; // create spring network hash edgehash = BLI_edgehash_new(); @@ -1232,16 +1231,20 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) { spring->ij = medge[i].v1; spring->kl = medge[i].v2; - VECSUB ( temp, verts[spring->kl].x, verts[spring->ij].x ); + VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; spring->flags = 0; struct_springs++; - - BLI_linklist_append ( &cloth->springs, spring ); + + if(!i) + node2 = BLI_linklist_append_fast ( &cloth->springs, spring ); + else + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; } } - + // shear springs for ( i = 0; i < numfaces; i++ ) { @@ -1249,7 +1252,7 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) spring->ij = mface[i].v1; spring->kl = mface[i].v3; - VECSUB ( temp, verts[spring->kl].x, verts[spring->ij].x ); + VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_SHEAR; @@ -1257,7 +1260,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) BLI_linklist_append ( &edgelist[spring->kl], spring ); shear_springs++; - BLI_linklist_append ( &cloth->springs, spring ); + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; if ( mface[i].v4 ) { @@ -1265,18 +1269,19 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) spring->ij = mface[i].v2; spring->kl = mface[i].v4; - VECSUB ( temp, verts[spring->kl].x, verts[spring->ij].x ); - spring->restlen = sqrt ( INPR ( temp, temp ) ); - spring->type = CLOTH_SPRING_TYPE_SHEAR; + VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); + spring->restlen = sqrt ( INPR ( temp, temp ) ); + spring->type = CLOTH_SPRING_TYPE_SHEAR; - BLI_linklist_append ( &edgelist[spring->ij], spring ); - BLI_linklist_append ( &edgelist[spring->kl], spring ); - shear_springs++; + BLI_linklist_append ( &edgelist[spring->ij], spring ); + BLI_linklist_append ( &edgelist[spring->kl], spring ); + shear_springs++; - BLI_linklist_append ( &cloth->springs, spring ); + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; } } - + // bending springs search2 = cloth->springs; for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) @@ -1294,35 +1299,36 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) // check for existing spring // check also if startpoint is equal to endpoint if ( !BLI_edgehash_haskey ( edgehash, index2, tspring2->ij ) - && !BLI_edgehash_haskey ( edgehash, tspring2->ij, index2 ) - && ( index2!=tspring2->ij ) ) + && !BLI_edgehash_haskey ( edgehash, tspring2->ij, index2 ) + && ( index2!=tspring2->ij ) ) { spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); spring->ij = tspring2->ij; spring->kl = index2; - VECSUB ( temp, verts[index2].x, verts[tspring2->ij].x ); + VECSUB ( temp, cloth->verts[index2].x, cloth->verts[tspring2->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_BENDING; BLI_edgehash_insert ( edgehash, spring->ij, index2, NULL ); bend_springs++; - BLI_linklist_append ( &cloth->springs, spring ); + node2 = BLI_linklist_append_fast ( &node->next, spring ); + node = node2; } search = search->next; } search2 = search2->next; } - + cloth->numsprings = struct_springs + shear_springs + bend_springs; - + for ( i = 0; i < numverts; i++ ) { BLI_linklist_free ( edgelist[i],NULL ); } if ( edgelist ) MEM_freeN ( edgelist ); - + BLI_edgehash_free ( edgehash, NULL ); return 1; From 3db5a4e8dc81fcc6663db267f24bc982dd201a18 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 22 Jan 2008 00:34:28 +0000 Subject: [PATCH 073/101] First successfull use of collision modifier. Means: Collision with cloth are enabled using the 'Deflection' panel from now on --- source/blender/blenkernel/BKE_cloth.h | 45 ++++- source/blender/blenkernel/intern/collision.c | 95 ++++++----- source/blender/blenkernel/intern/implicit.c | 3 +- source/blender/blenkernel/intern/kdop.c | 8 +- source/blender/blenkernel/intern/modifier.c | 15 +- source/blender/makesdna/DNA_cloth_types.h | 42 ----- source/blender/makesdna/DNA_modifier_types.h | 7 +- source/blender/src/buttons_object.c | 165 +++++++++---------- 8 files changed, 191 insertions(+), 189 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 592c34ad28e..6ad9893d072 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -61,6 +61,47 @@ struct ClothModifierData; #define CLOTH_MAX_THREAD 2 +/** + * Pin and unpin frames are the frames on which the vertices stop moving. + * They will assume the position they had prior to pinFrame until unpinFrame + * is reached. + */ +typedef struct ClothVertex +{ + int flags; /* General flags per vertex. */ + float v [3]; /* The velocity of the point. */ + float xconst [3]; /* constrained position */ + float x [3]; /* The current position of this vertex. */ + float xold [3]; /* The previous position of this vertex.*/ + float tx [3]; /* temporary position */ + float txold [3]; /* temporary old position */ + float tv[3]; /* temporary "velocity", mostly used as tv = tx-txold */ + float mass; /* mass / weight of the vertex */ + float goal; /* goal, from SB */ + float impulse[3]; /* used in collision.c */ + unsigned int impulse_count; /* same as above */ +} +ClothVertex; + + +/** + * The definition of a spring. + */ +typedef struct ClothSpring +{ + int ij; /* Pij from the paper, one end of the spring. */ + int kl; /* Pkl from the paper, one end of the spring. */ + float restlen; /* The original length of the spring. */ + int matrix_index; /* needed for implicit solver (fast lookup) */ + int type; /* types defined in BKE_cloth.h ("springType") */ + int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ + float dfdx[3][3]; + float dfdv[3][3]; + float f[3]; +} +ClothSpring; + + /* goal defines */ #define SOFTGOALSNAP 0.999f @@ -161,7 +202,7 @@ typedef struct BVH } BVH; -typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree * tree1, CollisionTree * tree2 ); +typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, CollisionModifierData *collmd, CollisionTree * tree1, CollisionTree * tree2 ); ///////////////////////////////////////////////// @@ -191,7 +232,7 @@ void bvh_build (BVH *bvh); LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr ); // needed for collision.c -int bvh_traverse ( ClothModifierData * clmd, ClothModifierData * coll_clmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response ); +int bvh_traverse ( ClothModifierData * clmd, CollisionModifierData * collmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response ); void bvh_update(BVH * bvh, int moving); //////////////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 4ab436b2936..c5e6c119e10 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -70,7 +70,11 @@ #include "Bullet-C-Api.h" -// step is limited from 0 (frame start position) to 1 (frame end position) +/*********************************** +Collision modifier code start +***********************************/ + +/* step is limited from 0 (frame start position) to 1 (frame end position) */ void collision_move_object(CollisionModifierData *collmd, float step, float prevstep) { float tv[3] = {0,0,0}; @@ -85,6 +89,7 @@ void collision_move_object(CollisionModifierData *collmd, float step, float prev } } +/* build bounding volume hierarchy from mverts (see kdop.c for whole BVH code) */ BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon) { BVH *bvh=NULL; @@ -137,6 +142,10 @@ void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xn bvh_update(bvh, moving); } +/*********************************** +Collision modifier code end +***********************************/ + /** * gsl_poly_solve_cubic - * @@ -437,19 +446,18 @@ DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal VecMulf(to, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); } -int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) +int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierData *collmd) { unsigned int i = 0; int result = 0; LinkNode *search = NULL; CollPair *collpair = NULL; - Cloth *cloth1, *cloth2; + Cloth *cloth1; float w1, w2, w3, u1, u2, u3; float v1[3], v2[3], relativeVelocity[3]; float magrelVel; cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; search = clmd->coll_parms.collision_list; @@ -463,17 +471,18 @@ int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData * cloth1->verts[collpair->ap2].txold, cloth1->verts[collpair->ap3].txold, &w1, &w2, &w3); - + + // was: txold cloth_compute_barycentric(collpair->pb, - cloth2->verts[collpair->bp1].txold, - cloth2->verts[collpair->bp2].txold, - cloth2->verts[collpair->bp3].txold, + collmd->current_x[collpair->bp1].co, + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, &u1, &u2, &u3); // Calculate relative "velocity". interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3); - interpolateOnTriangle(v2, cloth2->verts[collpair->bp1].tv, cloth2->verts[collpair->bp2].tv, cloth2->verts[collpair->bp3].tv, u1, u2, u3); + interpolateOnTriangle(v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3); VECSUB(relativeVelocity, v1, v2); @@ -575,21 +584,21 @@ int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData * int cloth_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) { - + return 1; } int cloth_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) { - + return 1; } -void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) +void cloth_collision_static(ClothModifierData *clmd, CollisionModifierData *collmd, CollisionTree *tree1, CollisionTree *tree2) { CollPair *collpair = NULL; - Cloth *cloth1=NULL, *cloth2=NULL; + Cloth *cloth1=NULL; MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; + ClothVertex *verts1=NULL; double distance = 0; float epsilon = clmd->coll_parms.epsilon; unsigned int i = 0; @@ -599,13 +608,11 @@ void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clm collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; verts1 = cloth1->verts; - verts2 = cloth2->verts; face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(cloth2->mfaces[tree2->tri_index]); + face2 = &(collmd->mfaces[tree2->tri_index]); // check all possible pairs of triangles if(i == 0) @@ -674,7 +681,7 @@ void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clm { // calc distance + normal distance = plNearestPoints( - verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, collpair->pa,collpair->pb,collpair->vector); + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector); if (distance <= (epsilon + ALMOST_ZERO)) { @@ -688,6 +695,7 @@ void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clm collpair->distance = distance; BLI_linklist_append(&clmd->coll_parms.collision_list, collpair); + } else { @@ -703,8 +711,8 @@ void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clm int cloth_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) { - Cloth *cloth1, *cloth2; - ClothVertex *verts1, *verts2; + Cloth *cloth1 = NULL, *cloth2 = NULL; + ClothVertex *verts1 = NULL, *verts2 = NULL; float temp[3]; cloth1 = clmd->clothObject; @@ -1023,7 +1031,7 @@ void cloth_update_collision_objects(float step) int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { Base *base=NULL; - ClothModifierData *coll_clmd=NULL; + CollisionModifierData *collmd=NULL; Cloth *cloth=NULL; Object *coll_ob=NULL; BVH *cloth_bvh=NULL; @@ -1064,23 +1072,21 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) for (base = G.scene->base.first; base; base = base->next) { coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + collmd = (CollisionModifierData *) modifiers_findByType (coll_ob, eModifierType_Collision); - if (!coll_clmd) + if (!collmd) continue; - // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + if (collmd->tree) { - if (coll_clmd->clothObject && coll_clmd->clothObject->tree) - { - BVH *coll_bvh = coll_clmd->clothObject->tree; + BVH *coll_bvh = collmd->tree; + + collision_move_object(collmd, step + dt, step); - bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static); - } - else - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + bvh_traverse(clmd, collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static); } + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); } // process all collisions (calculate impulses, TODO: also repulses if distance too short) @@ -1094,18 +1100,11 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - if (!coll_clmd) + collmd = (CollisionModifierData *) modifiers_findByType (coll_ob, eModifierType_Collision); + if (!collmd) continue; - // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) - { - if (coll_clmd->clothObject) - result += cloth_collision_response_static(clmd, coll_clmd); - else - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } + result += cloth_collision_response_static(clmd, collmd); } // apply impulses in parallel @@ -1140,14 +1139,10 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) clmd->coll_parms.collision_list = NULL; } - - // printf("ic: %d\n", ic); rounds++; } while(result && (CLOTH_MAX_THRESHOLD>rounds)); - // printf("\n"); - //////////////////////////////////////////////////////////// // update positions // this is needed for bvh_calc_DOP_hull_moving() [kdop.c] @@ -1162,9 +1157,11 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) //////////////////////////////////////////////////////////// // moving collisions + // + // response code is just missing itm //////////////////////////////////////////////////////////// - + /* // update cloth bvh bvh_update_from_cloth(clmd, 1); // 0 means STATIC, 1 means MOVING @@ -1294,7 +1291,6 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) } while(result && (CLOTH_MAX_THRESHOLD>rounds)); - //////////////////////////////////////////////////////////// // update positions + velocities //////////////////////////////////////////////////////////// @@ -1305,6 +1301,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) VECADD(verts[i].tx, verts[i].txold, verts[i].tv); } //////////////////////////////////////////////////////////// - + */ + return MIN2(ret, 1); } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index b154cb0e755..4985b3efa3f 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -850,6 +850,7 @@ DO_INLINE float fbstar(float length, float L, float kb, float cb) return tempfb; } +// function to calculae bending spring force (taken from Choi & Co) DO_INLINE float fbstar_jacobi(float length, float L, float kb, float cb) { float tempfb = kb * fb(length, L); @@ -1331,7 +1332,7 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto initdiag_bfmatrix(A, I); zero_lfvector(dV, numverts); - subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); + subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); mul_bfmatrix_lfvector(dFdXmV, dFdX, lV); diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c index ed1da4d19f9..736ffcf0965 100644 --- a/source/blender/blenkernel/intern/kdop.c +++ b/source/blender/blenkernel/intern/kdop.c @@ -670,7 +670,7 @@ DO_INLINE int bvh_overlap(float *bv1, float *bv2) * every other triangle that doesn't require any realloc, but uses * much memory */ -int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response) +int bvh_traverse ( ClothModifierData * clmd, CollisionModifierData * collmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response) { int i = 0, ret=0; @@ -693,7 +693,7 @@ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Collis // Provide the collision response. if(collision_response) - collision_response (clmd, coll_clmd, tree1, tree2); + collision_response (clmd, collmd, tree1, tree2); return 1; } else @@ -702,7 +702,7 @@ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Collis for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree2->nodes[i] && bvh_traverse (clmd, coll_clmd, tree1, tree2->nodes[i], step, collision_response)) + if (tree2->nodes[i] && bvh_traverse (clmd, collmd, tree1, tree2->nodes[i], step, collision_response)) ret = 1; } } @@ -713,7 +713,7 @@ int bvh_traverse(ClothModifierData * clmd, ClothModifierData * coll_clmd, Collis for (i = 0; i < 4; i++) { // Only traverse nodes that exist. - if (tree1->nodes [i] && bvh_traverse (clmd, coll_clmd, tree1->nodes[i], tree2, step, collision_response)) + if (tree1->nodes [i] && bvh_traverse (clmd, collmd, tree1->nodes[i], tree2, step, collision_response)) ret = 1; } } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index ed86e1ae17f..da31929442d 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5004,7 +5004,7 @@ static void clothModifier_updateDepgraph( CustomDataMask clothModifier_requiredDataMask(ModifierData *md) { - ClothModifierData *clmd = (HookModifierData *)md; + ClothModifierData *clmd = (ClothModifierData *)md; CustomDataMask dataMask = 0; /* ask for vertexgroups if we need them */ @@ -5067,6 +5067,9 @@ static void collisionModifier_freeData(ModifierData *md) 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; @@ -5075,6 +5078,7 @@ static void collisionModifier_freeData(ModifierData *md) collmd->time = -1; collmd->numverts = 0; collmd->tree = NULL; + collmd->mfaces = NULL; } } @@ -5139,7 +5143,10 @@ static void collisionModifier_deformVerts( // TODO: epsilon // create bounding box hierarchy - collmd->tree = bvh_build_from_mvert(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->current_x, numverts, ob->pd->pdef_sbift); + collmd->tree = bvh_build_from_mvert(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->x, numverts, ob->pd->pdef_sbift); + + collmd->mfaces = dm->dupFaceArray(dm); + collmd->numfaces = dm->getNumFaces(dm); } else if(numverts == collmd->numverts) { @@ -5156,8 +5163,8 @@ static void collisionModifier_deformVerts( Mat4MulVecfl ( ob->obmat, collmd->xnew[i].co ); } - memcpy(collmd->current_xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); - memcpy(collmd->current_x, dm->getVertArray(dm), numverts*sizeof(MVert)); + memcpy(collmd->current_xnew, collmd->x, numverts*sizeof(MVert)); + memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert)); // recalc static bounding boxes bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0); diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index ce942f5bbb0..3cb76c7a845 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -35,48 +35,6 @@ #include "DNA_listBase.h" -/** -* Pin and unpin frames are the frames on which the vertices stop moving. -* They will assume the position they had prior to pinFrame until unpinFrame -* is reached. -*/ -typedef struct ClothVertex -{ - int flags; /* General flags per vertex. */ - float v [3]; /* The velocity of the point. */ - float xconst [3]; /* constrained position */ - float x [3]; /* The current position of this vertex. */ - float xold [3]; /* The previous position of this vertex.*/ - float tx [3]; /* temporary position */ - float txold [3]; /* temporary old position */ - float tv[3]; /* temporary "velocity", mostly used as tv = tx-txold */ - float mass; /* mass / weight of the vertex */ - float goal; /* goal, from SB */ - float impulse[3]; /* used in collision.c */ - unsigned int impulse_count; /* same as above */ -} -ClothVertex; - - -/** -* The definition of a spring. -*/ -typedef struct ClothSpring -{ - int ij; /* Pij from the paper, one end of the spring. */ - int kl; /* Pkl from the paper, one end of the spring. */ - float restlen; /* The original length of the spring. */ - int matrix_index; /* needed for implicit solver (fast lookup) */ - int type; /* types defined in BKE_cloth.h ("springType") */ - int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */ - float dfdx[3][3]; - float dfdv[3][3]; - float f[3]; -} -ClothSpring; - - - /** * This struct contains all the global data required to run a simulation. * At the time of this writing, this structure contains data appropriate diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index f8b6f4202a5..9ea0a9c2c9a 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -354,15 +354,20 @@ typedef struct ClothModifierData { } ClothModifierData; typedef struct CollisionModifierData { - ModifierData modifier; + 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; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 384b88be1eb..6b5083c5e26 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -4941,101 +4941,94 @@ static void object_panel_cloth(Object *ob) if(clmd) { - but = uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object", 170,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); + Cloth *cloth = clmd->clothObject; + int defCount; + char *clvg1, *clvg2; + char clmvg [] = "Weight Paint Groups%t|"; - if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) + 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, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); + uiBlockEndAlign(block); + uiBlockBeginAlign(block); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Spring damping"); + uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms.Cvi, 0.0, 10.0, 10, 0, "Air has normaly some thickness which slows falling things down"); + uiBlockEndAlign(block); + + uiClearButLock(); + + uiBlockBeginAlign(block); + uiDefBut(block, LABEL, 0, "Gravity:", 10,100,60,20, NULL, 0.0, 0, 0, 0, ""); + // uiClearButLock(); + + uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,100,80,20, &clmd->sim_parms.gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,100,80,20, &clmd->sim_parms.gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:", 230,100,80,20, &clmd->sim_parms.gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiBlockEndAlign(block); + + /* GOAL STUFF */ + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "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) { - Cloth *cloth = clmd->clothObject; - int defCount; - char *clvg1, *clvg2; - char clmvg [] = "Weight Paint Groups%t|"; - - val2=0; - - // uiDefButBitI(block, TOG, CSIMSETT_FLAG_ADVANCED, REDRAWBUTSOBJECT, "Advanced", 180,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Enable advanced mode"); - - /* GENERAL STUFF */ - uiClearButLock(); - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms.structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle coefficient (higher = less smaller but more big wrinkles)"); - uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); - uiBlockEndAlign(block); - uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Spring damping"); - uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms.Cvi, 0.0, 10.0, 10, 0, "Air has normaly some thickness which slows falling things down"); - uiBlockEndAlign(block); - - uiClearButLock(); - - uiBlockBeginAlign(block); - uiDefBut(block, LABEL, 0, "Gravity:", 10,100,60,20, NULL, 0.0, 0, 0, 0, ""); - // uiClearButLock(); - - uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,100,80,20, &clmd->sim_parms.gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,100,80,20, &clmd->sim_parms.gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:", 230,100,80,20, &clmd->sim_parms.gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); - uiBlockEndAlign(block); - - /* GOAL STUFF */ - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "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) + if(ob->type==OB_MESH) { - 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; - - 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); - } - else - { - uiDefButS(block, TOG, B_CLOTH_RENEW, "W", 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); - } - uiDefButF(block, NUM, B_CLOTH_RENEW, "Pin Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Pin (vertex target position) spring stiffness"); - /* - // 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"); - */ + 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; + + 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); } - 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) + else { - 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"); - } + uiDefButS(block, TOG, B_CLOTH_RENEW, "W", 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + } - uiBlockEndAlign(block); + 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"); + /* + // 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"); */ } + 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); + */ } } From 35c93b07bd18590b4b80acc8c8a6adf1d6f122c1 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 22 Jan 2008 20:28:12 +0000 Subject: [PATCH 074/101] GUI cloth panel refactor, also made many code rearrangements, cleared DNA up --- source/blender/blenkernel/BKE_cloth.h | 115 ++-------- source/blender/blenkernel/BKE_modifier.h | 2 +- source/blender/blenkernel/intern/cloth.c | 136 ++++++------ source/blender/blenkernel/intern/collision.c | 95 ++------- source/blender/blenkernel/intern/implicit.c | 43 ++-- source/blender/blenkernel/intern/modifier.c | 55 +++-- source/blender/blenloader/intern/readfile.c | 36 ++-- source/blender/blenloader/intern/writefile.c | 15 +- source/blender/makesdna/DNA_cloth_types.h | 5 +- source/blender/makesdna/DNA_modifier_types.h | 6 +- source/blender/src/buttons_object.c | 208 +++++++++---------- 11 files changed, 297 insertions(+), 419 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 6ad9893d072..cb52e2f3ca0 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -35,6 +35,7 @@ #define BKE_CLOTH_H #include "BLI_linklist.h" +#include "BKE_collision.h" #include "BKE_customdata.h" #include "BKE_DerivedMesh.h" #include "DNA_cloth_types.h" @@ -48,7 +49,7 @@ struct Cloth; struct MFace; struct DerivedMesh; struct ClothModifierData; - +struct CollisionTree; // this is needed for inlining behaviour #ifndef _WIN32 @@ -60,7 +61,6 @@ struct ClothModifierData; #define CLOTH_MAX_THREAD 2 - /** * Pin and unpin frames are the frames on which the vertices stop moving. * They will assume the position they had prior to pinFrame until unpinFrame @@ -169,40 +169,7 @@ void implicit_set_positions ( ClothModifierData *clmd ); // from cloth.c, needed for modifier.c void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float ( *vertexCos ) [3], int numverts ); -// used in 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; - // ClothVertex *verts; // just a pointer to the original datastructure - 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; - -typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, CollisionModifierData *collmd, CollisionTree * tree1, CollisionTree * tree2 ); +typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, CollisionModifierData *collmd, CollisionTree *tree1, CollisionTree *tree2 ); ///////////////////////////////////////////////// @@ -213,30 +180,20 @@ typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, CollisionModi void bvh_collision_response ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree * tree1, CollisionTree * tree2 ); int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ); -// needed for modifier.c -BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon); - -// needed for collision.c -void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving); - -//////////////////////////////////////////////// - - -///////////////////////////////////////////////// -// kdop.c -//////////////////////////////////////////////// - -// needed for cloth.c -void bvh_free ( BVH * bvh ); -void bvh_build (BVH *bvh); -LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr ); - -// needed for collision.c int bvh_traverse ( ClothModifierData * clmd, CollisionModifierData * collmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response ); -void bvh_update(BVH * bvh, int moving); //////////////////////////////////////////////// +//////////////////////////////////////////////// +// 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 ); +//////////////////////////////////////////////// + ///////////////////////////////////////////////// // cloth.c @@ -276,12 +233,6 @@ typedef struct } CM_SOLVER_DEF; - -/* new C implicit simulator */ -int implicit_init ( Object *ob, ClothModifierData *clmd ); -int implicit_free ( ClothModifierData *clmd ); -int implicit_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors ); - /* used for caching in implicit.c */ typedef struct Frame { @@ -292,45 +243,5 @@ typedef struct Frame } Frame; -/* used for collisions in collision.c */ -typedef struct CollPair -{ - unsigned int face1; // cloth face - unsigned int face2; // object face - double distance; // magnitude of vector - float normal[3]; - float vector[3]; // unnormalized collision vector: p2-p1 - float pa[3], pb[3]; // collision point p1 on face1, p2 on face2 - int lastsign; // indicates if the distance sign has changed, unused itm - float time; // collision time, from 0 up to 1 - unsigned int ap1, ap2, ap3, bp1, bp2, bp3, bp4; - unsigned int pointsb[4]; -} -CollPair; - -/* used for collisions in collision.c */ -typedef struct EdgeCollPair -{ - unsigned int p11, p12, p21, p22; - float normal[3]; - float vector[3]; - float time; - int lastsign; - float pa[3], pb[3]; // collision point p1 on face1, p2 on face2 -} -EdgeCollPair; - -/* used for collisions in collision.c */ -typedef struct FaceCollPair -{ - unsigned int p11, p12, p13, p21; - float normal[3]; - float vector[3]; - float time; - int lastsign; - float pa[3], pb[3]; // collision point p1 on face1, p2 on face2 -} -FaceCollPair; - #endif diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 682eb1a00dd..068190cb6fa 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -287,7 +287,7 @@ int modifiers_getCageIndex(struct Object *ob, int *lastPossibleCageIndex_r); int modifiers_isSoftbodyEnabled(struct Object *ob); -ModifierData * modifiers_isClothEnabled(Object *ob); +ClothModifierData * modifiers_isClothEnabled(Object *ob); int modifiers_isParticleEnabled(struct Object *ob); struct Object *modifiers_isDeformedByArmature(struct Object *ob); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 3fa99279435..1b284d0d35a 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -141,46 +141,46 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short * 2. fill object with standard values or with the GUI settings if given */ void cloth_init ( ClothModifierData *clmd ) -{ +{ /* Initialize our new data structure to reasonable values. */ - clmd->sim_parms.gravity [0] = 0.0; - clmd->sim_parms.gravity [1] = 0.0; - clmd->sim_parms.gravity [2] = -9.81; - clmd->sim_parms.structural = 100.0; - clmd->sim_parms.shear = 100.0; - clmd->sim_parms.bending = 1.0; - clmd->sim_parms.Cdis = 5.0; - clmd->sim_parms.Cvi = 1.0; - clmd->sim_parms.mass = 1.0f; - clmd->sim_parms.stepsPerFrame = 5; - clmd->sim_parms.sim_time = 1.0; - clmd->sim_parms.flags = CLOTH_SIMSETTINGS_FLAG_RESET; - clmd->sim_parms.solver_type = 0; - clmd->sim_parms.preroll = 0; - clmd->sim_parms.maxspringlen = 10; - clmd->sim_parms.firstframe = 1; - clmd->sim_parms.lastframe = 250; - clmd->sim_parms.vgroup_mass = 0; - clmd->coll_parms.self_friction = 5.0; - clmd->coll_parms.friction = 10.0; - clmd->coll_parms.loop_count = 1; - clmd->coll_parms.epsilon = 0.01f; - clmd->coll_parms.flags = 0; + clmd->sim_parms->gravity [0] = 0.0; + clmd->sim_parms->gravity [1] = 0.0; + clmd->sim_parms->gravity [2] = -9.81; + clmd->sim_parms->structural = 100.0; + clmd->sim_parms->shear = 100.0; + clmd->sim_parms->bending = 1.0; + clmd->sim_parms->Cdis = 5.0; + clmd->sim_parms->Cvi = 1.0; + clmd->sim_parms->mass = 1.0f; + clmd->sim_parms->stepsPerFrame = 5; + clmd->sim_parms->sim_time = 1.0; + clmd->sim_parms->flags = CLOTH_SIMSETTINGS_FLAG_RESET; + clmd->sim_parms->solver_type = 0; + clmd->sim_parms->preroll = 0; + clmd->sim_parms->maxspringlen = 10; + clmd->sim_parms->firstframe = 1; + clmd->sim_parms->lastframe = 250; + clmd->sim_parms->vgroup_mass = 0; + clmd->coll_parms->self_friction = 5.0; + clmd->coll_parms->friction = 10.0; + clmd->coll_parms->loop_count = 1; + clmd->coll_parms->epsilon = 0.01f; + clmd->coll_parms->flags = 0; /* These defaults are copied from softbody.c's * softbody_calc_forces() function. */ - clmd->sim_parms.eff_force_scale = 1000.0; - clmd->sim_parms.eff_wind_scale = 250.0; + clmd->sim_parms->eff_force_scale = 1000.0; + clmd->sim_parms->eff_wind_scale = 250.0; // also from softbodies - clmd->sim_parms.maxgoal = 1.0f; - clmd->sim_parms.mingoal = 0.0f; - clmd->sim_parms.defgoal = 0.0f; - clmd->sim_parms.goalspring = 100.0f; - clmd->sim_parms.goalfrict = 0.0f; + clmd->sim_parms->maxgoal = 1.0f; + clmd->sim_parms->mingoal = 0.0f; + clmd->sim_parms->defgoal = 0.0f; + clmd->sim_parms->goalspring = 100.0f; + clmd->sim_parms->goalfrict = 0.0f; - clmd->sim_parms.cache = NULL; + clmd->sim_parms->cache = NULL; } @@ -488,7 +488,7 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) { int stack_index = -1; - if(!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) + if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) { stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); @@ -557,7 +557,7 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) fclose(fp); } - if(clmd->sim_parms.solver_type == 0) + if(clmd->sim_parms->solver_type == 0) implicit_set_positions(clmd); return ret; @@ -585,21 +585,21 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, ClothVertex *newframe= NULL, *verts; Frame *frame = NULL; LinkNode *search = NULL; - float deltaTime = current_time - clmd->sim_parms.sim_time; + float deltaTime = current_time - clmd->sim_parms->sim_time; - clmd->sim_parms.ob = ob; + clmd->sim_parms->ob = ob; // only be active during a specific period: // that's "first frame" and "last frame" on GUI /* - if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) ) + if ( ! ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) ) { if ( clmd->clothObject ) { - if ( clmd->sim_parms.cache ) + if ( clmd->sim_parms->cache ) { - if ( current_time < clmd->sim_parms.firstframe ) + if ( current_time < clmd->sim_parms->firstframe ) { int frametime = cloth_cache_first_frame ( clmd ); if ( cloth_cache_search_frame ( clmd, frametime ) ) @@ -609,7 +609,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, } return; } - else if ( current_time > clmd->sim_parms.lastframe ) + else if ( current_time > clmd->sim_parms->lastframe ) { int frametime = cloth_cache_last_frame ( clmd ); if ( cloth_cache_search_frame ( clmd, frametime ) ) @@ -626,7 +626,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, cloth_cache_get_frame ( clmd, framenr ); cloth_to_object ( ob, clmd, vertexCos, numverts ); } - clmd->sim_parms.sim_time = current_time; + clmd->sim_parms->sim_time = current_time; return; } } @@ -636,28 +636,28 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, */ // unused in the moment, calculated seperately in implicit.c - clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame; + clmd->sim_parms->dt = 1.0f / clmd->sim_parms->stepsPerFrame; - clmd->sim_parms.sim_time = current_time; + clmd->sim_parms->sim_time = current_time; // check if cloth object was some collision object before and needs freeing now - if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) && ( clmd->clothObject != NULL ) && ( clmd->clothObject->old_solver_type == 255 ) ) + if ( ! ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) && ( clmd->clothObject != NULL ) && ( clmd->clothObject->old_solver_type == 255 ) ) { // temporary set CSIMSETT_FLAG_COLLOBJ flag for proper freeing - clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; cloth_free_modifier ( clmd ); - clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_COLLOBJ; + clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_COLLOBJ; } // This is for collisions objects: check special case CSIMSETT_FLAG_COLLOBJ - if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) { // save next position + time if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) ) { if ( !collobj_from_object ( ob, clmd, dm, vertexCos, framenr ) ) { - clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; cloth_free_modifier ( clmd ); return; } @@ -669,8 +669,8 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, } // Save old position - clmd->sim_parms.sim_time_old = clmd->sim_parms.sim_time; - clmd->sim_parms.sim_time = current_time; + clmd->sim_parms->sim_time_old = clmd->sim_parms->sim_time; + clmd->sim_parms->sim_time = current_time; verts = cloth->verts; @@ -707,7 +707,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, cloth = clmd->clothObject; } - clmd->clothObject->old_solver_type = clmd->sim_parms.solver_type; + clmd->clothObject->old_solver_type = clmd->sim_parms->solver_type; // Insure we have a clmd->clothObject, in case allocation failed. if ( clmd->clothObject != NULL ) @@ -731,8 +731,8 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, tstart(); // Call the solver. - if ( solvers [clmd->sim_parms.solver_type].solver ) - solvers [clmd->sim_parms.solver_type].solver ( ob, framenr, clmd, effectors ); + if ( solvers [clmd->sim_parms->solver_type].solver ) + solvers [clmd->sim_parms->solver_type].solver ( ob, framenr, clmd, effectors ); tend(); // printf ( "Cloth simulation time: %f\n", ( float ) tval() ); @@ -749,7 +749,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, cloth_to_object ( ob, clmd, vertexCos, numverts ); // bvh_free(clmd->clothObject->tree); - // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); + // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms->epsilon); } } @@ -772,14 +772,14 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, void cloth_free_modifier ( ClothModifierData *clmd ) { Cloth *cloth = NULL; - Object *ob = clmd->sim_parms.ob; + Object *ob = clmd->sim_parms->ob; if ( !clmd ) return; cloth = clmd->clothObject; - if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT ) ) + if ( ! ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT ) ) { if ( cloth ) { @@ -898,7 +898,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short for ( i = 0; i < numverts; i++, verts++ ) { // LATER ON, support also mass painting here - if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) { dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT ); if ( dvert ) @@ -913,7 +913,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short /* // Kicking goal factor to simplify things...who uses that anyway? - // ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal ); + // ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); */ verts->goal = ( float ) pow ( verts->goal , 4.0f ); @@ -990,7 +990,7 @@ static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMes verts->impulse_count = 0; VECCOPY ( verts->impulse, tnull ); } - clmd->clothObject->tree = bvh_build_from_cloth ( clmd,clmd->coll_parms.epsilon ); + clmd->clothObject->tree = bvh_build_from_cloth ( clmd,clmd->coll_parms->epsilon ); } @@ -1039,7 +1039,7 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh return 0; } - clmd->sim_parms.ob = ob; + clmd->sim_parms->ob = ob; switch ( ob->type ) { @@ -1066,10 +1066,10 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh VECCOPY ( verts->x, mvert[i].co ); Mat4MulVecfl ( ob->obmat, verts->x ); - verts->mass = clmd->sim_parms.mass; + verts->mass = clmd->sim_parms->mass; - if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - verts->goal= clmd->sim_parms.defgoal; + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + verts->goal= clmd->sim_parms->defgoal; else verts->goal= 0.0f; @@ -1090,14 +1090,14 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh } // apply / set vertex groups - if ( clmd->sim_parms.vgroup_mass > 0 ) - cloth_apply_vgroup ( clmd, dm, clmd->sim_parms.vgroup_mass ); + if ( clmd->sim_parms->vgroup_mass > 0 ) + cloth_apply_vgroup ( clmd, dm, clmd->sim_parms->vgroup_mass ); // init our solver - if ( solvers [clmd->sim_parms.solver_type].init ) - solvers [clmd->sim_parms.solver_type].init ( ob, clmd ); + if ( solvers [clmd->sim_parms->solver_type].init ) + solvers [clmd->sim_parms->solver_type].init ( ob, clmd ); - clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms.epsilon ); + clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); cloth_write_cache(ob, clmd, framenr-1); } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index c5e6c119e10..75201bbcea3 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -459,7 +459,7 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa cloth1 = clmd->clothObject; - search = clmd->coll_parms.collision_list; + search = clmd->coll_parms->collision_list; while(search) { @@ -503,10 +503,10 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa float vrel_t_pre[3]; float vrel_t[3]; double impulse; - float epsilon = clmd->coll_parms.epsilon; + float epsilon = clmd->coll_parms->epsilon; float overlap = (epsilon + ALMOST_ZERO-collpair->distance); - // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); + // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms->friction*0.01, magrelVel); // magtangent = INPR(tangential, tangential); @@ -562,11 +562,11 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa // Apply the impulse and increase impulse counters. /* - // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent); + // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms->friction*0.01, magtangent); VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); - // VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); + // VecMulf(vrel_t_pre, clmd->coll_parms->friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); magtangent = Normalize(vrel_t_pre); - VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent)); + VecMulf(vrel_t_pre, MIN2(clmd->coll_parms->friction*0.01f*magnormal,magtangent)); VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre); */ @@ -600,7 +600,7 @@ void cloth_collision_static(ClothModifierData *clmd, CollisionModifierData *coll MFace *face1=NULL, *face2=NULL; ClothVertex *verts1=NULL; double distance = 0; - float epsilon = clmd->coll_parms.epsilon; + float epsilon = clmd->coll_parms->epsilon; unsigned int i = 0; for(i = 0; i < 4; i++) @@ -694,7 +694,7 @@ void cloth_collision_static(ClothModifierData *clmd, CollisionModifierData *coll Normalize(collpair->normal); collpair->distance = distance; - BLI_linklist_append(&clmd->coll_parms.collision_list, collpair); + BLI_linklist_append(&clmd->coll_parms->collision_list, collpair); } else @@ -747,7 +747,7 @@ void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *co MFace *face1=NULL, *face2=NULL; ClothVertex *verts1=NULL, *verts2=NULL; double distance = 0; - float epsilon = clmd->coll_parms.epsilon; + float epsilon = clmd->coll_parms->epsilon; unsigned int i = 0, j = 0, k = 0; int numsolutions = 0; float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; @@ -882,7 +882,7 @@ void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *col MFace *face1=NULL, *face2=NULL; ClothVertex *verts1=NULL, *verts2=NULL; double distance = 0; - float epsilon = clmd->coll_parms.epsilon; + float epsilon = clmd->coll_parms->epsilon; unsigned int i = 0, j = 0, k = 0; int numsolutions = 0; float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; @@ -978,52 +978,6 @@ void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clm cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); } -// move collision objects forward in time and update static bounding boxes -void cloth_update_collision_objects(float step) -{ - Base *base=NULL; - ClothModifierData *coll_clmd=NULL; - Object *coll_ob=NULL; - unsigned int i=0; - - // search all objects for collision object - for (base = G.scene->base.first; base; base = base->next) - { - - coll_ob = base->object; - coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); - if (!coll_clmd) - continue; - - // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) - { - if (coll_clmd->clothObject && coll_clmd->clothObject->tree) - { - Cloth *coll_cloth = coll_clmd->clothObject; - BVH *coll_bvh = coll_clmd->clothObject->tree; - unsigned int coll_numverts = coll_cloth->numverts; - - // update position of collision object - for(i = 0; i < coll_numverts; i++) - { - VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx); - - VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step); - - // no dt here because of float rounding errors - VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold); - } - - // update BVH of collision object - bvh_update_from_cloth(coll_clmd, 0); // 0 means STATIC, 1 means MOVING - } - else - printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } - } -} - // CLOTH_MAX_THRESHOLD defines how much collision rounds/loops should be taken #define CLOTH_MAX_THRESHOLD 10 @@ -1041,7 +995,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) float tnull[3] = {0,0,0}; int ret = 0; - if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) + if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) { return 0; } @@ -1059,14 +1013,11 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) // update cloth bvh bvh_update_from_cloth(clmd, 0); // 0 means STATIC, 1 means MOVING (see later in this function) - // update collision objects - cloth_update_collision_objects(step); - do { result = 0; ic = 0; - clmd->coll_parms.collision_list = NULL; + clmd->coll_parms->collision_list = NULL; // check all collision objects for (base = G.scene->base.first; base; base = base->next) @@ -1125,9 +1076,9 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) } // free collision list - if(clmd->coll_parms.collision_list) + if(clmd->coll_parms->collision_list) { - LinkNode *search = clmd->coll_parms.collision_list; + LinkNode *search = clmd->coll_parms->collision_list; while(search) { CollPair *coll_pair = search->link; @@ -1135,9 +1086,9 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) MEM_freeN(coll_pair); search = search->next; } - BLI_linklist_free(clmd->coll_parms.collision_list,NULL); + BLI_linklist_free(clmd->coll_parms->collision_list,NULL); - clmd->coll_parms.collision_list = NULL; + clmd->coll_parms->collision_list = NULL; } rounds++; } @@ -1191,7 +1142,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { result = 0; ic = 0; - clmd->coll_parms.collision_list = NULL; + clmd->coll_parms->collision_list = NULL; // check all collision objects for (base = G.scene->base.first; base; base = base->next) @@ -1203,7 +1154,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) continue; // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + if (coll_clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) { if (coll_clmd->clothObject && coll_clmd->clothObject->tree) { @@ -1233,7 +1184,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) continue; // if collision object go on - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + if (coll_clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) { if (coll_clmd->clothObject) result += cloth_collision_response_moving_tris(clmd, coll_clmd); @@ -1271,9 +1222,9 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) // free collision list - if(clmd->coll_parms.collision_list) + if(clmd->coll_parms->collision_list) { - LinkNode *search = clmd->coll_parms.collision_list; + LinkNode *search = clmd->coll_parms->collision_list; while(search) { CollPair *coll_pair = search->link; @@ -1281,9 +1232,9 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) MEM_freeN(coll_pair); search = search->next; } - BLI_linklist_free(clmd->coll_parms.collision_list,NULL); + BLI_linklist_free(clmd->coll_parms->collision_list,NULL); - clmd->coll_parms.collision_list = NULL; + clmd->coll_parms->collision_list = NULL; } // printf("ic: %d\n", ic); diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 4985b3efa3f..3f21bf2bfc5 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1081,7 +1081,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float vel[3]; float k = 0.0f; float L = s->restlen; - float cb = clmd->sim_parms.structural; + float cb = clmd->sim_parms->structural; float nullf[3] = {0,0,0}; float stretch_force[3] = {0,0,0}; @@ -1089,7 +1089,6 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float damping_force[3] = {0,0,0}; float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; Cloth *cloth = clmd->clothObject; - ClothVertex *verts = cloth->verts; VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); @@ -1107,8 +1106,8 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, /* if(length>L) { - if((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) - && ((((length-L)*100.0f/L) > clmd->sim_parms.maxspringlen))) // cut spring! + if((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) + && ((((length-L)*100.0f/L) > clmd->sim_parms->maxspringlen))) // cut spring! { s->flags |= CSPRING_FLAG_DEACTIVATE; return; @@ -1130,19 +1129,19 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, { s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = clmd->sim_parms.structural; + k = clmd->sim_parms->structural; mul_fvector_S(stretch_force, dir, (k*(length-L))); VECADD(s->f, s->f, stretch_force); // Ascher & Boxman, p.21: Damping only during elonglation - mul_fvector_S(damping_force, extent, clmd->sim_parms.Cdis * ((INPR(vel,extent)/length))); + mul_fvector_S(damping_force, extent, clmd->sim_parms->Cdis * ((INPR(vel,extent)/length))); VECADD(s->f, s->f, damping_force); dfdx_spring_type1(s->dfdx, dir,length,L,k); - dfdv_damp(s->dfdv, dir,clmd->sim_parms.Cdis); + dfdv_damp(s->dfdv, dir,clmd->sim_parms->Cdis); } } else // calculate force of bending springs @@ -1151,7 +1150,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, { s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = clmd->sim_parms.bending; + k = clmd->sim_parms->bending; mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); VECADD(s->f, s->f, bending_force); @@ -1228,7 +1227,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec /* Collect forces and derivatives: F,dFdX,dFdV */ Cloth *cloth = clmd->clothObject; unsigned int i = 0; - float spring_air = clmd->sim_parms.Cvi * 0.01f; /* viscosity of air scaled in percent */ + float spring_air = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */ float gravity[3]; float tm2[3][3] = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}}; ClothVertex *verts = cloth->verts; @@ -1240,7 +1239,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec LinkNode *search = cloth->springs; - VECCOPY(gravity, clmd->sim_parms.gravity); + VECCOPY(gravity, clmd->sim_parms->gravity); mul_fvector_S(gravity, gravity, 0.001f); /* scale gravity force */ /* set dFdX jacobi matrix to zero */ @@ -1253,7 +1252,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec submul_lfvectorS(lF, lV, spring_air, numverts); /* do goal stuff */ - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { for(i = 0; i < numverts; i++) { @@ -1265,12 +1264,12 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec VECADD(tvect, tvect, verts[i].xold); VECSUB(auxvect, tvect, lX[i]); - ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms.goalspring)-1.0f ; + ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms->goalspring)-1.0f ; VECADDS(lF[i], lF[i], auxvect, -ks); // calulate damping forces generated by goals VECSUB(velgoal,verts[i].xold, verts[i].xconst); - kd = clmd->sim_parms.goalfrict * 0.01f; // friction force scale taken from SB + kd = clmd->sim_parms->goalfrict * 0.01f; // friction force scale taken from SB VECSUBADDSS(lF[i], velgoal, kd, lV[i], kd); } @@ -1287,7 +1286,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec for(i = 0; i < cloth->numverts; i++) { float vertexnormal[3]={0,0,0}; - float fieldfactor = 1000.0f, windfactor = 250.0f; // from sb + float fieldfactor = 1000.0f; // windfactor = 250.0f; // from sb pdDoEffectors(effectors, lX[i], force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); @@ -1307,7 +1306,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec while(search) { // only handle active springs - // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)){} + // if(((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)){} cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); search = search->next; @@ -1318,7 +1317,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec while(search) { // only handle active springs - // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) + // if(((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)) cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); search = search->next; } @@ -1357,16 +1356,16 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) { - unsigned int i=0, j; + unsigned int i=0; float step=0.0f, tf=1.0f; Cloth *cloth = clmd->clothObject; ClothVertex *verts = cloth->verts; unsigned int numverts = cloth->numverts; - float dt = 1.0f / clmd->sim_parms.stepsPerFrame; + float dt = 1.0f / clmd->sim_parms->stepsPerFrame; Implicit_Data *id = cloth->implicit; int result = 0; - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { for(i = 0; i < numverts; i++) { @@ -1389,7 +1388,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); - if(clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + if(clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) { // collisions // itstart(); @@ -1397,7 +1396,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // update verts to current positions for(i = 0; i < numverts; i++) { - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { if(verts [i].goal >= SOFTGOALSNAP) { @@ -1472,7 +1471,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase for(i = 0; i < numverts; i++) { - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { if(verts [i].goal < SOFTGOALSNAP) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index da31929442d..9273b6bf9ab 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4947,6 +4947,14 @@ static void softbodyModifier_deformVerts( static void clothModifier_initData(ModifierData *md) { ClothModifierData *clmd = (ClothModifierData*) md; + + clmd->sim_parms = MEM_callocN(sizeof(SimulationSettings), "cloth sim parms"); + clmd->coll_parms = MEM_callocN(sizeof(CollisionSettings), "cloth coll parms"); + + /* check for alloc failing */ + if(!clmd->sim_parms || !clmd->coll_parms) + return; + cloth_init (clmd); } @@ -4956,7 +4964,7 @@ static void clothModifier_deformVerts( { DerivedMesh *dm = NULL; - // if possible use/create DerivedMesh + /* if possible use/create DerivedMesh */ if(derivedData) dm = CDDM_copy(derivedData); else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); @@ -4967,6 +4975,8 @@ static void clothModifier_deformVerts( CDDM_calc_normals(dm); } + /* TODO: check for sim_parms / coll_parms NOT NULL */ + clothModifier_do((ClothModifierData *)md, ob, dm, vertexCos, numVerts); if(dm) @@ -4991,7 +5001,7 @@ static void clothModifier_updateDepgraph( ClothModifierData *coll_clmd = (ClothModifierData *)modifiers_findByType(ob1, eModifierType_Cloth); if(coll_clmd) { - if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + if (coll_clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) { DagNode *curNode = dag_get_node(forest, ob1); dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA); @@ -5008,8 +5018,8 @@ CustomDataMask clothModifier_requiredDataMask(ModifierData *md) CustomDataMask dataMask = 0; /* ask for vertexgroups if we need them */ - if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - if (clmd->sim_parms.vgroup_mass > 0) + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + if (clmd->sim_parms->vgroup_mass > 0) dataMask |= (1 << CD_MDEFORMVERT); return dataMask; @@ -5027,8 +5037,11 @@ static void clothModifier_freeData(ModifierData *md) if (clmd) { - clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; + clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; cloth_free_modifier (clmd); + + MEM_freeN(clmd->sim_parms); + MEM_freeN(clmd->coll_parms); } } @@ -5096,9 +5109,8 @@ static void collisionModifier_deformVerts( float current_time = 0; unsigned int numverts = 0, i = 0; MVert *tempVert = NULL; - - // if possible use/create DerivedMesh + /* if possible use/create DerivedMesh */ if(derivedData) dm = CDDM_copy(derivedData); else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); @@ -5112,12 +5124,11 @@ static void collisionModifier_deformVerts( { CDDM_apply_vert_coords(dm, vertexCos); CDDM_calc_normals(dm); - - + current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); if(current_time > collmd->time) - { + { numverts = dm->getNumVerts ( dm ); // check if mesh has changed @@ -5141,12 +5152,12 @@ static void collisionModifier_deformVerts( collmd->numverts = numverts; - // TODO: epsilon - // create bounding box hierarchy - collmd->tree = bvh_build_from_mvert(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->x, numverts, ob->pd->pdef_sbift); - 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) { @@ -5166,8 +5177,16 @@ static void collisionModifier_deformVerts( memcpy(collmd->current_xnew, collmd->x, numverts*sizeof(MVert)); memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert)); - // recalc static bounding boxes - bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0); + /* 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; @@ -7271,11 +7290,11 @@ int modifiers_isSoftbodyEnabled(Object *ob) return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -ModifierData * modifiers_isClothEnabled(Object *ob) +ClothModifierData * modifiers_isClothEnabled(Object *ob) { ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); - return md; + return (ClothModifierData *)md; } int modifiers_isParticleEnabled(Object *ob) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index af75e9490d5..c725b3d63ac 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2998,29 +2998,41 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) SubsurfModifierData *smd = (SubsurfModifierData*) md; smd->emCache = smd->mCache = 0; - } + } 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); - */ - - } + ClothModifierData *clmd = (ClothModifierData*) md; + + clmd->clothObject = NULL; + + clmd->sim_parms= newdataadr(fd, clmd->sim_parms); + clmd->coll_parms= newdataadr(fd, clmd->coll_parms); + + } else if (md->type==eModifierType_Collision) { - /* + CollisionModifierData *collmd = (CollisionModifierData*) md; + /* + // 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; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 3ac4160b105..8bcc2497dbd 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -839,11 +839,22 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) } else if(md->type==eModifierType_Cloth) { ClothModifierData *clmd = (ClothModifierData*) md; - /* + writestruct(wd, DATA, "SimulationSettings", 1, clmd->sim_parms); writestruct(wd, DATA, "CollisionSettings", 1, clmd->coll_parms); - */ + } + else if (md->type==eModifierType_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; diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 3cb76c7a845..ee4a0130dbf 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -34,7 +34,6 @@ #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 @@ -116,9 +115,9 @@ typedef struct Cloth unsigned char old_solver_type; unsigned char pad2; short pad3; - void *tree; /* collision tree for this cloth object */ + struct BVH *tree; /* collision tree for this cloth object */ struct MFace *mfaces; - void *implicit; /* our implicit solver connects to this pointer */ + struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ } Cloth; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 9ea0a9c2c9a..e5c3b46d875 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -7,8 +7,6 @@ #define MODSTACK_DEBUG 1 -#include "DNA_cloth_types.h" - /* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE! */ typedef enum ModifierType { @@ -349,8 +347,8 @@ typedef struct ClothModifierData { ModifierData modifier; struct Cloth *clothObject; /* The internal data structure for cloth. */ - struct SimulationSettings sim_parms; /* definition is in DNA_cloth_types.h */ - struct CollisionSettings coll_parms; /* definition is in DNA_cloth_types.h */ + struct SimulationSettings *sim_parms; /* definition is in DNA_cloth_types.h */ + struct CollisionSettings *coll_parms; /* definition is in DNA_cloth_types.h */ } ClothModifierData; typedef struct CollisionModifierData { diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 6b5083c5e26..90f7dab0a58 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3083,7 +3083,7 @@ void do_effects_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - if(clmd->sim_parms.cache) + if(clmd->sim_parms->cache) { CFRA= 1; update_for_newframe_muted(); @@ -3099,7 +3099,7 @@ void do_effects_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - clmd->sim_parms.vgroup_mass = 0; + clmd->sim_parms->vgroup_mass = 0; do_object_panels(B_CLOTH_RENEW); } allqueue(REDRAWBUTSOBJECT, 0); @@ -4923,25 +4923,25 @@ static void object_cloth__enabletoggle(void *ob_v, void *arg2) allqueue(REDRAWBUTSEDIT, 0); } + static void object_panel_cloth(Object *ob) { uiBlock *block; - static int val, val2; uiBut *but; + static int val, val2; ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Cloth", "Physics", 640, 0, 318, 204)==0) return; + + 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); - if(ob->id.lib) uiSetButLock(1, "Can't edit library data"); - val = ((clmd)?(1):(0)); + but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Cloth", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become cloth"); - but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Cloth Object", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become cloth"); uiButSetFunc(but, object_cloth__enabletoggle, ob, NULL); uiDefBut(block, LABEL, 0, "",10,10,300,0, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ if(clmd) { - Cloth *cloth = clmd->clothObject; int defCount; char *clvg1, *clvg2; char clmvg [] = "Weight Paint Groups%t|"; @@ -4951,13 +4951,13 @@ static void object_panel_cloth(Object *ob) /* 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, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms->structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms->bending, 0.0, 10000.0, 1000, 0, "Wrinkle coefficient (higher = less smaller but more big wrinkles)"); + uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,150,150,20, &clmd->sim_parms->stepsPerFrame, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms.Cdis, 0.0, 10.0, 10, 0, "Spring damping"); - uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms.Cvi, 0.0, 10.0, 10, 0, "Air has normaly some thickness which slows falling things down"); + 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"); uiBlockEndAlign(block); uiClearButLock(); @@ -4966,15 +4966,20 @@ static void object_panel_cloth(Object *ob) uiDefBut(block, LABEL, 0, "Gravity:", 10,100,60,20, NULL, 0.0, 0, 0, 0, ""); // uiClearButLock(); - uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,100,80,20, &clmd->sim_parms.gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,100,80,20, &clmd->sim_parms.gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:", 230,100,80,20, &clmd->sim_parms.gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,100,80,20, &clmd->sim_parms->gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,100,80,20, &clmd->sim_parms->gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:", 230,100,80,20, &clmd->sim_parms->gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); uiBlockEndAlign(block); /* GOAL STUFF */ uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "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) + + if(BLI_countlist (&ob->defbase) > 0) + { + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "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) { if(ob->type==OB_MESH) { @@ -4989,30 +4994,30 @@ static void object_panel_cloth(Object *ob) defCount = BLI_countlist (&ob->defbase); if (defCount == 0) { - clmd->sim_parms.vgroup_mass = 0; + clmd->sim_parms->vgroup_mass = 0; } else - if(!clmd->sim_parms.vgroup_mass) - clmd->sim_parms.vgroup_mass = 1; + if(!clmd->sim_parms->vgroup_mass) + clmd->sim_parms->vgroup_mass = 1; 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"); + 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); } else { - uiDefButS(block, TOG, B_CLOTH_RENEW, "W", 140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + uiDefButS(block, TOG, B_CLOTH_RENEW, "W", 140,70,20,20, &clmd->sim_parms->vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); } - uiDefButF(block, NUM, B_CLOTH_RENEW, "Pin Stiff:", 10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Pin (vertex target position) spring stiffness"); + 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"); /* // 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"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Damp:", 160,50,150,20, &clmd->sim_parms->goalfrict , 0.0, 50.0, 10, 0, "Goal (vertex target position) friction"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Min:", 10,30,150,20, &clmd->sim_parms->mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range"); + uiDefButF(block, NUM, B_CLOTH_RENEW, "G Max:", 160,30,150,20, &clmd->sim_parms->maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); */ } uiBlockEndAlign(block); @@ -5020,111 +5025,85 @@ static void object_panel_cloth(Object *ob) /* // no tearing supported anymore since modifier stack restrictions uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CSIMSETT_FLAG_TEARING_ENABLED, B_EFFECT_DEP, "Tearing", 10,0,150,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); + uiDefButBitI(block, TOG, CSIMSETT_FLAG_TEARING_ENABLED, B_EFFECT_DEP, "Tearing", 10,0,150,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Sets object to become a cloth collision object"); - if (clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) + if (clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) { - uiDefButI(block, NUM, B_DIFF, "Max extent:", 160,0,150,20, &clmd->sim_parms.maxspringlen, 1.0, 1000.0, 10, 0, "Maximum extension before spring gets cut"); - } + uiDefButI(block, NUM, B_DIFF, "Max extent:", 160,0,150,20, &clmd->sim_parms->maxspringlen, 1.0, 1000.0, 10, 0, "Maximum extension before spring gets cut"); + } uiBlockEndAlign(block); */ } + + uiBlockEndAlign(block); + + uiBlockEndAlign(block); } - static void object_panel_cloth_II(Object *ob) { uiBlock *block; - static int val; - uiBut *but; 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) - { - if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) - { - Cloth *cloth = clmd->clothObject; - char str[128]; - - block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_II", UI_EMBOSS, UI_HELV, curarea->win); - uiNewPanelTabbed("Cloth", "Physics"); - if(uiNewPanel(curarea, block, "Cloth Cache", "Physics", 651, 0, 318, 204)==0) return; - - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - - uiDefButI(block, NUM, B_DIFF, "First Frame:", 10,160,150,20, &clmd->sim_parms.firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts"); - uiDefButI(block, NUM, B_DIFF, "Last Frame:", 160,160,150,20, &clmd->sim_parms.lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops"); - - if(clmd->sim_parms.cache) - { - int length = BLI_linklist_length(clmd->sim_parms.cache); - - /* correct spelling if only 1 frame cacheed --> only gimmick */ - if(length-clmd->sim_parms.preroll>1) - sprintf (str, "Frame 1 - %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms.preroll, clmd->sim_parms.preroll, length); - else - sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms.preroll, clmd->sim_parms.preroll, length); - - uiDefBut(block, LABEL, 0, str, 10,140,290,20, NULL, 0.0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "Clear cache:", 10,120,290,20, NULL, 0.0, 0, 0, 0, ""); - uiBlockBeginAlign (block); - uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 10, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache without preroll"); - uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache"); - if(length>1) // B_CLOTH_CHANGEPREROLL - uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); - else - uiDefBut(block, LABEL, 0, " ", 10,80,145,20, NULL, 0.0, 0, 0, 0, ""); - } - else - { - uiDefBut(block, LABEL, 0, "No frames cached.", 10,120,290,20, NULL, 0.0, 0, 0, 0, ""); - } - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,50,145,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); - uiBlockEndAlign(block); - } - } - // uiBlockEndAlign(block); -} - -static void object_panel_cloth_III(Object *ob) -{ - uiBlock *block; - static int val; - uiBut *but; - ClothModifierData *clmd = NULL; - clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) - { - Cloth *cloth = clmd->clothObject; - char str[128]; - - block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_III", UI_EMBOSS, UI_HELV, curarea->win); - uiNewPanelTabbed("Cloth", "Physics"); - if(uiNewPanel(curarea, block, "Cloth Collisions", "Physics", 651, 0, 318, 204)==0) return; + // char str[128]; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); - - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,70,130,20, &clmd->coll_parms.flags, 0, 0, 0, 0, "Enable collisions with this object"); - if (clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) - { - // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ - uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,30,150,20, &clmd->coll_parms.epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in"); - uiDefBut(block, LABEL, 0, "",160,30,150,20, NULL, 0.0, 0, 0, 0, ""); - } - else - uiDefBut(block, LABEL, 0, "",140,10,170,20, NULL, 0.0, 0, 0, 0, ""); - uiBlockEndAlign(block); + uiDefButI(block, NUM, B_DIFF, "First Frame:", 10,160,150,20, &clmd->sim_parms->firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts"); + uiDefButI(block, NUM, B_DIFF, "Last Frame:", 160,160,150,20, &clmd->sim_parms->lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops"); + + uiDefBut(block, LABEL, 0, "",10,140,300,20, NULL, 0.0, 0, 0, 0, ""); + + /* correct spelling if only 1 frame cacheed --> only gimmick */ + /* + if(length-clmd->sim_parms->preroll>1) + sprintf (str, "Frame 1 - %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length); + else + sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length); + */ + + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,120,300,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); + + if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) + { + 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, 0, 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, 0, 0, "Free cloth cache starting from next frame"); + uiDefBut(block, LABEL, 0, " ", 10,80,300,20, NULL, 0.0, 0, 0, 0, ""); + } + else + { + uiDefBut(block, LABEL, 0, " ", 10,100,300,40, NULL, 0.0, 0, 0, 0, ""); } - } - // uiBlockEndAlign(block); -} + /* + 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_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "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_COLLISIONSETTINGS_FLAG_ENABLED) + { + uiDefButF(block, NUM, B_CLOTH_RENEW, "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"); + } + else + uiDefBut(block, LABEL, 0, "",160,60,150,20, NULL, 0.0, 0, 0, 0, ""); + } + + uiBlockEndAlign(block); + +} void object_panels() { @@ -5156,7 +5135,6 @@ void physics_panels() object_softbodies_II(ob); object_panel_cloth(ob); object_panel_cloth_II(ob); - object_panel_cloth_III(ob); object_panel_fluidsim(ob); } } From ab7b4bb892d4bd9926dbc381634d97a556dab3e4 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 22 Jan 2008 23:17:10 +0000 Subject: [PATCH 075/101] (hopefully) fixed huge problem with cache/cloth reset. --- source/blender/blenkernel/BKE_cloth.h | 12 +- source/blender/blenkernel/BKE_modifier.h | 2 +- source/blender/blenkernel/intern/cloth.c | 218 +++++++------------- source/blender/blenkernel/intern/modifier.c | 11 +- source/blender/include/butspace.h | 3 +- source/blender/makesdna/DNA_cloth_types.h | 1 - source/blender/src/buttons_object.c | 115 +++++------ source/blender/src/editmesh.c | 3 +- source/blender/src/editobject.c | 3 +- source/blender/src/transform_conversions.c | 3 +- source/blender/src/transform_generics.c | 16 +- source/blender/src/vpaint.c | 3 +- 12 files changed, 163 insertions(+), 227 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index cb52e2f3ca0..11de3092e7c 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -198,10 +198,14 @@ int implicit_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase ///////////////////////////////////////////////// // cloth.c //////////////////////////////////////////////// -void cloth_free_modifier ( ClothModifierData *clmd ); -void cloth_init ( ClothModifierData *clmd ); -void cloth_deform_verts ( struct Object *ob, float framenr, float ( *vertexCos ) [3], int numVerts, void *derivedData, ClothModifierData *clmd ); -void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int totface ); + +// needed for modifier.c +void cloth_free_modifier_extern (ClothModifierData *clmd); +void cloth_free_modifier (Object *ob, ClothModifierData *clmd); +void cloth_init (ClothModifierData *clmd); +void cloth_deform_verts (struct Object *ob, float framenr, float ( *vertexCos ) [3], int numVerts, void *derivedData, ClothModifierData *clmd); + +void cloth_update_normals (ClothVertex *verts, int nVerts, MFace *face, int totface); // needed for collision.c void bvh_update_from_cloth(ClothModifierData *clmd, int moving); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 068190cb6fa..fba30264fea 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -287,7 +287,7 @@ int modifiers_getCageIndex(struct Object *ob, int *lastPossibleCageIndex_r); int modifiers_isSoftbodyEnabled(struct Object *ob); -ClothModifierData * modifiers_isClothEnabled(Object *ob); +int modifiers_isClothEnabled(struct Object *ob); int modifiers_isParticleEnabled(struct Object *ob); struct Object *modifiers_isDeformedByArmature(struct Object *ob); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 1b284d0d35a..2b5937985ae 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -124,7 +124,6 @@ static CM_SOLVER_DEF solvers [] = static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ); static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts, float framenr ); -static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ); int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ); static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ); @@ -165,7 +164,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->coll_parms->friction = 10.0; clmd->coll_parms->loop_count = 1; clmd->coll_parms->epsilon = 0.01f; - clmd->coll_parms->flags = 0; + clmd->coll_parms->flags = CLOTH_COLLISIONSETTINGS_FLAG_ENABLED; /* These defaults are copied from softbody.c's * softbody_calc_forces() function. @@ -572,24 +571,13 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float ( *vertexCos ) [3], int numverts ) { unsigned int i; - unsigned int numedges = -1; - unsigned int numfaces = -1; - MVert *mvert = NULL; - MEdge *medge = NULL; - MFace *mface = NULL; - DerivedMesh *result = NULL, *result2 = NULL; Cloth *cloth = clmd->clothObject; unsigned int framenr = ( float ) G.scene->r.cfra; float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); ListBase *effectors = NULL; - ClothVertex *newframe= NULL, *verts; - Frame *frame = NULL; - LinkNode *search = NULL; + ClothVertex *verts = NULL; float deltaTime = current_time - clmd->sim_parms->sim_time; - clmd->sim_parms->ob = ob; - - // only be active during a specific period: // that's "first frame" and "last frame" on GUI /* @@ -640,56 +628,9 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, clmd->sim_parms->sim_time = current_time; - // check if cloth object was some collision object before and needs freeing now - if ( ! ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) && ( clmd->clothObject != NULL ) && ( clmd->clothObject->old_solver_type == 255 ) ) - { - // temporary set CSIMSETT_FLAG_COLLOBJ flag for proper freeing - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; - cloth_free_modifier ( clmd ); - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_COLLOBJ; - } - - // This is for collisions objects: check special case CSIMSETT_FLAG_COLLOBJ - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) - { - // save next position + time - if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) ) - { - if ( !collobj_from_object ( ob, clmd, dm, vertexCos, framenr ) ) - { - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; - cloth_free_modifier ( clmd ); - return; - } - - if ( clmd->clothObject == NULL ) - return; - - cloth = clmd->clothObject; - } - - // Save old position - clmd->sim_parms->sim_time_old = clmd->sim_parms->sim_time; - clmd->sim_parms->sim_time = current_time; - - verts = cloth->verts; - - for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) - { - // Save the previous position. - VECCOPY ( verts->xold, verts->x ); - VECCOPY ( verts->txold, verts->x ); - - // Get the current position. - VECCOPY ( verts->x, vertexCos[i] ); - Mat4MulVecfl ( ob->obmat, verts->x ); - - // Compute the vertices "velocity". - // (no dt correction here because of float error) - VECSUB ( verts->v, verts->x, verts->xold ); - } - - return; + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_RESET) + { + cloth_free_modifier (ob, clmd); } if ( deltaTime == 1.0f ) @@ -769,10 +710,9 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, } /* frees all */ -void cloth_free_modifier ( ClothModifierData *clmd ) +void cloth_free_modifier ( Object *ob, ClothModifierData *clmd ) { Cloth *cloth = NULL; - Object *ob = clmd->sim_parms->ob; if ( !clmd ) return; @@ -784,8 +724,7 @@ void cloth_free_modifier ( ClothModifierData *clmd ) if ( cloth ) { // free our frame cache, TODO: but get to first position before - if(ob) - cloth_clear_cache ( ob, clmd, 0 ); + cloth_clear_cache ( ob, clmd, 0 ); // If our solver provides a free function, call it if ( cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free ) @@ -834,8 +773,72 @@ void cloth_free_modifier ( ClothModifierData *clmd ) clmd->clothObject = NULL; } } + clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_RESET; } +/* frees all */ +void cloth_free_modifier_extern ( ClothModifierData *clmd ) +{ + Cloth *cloth = NULL; + + if ( !clmd ) + return; + + cloth = clmd->clothObject; + + if ( ! ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT ) ) + { + if ( cloth ) + { + // If our solver provides a free function, call it + if ( cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free ) + { + solvers [cloth->old_solver_type].free ( clmd ); + } + + // Free the verts. + if ( cloth->verts != NULL ) + MEM_freeN ( cloth->verts ); + + cloth->verts = NULL; + cloth->numverts = 0; + + // Free the springs. + if ( cloth->springs != NULL ) + { + LinkNode *search = cloth->springs; + while(search) + { + ClothSpring *spring = search->link; + + MEM_freeN ( spring ); + search = search->next; + } + BLI_linklist_free(cloth->springs, NULL); + + cloth->springs = NULL; + } + + cloth->springs = NULL; + cloth->numsprings = 0; + + // free BVH collision tree + if ( cloth->tree ) + bvh_free ( ( BVH * ) cloth->tree ); + + // we save our faces for collision objects + if ( cloth->mfaces ) + MEM_freeN ( cloth->mfaces ); + /* + if(clmd->clothObject->facemarks) + MEM_freeN(clmd->clothObject->facemarks); + */ + MEM_freeN ( cloth ); + clmd->clothObject = NULL; + } + } + clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_RESET; +} /****************************************************************************** * @@ -933,72 +936,6 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short } } -// only meshes supported at the moment -/* collision objects */ -static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ) -{ - unsigned int i; - MVert *mvert = NULL; - ClothVertex *verts = NULL; - float tnull[3] = {0,0,0}; - - /* If we have a clothObject, free it. */ - if ( clmd->clothObject != NULL ) - cloth_free_modifier ( clmd ); - - /* Allocate a new cloth object. */ - clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" ); - if ( clmd->clothObject ) - { - clmd->clothObject->old_solver_type = 255; - // clmd->clothObject->old_collision_type = 255; - } - else if ( clmd->clothObject == NULL ) - { - modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject." ); - return 0; - } - - switch ( ob->type ) - { - case OB_MESH: - - // mesh input objects need DerivedMesh - if ( !dm ) - return 0; - - cloth_from_mesh ( ob, clmd, dm ); - - if ( clmd->clothObject != NULL ) - { - if ( !dm ) return 0; - if ( !dm->getNumVerts ( dm ) || !dm->getNumFaces ( dm ) ) return 0; - - mvert = dm->getVertArray ( dm ); - verts = clmd->clothObject->verts; - numverts = clmd->clothObject->numverts = dm->getNumVerts ( dm ); - - for ( i = 0; i < numverts; i++, verts++ ) - { - VECCOPY ( verts->x, mvert[i].co ); - Mat4MulVecfl ( ob->obmat, verts->x ); - verts->flags = 0; - VECCOPY ( verts->xold, verts->x ); - VECCOPY ( verts->txold, verts->x ); - VECCOPY ( verts->tx, verts->x ); - VecMulf ( verts->v, 0.0f ); - verts->impulse_count = 0; - VECCOPY ( verts->impulse, tnull ); - } - clmd->clothObject->tree = bvh_build_from_cloth ( clmd,clmd->coll_parms->epsilon ); - - } - - return 1; - default: return 0; // TODO - we do not support changing meshes - } -} - /* helper function to get proper spring length when object is rescaled @@ -1024,7 +961,7 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh /* If we have a clothObject, free it. */ if ( clmd->clothObject != NULL ) - cloth_free_modifier ( clmd ); + cloth_free_modifier ( ob, clmd ); /* Allocate a new cloth object. */ clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" ); @@ -1038,8 +975,6 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject." ); return 0; } - - clmd->sim_parms->ob = ob; switch ( ob->type ) { @@ -1085,6 +1020,7 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh if ( !cloth_build_springs ( clmd->clothObject, dm ) ) { + cloth_free_modifier ( ob, clmd ); modifier_setError ( & ( clmd->modifier ), "Can't build springs." ); return 0; } @@ -1130,7 +1066,7 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh * clmd->clothObject->verts = MEM_callocN ( sizeof ( ClothVertex ) * clmd->clothObject->numverts, "clothVertex" ); if ( clmd->clothObject->verts == NULL ) { - cloth_free_modifier ( clmd ); + cloth_free_modifier ( ob, clmd ); modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." ); return; } @@ -1140,7 +1076,7 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh * clmd->clothObject->mfaces = MEM_callocN ( sizeof ( MFace ) * clmd->clothObject->numfaces, "clothMFaces" ); if ( clmd->clothObject->mfaces == NULL ) { - cloth_free_modifier ( clmd ); + cloth_free_modifier ( ob, clmd ); modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->mfaces." ); return; } @@ -1191,7 +1127,7 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) { ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0; - unsigned int i = 0, j = 0, akku_count; + unsigned int i = 0; unsigned int numverts = dm->getNumVerts ( dm ); unsigned int numedges = dm->getNumEdges ( dm ); unsigned int numfaces = dm->getNumFaces ( dm ); @@ -1201,7 +1137,7 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) LinkNode **edgelist = NULL; EdgeHash *edgehash = NULL; LinkNode *search = NULL, *search2 = NULL; - float temp[3], akku, min, max; + float temp[3]; LinkNode *node = NULL, *node2 = NULL; // error handling diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 9273b6bf9ab..40b01fa3322 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4991,6 +4991,7 @@ static void clothModifier_updateDepgraph( Base *base; + /* TODO: this belongs to collision modifier */ if(clmd) { for(base = G.scene->base.first; base; base= base->next) @@ -5034,11 +5035,13 @@ static int clothModifier_dependsOnTime(ModifierData *md) static void clothModifier_freeData(ModifierData *md) { ClothModifierData *clmd = (ClothModifierData*) md; + Object *ob = NULL; + ClothModifierData *clmd2 = NULL; if (clmd) { - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; - cloth_free_modifier (clmd); + + cloth_free_modifier_extern (clmd); MEM_freeN(clmd->sim_parms); MEM_freeN(clmd->coll_parms); @@ -7290,11 +7293,11 @@ int modifiers_isSoftbodyEnabled(Object *ob) return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -ClothModifierData * modifiers_isClothEnabled(Object *ob) +int modifiers_isClothEnabled(Object *ob) { ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); - return (ClothModifierData *)md; + return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } int modifiers_isParticleEnabled(Object *ob) diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index c925a0689ef..a7759f799ba 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -295,8 +295,7 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_CLOTH_CLEARCACHEALL 1480 #define B_CLOTH_CLEARCACHEFRAME 1481 #define B_CLOTH_CHANGEPREROLL 1482 -#define B_CLOTH_DEL_VG 1483 -#define B_CLOTH_RENEW 1484 +#define B_CLOTH_RENEW 1483 /* *********************** */ #define B_WORLDBUTS 1600 diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index ee4a0130dbf..65b8f4169ff 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -76,7 +76,6 @@ typedef struct SimulationSettings 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 */ - struct Object *ob; } SimulationSettings; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 7f62c5b3308..4ac49a93119 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2287,6 +2287,56 @@ 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) + { + CFRA= 1; + update_for_newframe_muted(); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + cloth_clear_cache(ob, clmd, 2); + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); + } + } + break; + case B_CLOTH_CLEARCACHEFRAME: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + cloth_clear_cache(ob, clmd, MAX2(2.0,G.scene->r.cfra + 1.0)); + allqueue(REDRAWBUTSOBJECT, 0); + } + } + break; + case B_CLOTH_CHANGEPREROLL: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + if(clmd->sim_parms->cache) + { + CFRA= 1; + update_for_newframe_muted(); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + 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; + } + } + break; default: if(event>=B_SELEFFECT && eventr.cfra + 1.0)); - allqueue(REDRAWBUTSOBJECT, 0); - } - } - break; - case B_CLOTH_CHANGEPREROLL: - { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - if(clmd) - { - if(clmd->sim_parms->cache) - { - CFRA= 1; - update_for_newframe_muted(); - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - allqueue(REDRAWBUTSOBJECT, 0); - allqueue(REDRAWVIEW3D, 0); - } - } - } - break; - case B_CLOTH_DEL_VG: - { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - if(clmd) - { - clmd->sim_parms->vgroup_mass = 0; - do_object_panels(B_CLOTH_RENEW); - } - allqueue(REDRAWBUTSOBJECT, 0); - } - break; - case B_CLOTH_RENEW: - { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - if(clmd) - { - do_object_panels(B_CLOTH_CLEARCACHEALL); - cloth_free_modifier (clmd); - } - } - break; default: if(event>=B_SELEFFECT && eventsim_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); diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index dc16caa1f59..8bd397b0da4 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -1329,7 +1329,8 @@ void load_editMesh(void) for(base= G.scene->base.first; base; base= base->next) { if(base->object->data==me) { if(modifiers_isClothEnabled(base->object)) { - cloth_free_modifier(modifiers_isClothEnabled(base->object)); + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(base->object, eModifierType_Cloth); + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; } base->object->softflag |= OB_SB_REDO; diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 7b3a1a24188..cb1ed4c3e5a 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -1761,7 +1761,8 @@ void exit_editmode(int flag) /* freedata==0 at render, 1= freedata, 2= do undo b } if(modifiers_isClothEnabled(ob)) { - cloth_free_modifier(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) diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 9160bf2f563..882a16bb9ce 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -3405,7 +3405,8 @@ void special_aftertrans_update(TransInfo *t) if (modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO; else if(modifiers_isClothEnabled(ob)) { - cloth_free_modifier(modifiers_isClothEnabled(ob)); + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; } /* Set autokey if necessary */ diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index a79b1d4c4ea..1f6d8ecf7af 100644 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -468,14 +468,13 @@ void recalcData(TransInfo *t) /* bah, softbody exception... recalcdata doesnt reset */ for(base= FIRSTBASE; base; base= base->next) { if(base->object->recalc & OB_RECALC_DATA) - { - ClothModifierData *clmd = NULL; - + { if(modifiers_isSoftbodyEnabled(base->object)) { base->object->softflag |= OB_SB_REDO; } - else if((clmd = (ClothModifierData *)modifiers_isClothEnabled(ob))) { - cloth_free_modifier(clmd); + else if(modifiers_isClothEnabled(base->object)) { + ClothModifierData *clmd = (ClothModifierData *) modifiers_findByType(base->object, eModifierType_Cloth); + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; } } @@ -516,13 +515,12 @@ void recalcData(TransInfo *t) /* softbody & cloth exception */ if(ob->recalc & OB_RECALC_DATA) { - ClothModifierData *clmd = NULL; - if(modifiers_isSoftbodyEnabled(ob)) { ob->softflag |= OB_SB_REDO; } - else if((clmd = (ClothModifierData *)modifiers_isClothEnabled(ob))) { - cloth_free_modifier(clmd); + else if(modifiers_isClothEnabled(ob)) { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; } } diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c index 2e4ecd95709..dec15f96b8a 100644 --- a/source/blender/src/vpaint.c +++ b/source/blender/src/vpaint.c @@ -1351,7 +1351,8 @@ void weight_paint(void) // same goes for cloth if(modifiers_isClothEnabled(ob)) { - cloth_free_modifier((ClothModifierData *)modifiers_isClothEnabled(ob)); + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; } BIF_undo_push("Weight Paint"); From 6490b2b29add882065637ea8701946940bc02d2d Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 23 Jan 2008 13:24:44 +0000 Subject: [PATCH 076/101] Made GUI even more intuitive with explanations why something is not available etc., fixed some uninitialized variable. NEW: show pinned verts as big red balls in 3dview - please tell me how to improve that visual feedback :) --- source/blender/blenkernel/BKE_cloth.h | 5 ++- source/blender/blenkernel/intern/cloth.c | 45 ++++++++++++-------- source/blender/makesdna/DNA_cloth_types.h | 2 +- source/blender/src/buttons_object.c | 46 ++++++++++++-------- source/blender/src/drawobject.c | 51 +++++++++++++++++++++++ 5 files changed, 110 insertions(+), 39 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 11de3092e7c..4e704098ebd 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -80,6 +80,7 @@ typedef struct ClothVertex 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 */ } ClothVertex; @@ -156,8 +157,8 @@ typedef enum } CLOTH_SPRINGS_FLAGS; /* Bits to or into the ClothVertex.flags. */ -#define CVERT_FLAG_PINNED 1 -#define CVERT_FLAG_COLLISION 2 +#define CLOTH_VERT_FLAG_PINNED 1 +#define CLOTH_VERT_FLAG_COLLISION 2 // needed for buttons_object.c diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 2b5937985ae..fb3617e16f0 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -124,7 +124,7 @@ static CM_SOLVER_DEF solvers [] = static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ); static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts, float framenr ); -int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ); +int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ); @@ -502,12 +502,17 @@ static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr Cloth *cloth = clmd->clothObject; if(!cloth) + { return; + } stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); fp = BKE_ptcache_id_fopen((ID *)ob, 'w', framenr, stack_index); - if(!fp) return; + if(!fp) + { + return; + } for(a = 0; a < cloth->numverts; a++) { @@ -554,10 +559,10 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) } fclose(fp); + + if(clmd->sim_parms->solver_type == 0) + implicit_set_positions(clmd); } - - if(clmd->sim_parms->solver_type == 0) - implicit_set_positions(clmd); return ret; } @@ -622,6 +627,8 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, } } */ + + // printf("ct: %f, st: %f, r.cfra: %f, dt: %f\n", current_time, clmd->sim_parms->sim_time, ( float ) G.scene->r.cfra, deltaTime); // unused in the moment, calculated seperately in implicit.c clmd->sim_parms->dt = 1.0f / clmd->sim_parms->stepsPerFrame; @@ -681,11 +688,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, cloth_write_cache(ob, clmd, framenr); } - else // just retrieve the cached frame - { - cloth_read_cache(ob, clmd, framenr); - } - + // Copy the result back to the object. cloth_to_object ( ob, clmd, vertexCos, numverts ); @@ -694,12 +697,14 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, } } - else if ( ( deltaTime <= 0.0f ) || ( deltaTime > 1.0f ) ) + else { if ( clmd->clothObject != NULL ) { if(cloth_read_cache(ob, clmd, framenr)) + { cloth_to_object ( ob, clmd, vertexCos, numverts ); + } } else { @@ -866,7 +871,7 @@ static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vert for ( i = 0; i < numverts; i++, verts++ ) { VECCOPY ( vertexCos[i], verts->x ); - Mat4MulVecfl ( ob->imat, vertexCos[i] ); /* softbody is in global coords */ + Mat4MulVecfl ( ob->imat, vertexCos[i] ); /* cloth is in global coords */ } } } @@ -921,9 +926,9 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short verts->goal = ( float ) pow ( verts->goal , 4.0f ); - if ( dvert->dw [j].weight >=SOFTGOALSNAP ) + if ( verts->goal >=SOFTGOALSNAP ) { - verts->flags |= CVERT_FLAG_PINNED; + verts->flags |= CLOTH_VERT_FLAG_PINNED; } // TODO enable mass painting here, for the moment i let "goals" go first @@ -1018,7 +1023,7 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh VECCOPY ( verts->impulse, tnull ); } - if ( !cloth_build_springs ( clmd->clothObject, dm ) ) + if ( !cloth_build_springs ( clmd, dm ) ) { cloth_free_modifier ( ob, clmd ); modifier_setError ( & ( clmd->modifier ), "Can't build springs." ); @@ -1042,11 +1047,11 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh case OB_LATTICE: printf ( "Not supported: OB_LATTICE\n" ); // lattice_to_softbody(ob); - return 1; + return 0; case OB_CURVE: case OB_SURF: printf ( "Not supported: OB_SURF| OB_CURVE\n" ); - return 1; + return 0; default: return 0; // TODO - we do not support changing meshes } @@ -1123,8 +1128,9 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in return 0; } -int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) +int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) { + Cloth *cloth = clmd->clothObject; ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0; unsigned int i = 0; @@ -1169,6 +1175,7 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) spring->kl = medge[i].v2; VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); + clmd->coll_parms->avg_spring_len += spring->restlen; spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; spring->flags = 0; struct_springs++; @@ -1181,6 +1188,8 @@ int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) } } + clmd->coll_parms->avg_spring_len /= struct_springs; + // shear springs for ( i = 0; i < numfaces; i++ ) { diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 65b8f4169ff..9c5e3a1b9f2 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -89,7 +89,7 @@ typedef struct CollisionSettings 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 */ - int pad; + float avg_spring_len; /* for selfcollision */ } CollisionSettings; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 4ac49a93119..8e691c30f94 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -4937,6 +4937,8 @@ static void object_panel_cloth(Object *ob) 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"); @@ -4977,12 +4979,10 @@ static void object_panel_cloth(Object *ob) /* GOAL STUFF */ uiBlockBeginAlign(block); - if(BLI_countlist (&ob->defbase) > 0) - { - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "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) + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "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) { @@ -5013,13 +5013,9 @@ static void object_panel_cloth(Object *ob) MEM_freeN (clvg1); MEM_freeN (clvg2); } - else - { - uiDefButS(block, TOG, B_CLOTH_RENEW, "W", 140,70,20,20, &clmd->sim_parms->vgroup_mass, 0, 1, 0, 0, "Use control point weight values"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); - } uiDefButF(block, NUM, B_CLOTH_RENEW, "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"); @@ -5027,6 +5023,12 @@ static void object_panel_cloth(Object *ob) 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); /* @@ -5078,18 +5080,26 @@ static void object_panel_cloth_II(Object *ob) sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length); */ - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,120,300,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); - - if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) + if (!G.relbase_valid) { - 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, 0, 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, 0, 0, "Free cloth cache starting from next frame"); - uiDefBut(block, LABEL, 0, " ", 10,80,300,20, NULL, 0.0, 0, 0, 0, ""); + 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 { - uiDefBut(block, LABEL, 0, " ", 10,100,300,40, NULL, 0.0, 0, 0, 0, ""); + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,120,300,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); + + if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) + { + 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, ""); + } + else + { + uiDefBut(block, LABEL, 0, " ", 10,100,300,40, NULL, 0.0, 0, 0, 0, ""); + } } /* diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index c8d2e3dad90..0069ac0f15e 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -5399,6 +5399,57 @@ void draw_object(Base *base, int flag) if(col) cpack(col); glDepthMask(GL_TRUE); } + + /* code for drawing pinned cloth verts */ + if(modifiers_isClothEnabled(ob)) + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + Cloth *cloth = clmd->clothObject; + ClothVertex *verts; + float col[3], point[3]; + col[0] = 0.53; + col[1] = 0.04; + col[2] = 0.0; + glColor3fv(col); + + /* inverse matrix is not uptodate... */ + Mat4Invert ( ob->imat, ob->obmat ); + + if(cloth) + { + verts = cloth->verts; + + for(i = 0; i < cloth->numverts; i++) + { + if(verts[i].flags & CLOTH_VERT_FLAG_PINNED) + { + float size[3], cent[3]; + GLUquadricObj *qobj = gluNewQuadric(); + + gluQuadricDrawStyle(qobj, GLU_FILL); + + size[0]= clmd->coll_parms->avg_spring_len / 3.0; + size[1]= clmd->coll_parms->avg_spring_len / 3.0; + size[2]= clmd->coll_parms->avg_spring_len / 3.0; + + VECCOPY ( point, verts[i].x ); + Mat4MulVecfl ( ob->imat, point ); + + cent[0]= point[0]; + cent[1]= point[1]; + cent[2]= point[2]; + + glPushMatrix(); + glTranslatef(cent[0], cent[1], cent[2]); + glScalef(size[0], size[1], size[2]); + gluSphere(qobj, 1.0, 8, 5); + glPopMatrix(); + + gluDeleteQuadric(qobj); + } + } + } + } { bConstraint *con; From 4b1b749130258edd5a1bf0489d07e6e4138f3a9c Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 23 Jan 2008 15:30:23 +0000 Subject: [PATCH 077/101] Enabled first + last simulation frame, hopefully fixed some cache problems, changed 3d view ball to a pushpin layout -feel free to enhance in drawobject.c line 5440 --- source/blender/blenkernel/intern/cloth.c | 147 ++++++++++------------ source/blender/makesdna/DNA_cloth_types.h | 2 + source/blender/src/buttons_object.c | 4 +- source/blender/src/drawobject.c | 75 ++++++----- 4 files changed, 117 insertions(+), 111 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index fb3617e16f0..4a0252b7fd7 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -160,6 +160,8 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->firstframe = 1; clmd->sim_parms->lastframe = 250; clmd->sim_parms->vgroup_mass = 0; + clmd->sim_parms->lastcachedframe = 0; + clmd->coll_parms->self_friction = 5.0; clmd->coll_parms->friction = 10.0; clmd->coll_parms->loop_count = 1; @@ -483,46 +485,6 @@ DerivedMesh *CDDM_create_tearing ( ClothModifierData *clmd, DerivedMesh *dm ) int modifiers_indexInObject(Object *ob, ModifierData *md_seek); -void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) -{ - int stack_index = -1; - - if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) - { - stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); - - BKE_ptcache_id_clear((ID *)ob, PTCACHE_CLEAR_AFTER, framenr, stack_index); - } -} -static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) -{ - FILE *fp = NULL; - int stack_index = -1; - unsigned int a; - Cloth *cloth = clmd->clothObject; - - if(!cloth) - { - return; - } - - stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); - - fp = BKE_ptcache_id_fopen((ID *)ob, 'w', framenr, stack_index); - if(!fp) - { - return; - } - - for(a = 0; a < cloth->numverts; a++) - { - fwrite(&cloth->verts[a].x, sizeof(float),3,fp); - fwrite(&cloth->verts[a].xconst, sizeof(float),3,fp); - fwrite(&cloth->verts[a].v, sizeof(float),3,fp); - } - - fclose(fp); -} static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) { FILE *fp = NULL; @@ -567,6 +529,55 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) return ret; } +void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) +{ + int stack_index = -1; + + if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) + { + stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); + + BKE_ptcache_id_clear((ID *)ob, PTCACHE_CLEAR_AFTER, framenr, stack_index); + } + + if(framenr>0) + { + cloth_read_cache(ob, clmd, framenr); + } +} +static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) +{ + FILE *fp = NULL; + int stack_index = -1; + unsigned int a; + Cloth *cloth = clmd->clothObject; + + if(!cloth) + { + return; + } + + stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); + + fp = BKE_ptcache_id_fopen((ID *)ob, 'w', framenr, stack_index); + if(!fp) + { + return; + } + + for(a = 0; a < cloth->numverts; a++) + { + fwrite(&cloth->verts[a].x, sizeof(float),3,fp); + fwrite(&cloth->verts[a].xconst, sizeof(float),3,fp); + fwrite(&cloth->verts[a].v, sizeof(float),3,fp); + } + + clmd->sim_parms->lastcachedframe = MAX2(clmd->sim_parms->lastcachedframe, framenr); + + fclose(fp); +} + + /** * cloth_deform_verts - simulates one step, framenr is in frames. @@ -585,48 +596,24 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, // only be active during a specific period: // that's "first frame" and "last frame" on GUI - /* - if ( ! ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) ) + if ( current_time < clmd->sim_parms->firstframe ) { - if ( clmd->clothObject ) - { - if ( clmd->sim_parms->cache ) - { - if ( current_time < clmd->sim_parms->firstframe ) - { - int frametime = cloth_cache_first_frame ( clmd ); - if ( cloth_cache_search_frame ( clmd, frametime ) ) - { - cloth_cache_get_frame ( clmd, frametime ); - cloth_to_object ( ob, clmd, vertexCos, numverts ); - } - return; - } - else if ( current_time > clmd->sim_parms->lastframe ) - { - int frametime = cloth_cache_last_frame ( clmd ); - if ( cloth_cache_search_frame ( clmd, frametime ) ) - { - cloth_cache_get_frame ( clmd, frametime ); - cloth_to_object ( ob, clmd, vertexCos, numverts ); - } - return; - } - else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed - { - if ( cloth_cache_search_frame ( clmd, framenr ) ) - { - cloth_cache_get_frame ( clmd, framenr ); - cloth_to_object ( ob, clmd, vertexCos, numverts ); - } - clmd->sim_parms->sim_time = current_time; - return; - } - } - - } + return; + } + else if ( current_time > clmd->sim_parms->lastframe ) + { + int stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); + + if(BKE_ptcache_id_exist((ID *)ob, clmd->sim_parms->lastcachedframe, stack_index)) + { + if(cloth_read_cache(ob, clmd, framenr)) + { + // Copy the result back to the object. + cloth_to_object ( ob, clmd, vertexCos, numverts ); + } + } + return; } - */ // printf("ct: %f, st: %f, r.cfra: %f, dt: %f\n", current_time, clmd->sim_parms->sim_time, ( float ) G.scene->r.cfra, deltaTime); diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 9c5e3a1b9f2..661ad9547d5 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -76,6 +76,8 @@ typedef struct SimulationSettings 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 pad3; } SimulationSettings; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 8e691c30f94..1d7a1972d36 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2295,7 +2295,7 @@ void do_object_panels(unsigned short event) CFRA= 1; update_for_newframe_muted(); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - cloth_clear_cache(ob, clmd, 2); + cloth_clear_cache(ob, clmd, 1); allqueue(REDRAWBUTSOBJECT, 0); allqueue(REDRAWVIEW3D, 0); } @@ -2306,7 +2306,7 @@ void do_object_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - cloth_clear_cache(ob, clmd, MAX2(2.0,G.scene->r.cfra + 1.0)); + cloth_clear_cache(ob, clmd, MAX2(1.0,G.scene->r.cfra + 1.0)); allqueue(REDRAWBUTSOBJECT, 0); } } diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 0069ac0f15e..a23ee559570 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -5406,7 +5406,7 @@ void draw_object(Base *base, int flag) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); Cloth *cloth = clmd->clothObject; ClothVertex *verts; - float col[3], point[3]; + float col[3]; col[0] = 0.53; col[1] = 0.04; col[2] = 0.0; @@ -5417,35 +5417,52 @@ void draw_object(Base *base, int flag) if(cloth) { - verts = cloth->verts; - - for(i = 0; i < cloth->numverts; i++) - { - if(verts[i].flags & CLOTH_VERT_FLAG_PINNED) + /* don't paint anything if cloth has RESET status */ + if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_RESET)) + { + verts = cloth->verts; + + for(i = 0; i < cloth->numverts; i++) { - float size[3], cent[3]; - GLUquadricObj *qobj = gluNewQuadric(); - - gluQuadricDrawStyle(qobj, GLU_FILL); - - size[0]= clmd->coll_parms->avg_spring_len / 3.0; - size[1]= clmd->coll_parms->avg_spring_len / 3.0; - size[2]= clmd->coll_parms->avg_spring_len / 3.0; - - VECCOPY ( point, verts[i].x ); - Mat4MulVecfl ( ob->imat, point ); - - cent[0]= point[0]; - cent[1]= point[1]; - cent[2]= point[2]; - - glPushMatrix(); - glTranslatef(cent[0], cent[1], cent[2]); - glScalef(size[0], size[1], size[2]); - gluSphere(qobj, 1.0, 8, 5); - glPopMatrix(); - - gluDeleteQuadric(qobj); + if(verts[i].flags & CLOTH_VERT_FLAG_PINNED) + { + float size[3], cent[3]; + GLUquadricObj *qobj = gluNewQuadric(); + + gluQuadricDrawStyle(qobj, GLU_FILL); + + size[0]= clmd->coll_parms->avg_spring_len / 3.0; + size[1]= clmd->coll_parms->avg_spring_len / 3.0; + size[2]= clmd->coll_parms->avg_spring_len / 3.0; + + VECCOPY ( cent, verts[i].x ); + Mat4MulVecfl ( ob->imat, cent ); + + glPushMatrix(); + glTranslatef(cent[0], cent[1], cent[2]); + glScalef(size[0], size[1], size[2]); + + // gluSphere(qobj, 1.0, 8, 5); + glTranslatef(0, 0, 1.0); + gluDisk(qobj, 0, 0.4, 8, 5); + gluCylinder(qobj, 0.4, 0.4, 1.0, 8, 5); + + glTranslatef(0, 0, 1.0); + gluDisk(qobj, 0, 0.4, 8, 5); + + glTranslatef(0, 0, -2.0); + /* + col[0] = 0.53; + col[1] = 0.54; + col[2] = 0.0; + glColor3fv(col); + */ + gluCylinder(qobj, 0.0, 0.2, 1.0, 8, 5); + + glPopMatrix(); + + gluDeleteQuadric(qobj); + } } } } From 576a7f623c99a1df71bf4135dd44930c99d63150 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 23 Jan 2008 17:58:09 +0000 Subject: [PATCH 078/101] fix for collision modifier not reseted after first run + made the pushpin more like one --- source/blender/blenkernel/intern/cloth.c | 6 +++ source/blender/blenkernel/intern/modifier.c | 6 +++ source/blender/src/drawobject.c | 42 +++++++++++++++++---- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 4a0252b7fd7..df57440996a 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -621,6 +621,12 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, clmd->sim_parms->dt = 1.0f / clmd->sim_parms->stepsPerFrame; clmd->sim_parms->sim_time = current_time; + + /* check if cache is active / if file is already saved */ + if ((!G.relbase_valid) && ( deltaTime != 1.0f )) + { + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; + } if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_RESET) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 40b01fa3322..3ea4d4fb584 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5130,6 +5130,8 @@ static void collisionModifier_deformVerts( 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 ); @@ -5194,6 +5196,10 @@ static void collisionModifier_deformVerts( collmd->time = current_time; } + else + { + collmd->time = current_time; + } } if(dm) diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index a23ee559570..6696fd3cfe3 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -5421,7 +5421,13 @@ void draw_object(Base *base, int flag) if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_RESET)) { verts = cloth->verts; - + /* + // this makes the screen pink + glEnable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + glShadeModel(GL_SMOOTH); + */ + for(i = 0; i < cloth->numverts; i++) { if(verts[i].flags & CLOTH_VERT_FLAG_PINNED) @@ -5443,27 +5449,49 @@ void draw_object(Base *base, int flag) glScalef(size[0], size[1], size[2]); // gluSphere(qobj, 1.0, 8, 5); - glTranslatef(0, 0, 1.0); - gluDisk(qobj, 0, 0.4, 8, 5); - gluCylinder(qobj, 0.4, 0.4, 1.0, 8, 5); glTranslatef(0, 0, 1.0); - gluDisk(qobj, 0, 0.4, 8, 5); + gluDisk(qobj, 0, 0.25, 8, 5); - glTranslatef(0, 0, -2.0); + glTranslatef(0, 0, -1.0); + + glTranslatef(0, 0, 0.875); + gluCylinder(qobj, 0.15, 0.25, 0.125, 8, 5); + + glTranslatef(0, 0, -0.25); + gluCylinder(qobj, 0.15, 0.15, 0.25, 8, 5); + + glTranslatef(0, 0, -0.125); + gluCylinder(qobj, 0.25, 0.15, 0.125, 8, 5); + + // gluDisk(qobj, 0, 0.5, 8, 5); + + /* + glTranslatef(0, 0, 1.0); + gluDisk(qobj, 0, 0.4, 8, 5); + */ /* col[0] = 0.53; col[1] = 0.54; col[2] = 0.0; glColor3fv(col); */ - gluCylinder(qobj, 0.0, 0.2, 1.0, 8, 5); + glTranslatef(0, 0, -0.5); + gluCylinder(qobj, 0.0, 0.05, 0.5, 8, 5); + + glTranslatef(0, 0, 0.5); + gluDisk(qobj, 0, 0.25, 8, 5); glPopMatrix(); gluDeleteQuadric(qobj); } } + /* + glShadeModel(GL_FLAT); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_LIGHTING); + */ } } } From c5dc7c7b024b0136e385aabf846c086428daf4c0 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 24 Jan 2008 10:43:12 +0000 Subject: [PATCH 079/101] New: Editable cache. Fixed: Don't clear cache on e.g. lamp moving. Changed: Switched to another modifier type to be more flexible (allows tearing later) --- source/blender/blenkernel/BKE_cloth.h | 16 +- source/blender/blenkernel/intern/cloth.c | 315 ++++++++++---------- source/blender/blenkernel/intern/implicit.c | 45 +-- source/blender/blenkernel/intern/modifier.c | 43 ++- source/blender/src/buttons_object.c | 2 +- source/blender/src/editmesh.c | 105 ++++++- source/blender/src/transform_conversions.c | 2 +- source/blender/src/vpaint.c | 1 + 8 files changed, 305 insertions(+), 224 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 4e704098ebd..e3fdb9e0f25 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -160,16 +160,6 @@ typedef enum #define CLOTH_VERT_FLAG_PINNED 1 #define CLOTH_VERT_FLAG_COLLISION 2 - -// needed for buttons_object.c -void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr); - -// needed for cloth.c -void implicit_set_positions ( ClothModifierData *clmd ); - -// from cloth.c, needed for modifier.c -void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float ( *vertexCos ) [3], int numverts ); - typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, CollisionModifierData *collmd, CollisionTree *tree1, CollisionTree *tree2 ); @@ -193,6 +183,7 @@ int bvh_traverse ( ClothModifierData * clmd, CollisionModifierData * collmd, Col 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 ); //////////////////////////////////////////////// @@ -204,13 +195,16 @@ int implicit_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase void cloth_free_modifier_extern (ClothModifierData *clmd); void cloth_free_modifier (Object *ob, ClothModifierData *clmd); void cloth_init (ClothModifierData *clmd); -void cloth_deform_verts (struct Object *ob, float framenr, float ( *vertexCos ) [3], int numVerts, void *derivedData, ClothModifierData *clmd); +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); + //////////////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index df57440996a..f22fd28d96e 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -121,9 +121,9 @@ static CM_SOLVER_DEF solvers [] = /* ********** cloth engine ******* */ /* Prototypes for internal functions. */ -static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ); +static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm); static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); -static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts, float framenr ); +static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr); int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ); @@ -545,7 +545,7 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) cloth_read_cache(ob, clmd, framenr); } } -static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) +void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) { FILE *fp = NULL; int stack_index = -1; @@ -579,26 +579,46 @@ static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr -/** -* cloth_deform_verts - simulates one step, framenr is in frames. -* -**/ -void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, - float ( *vertexCos ) [3], int numverts ) +/************************************************ + * clothModifier_do - main simulation function +************************************************/ +DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) + { unsigned int i; Cloth *cloth = clmd->clothObject; unsigned int framenr = ( float ) G.scene->r.cfra; float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); - ListBase *effectors = NULL; + ListBase *effectors = NULL; ClothVertex *verts = NULL; float deltaTime = current_time - clmd->sim_parms->sim_time; + unsigned int numverts = -1; + unsigned int numedges = -1; + unsigned int numfaces = -1; + MVert *mvert = NULL; + MEdge *medge = NULL; + MFace *mface = NULL; + DerivedMesh *result = NULL; + + result = CDDM_copy(dm); + + if(!result) + { + return dm; + } + + numverts = result->getNumVerts(result); + numedges = result->getNumEdges(result); + numfaces = result->getNumFaces(result); + mvert = CDDM_get_verts(result); + medge = CDDM_get_edges(result); + mface = CDDM_get_faces(result); // only be active during a specific period: // that's "first frame" and "last frame" on GUI if ( current_time < clmd->sim_parms->firstframe ) { - return; + return result; } else if ( current_time > clmd->sim_parms->lastframe ) { @@ -609,10 +629,10 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, if(cloth_read_cache(ob, clmd, framenr)) { // Copy the result back to the object. - cloth_to_object ( ob, clmd, vertexCos, numverts ); + cloth_to_object (ob, clmd, result); } } - return; + return result; } // printf("ct: %f, st: %f, r.cfra: %f, dt: %f\n", current_time, clmd->sim_parms->sim_time, ( float ) G.scene->r.cfra, deltaTime); @@ -639,11 +659,11 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, { cloth_clear_cache(ob, clmd, 0); - if ( !cloth_from_object ( ob, clmd, dm, vertexCos, numverts, framenr ) ) - return; + if ( !cloth_from_object ( ob, clmd, result, framenr ) ) + return result; if ( clmd->clothObject == NULL ) - return; + return result; cloth = clmd->clothObject; } @@ -665,7 +685,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, VECCOPY ( verts->txold, verts->x ); // Get the current position. - VECCOPY ( verts->xconst, vertexCos[i] ); + VECCOPY ( verts->xconst, mvert[i].co ); Mat4MulVecfl ( ob->obmat, verts->xconst ); } @@ -679,14 +699,10 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, // printf ( "Cloth simulation time: %f\n", ( float ) tval() ); cloth_write_cache(ob, clmd, framenr); - } // Copy the result back to the object. - cloth_to_object ( ob, clmd, vertexCos, numverts ); - - // bvh_free(clmd->clothObject->tree); - // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms->epsilon); + cloth_to_object (ob, clmd, result); } } @@ -696,7 +712,7 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, { if(cloth_read_cache(ob, clmd, framenr)) { - cloth_to_object ( ob, clmd, vertexCos, numverts ); + cloth_to_object (ob, clmd, result); } } else @@ -704,6 +720,8 @@ void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, cloth_clear_cache(ob, clmd, 0); } } + + return result; } @@ -783,59 +801,55 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd ) return; cloth = clmd->clothObject; - - if ( ! ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT ) ) - { - if ( cloth ) - { - // If our solver provides a free function, call it - if ( cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free ) - { - solvers [cloth->old_solver_type].free ( clmd ); - } - - // Free the verts. - if ( cloth->verts != NULL ) - MEM_freeN ( cloth->verts ); - - cloth->verts = NULL; - cloth->numverts = 0; - - // Free the springs. - if ( cloth->springs != NULL ) - { - LinkNode *search = cloth->springs; - while(search) - { - ClothSpring *spring = search->link; - - MEM_freeN ( spring ); - search = search->next; - } - BLI_linklist_free(cloth->springs, NULL); - - cloth->springs = NULL; - } - - cloth->springs = NULL; - cloth->numsprings = 0; - - // free BVH collision tree - if ( cloth->tree ) - bvh_free ( ( BVH * ) cloth->tree ); - - // we save our faces for collision objects - if ( cloth->mfaces ) - MEM_freeN ( cloth->mfaces ); - /* - if(clmd->clothObject->facemarks) - MEM_freeN(clmd->clothObject->facemarks); - */ - MEM_freeN ( cloth ); - clmd->clothObject = NULL; + + if ( cloth ) + { + // If our solver provides a free function, call it + if ( cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free ) + { + solvers [cloth->old_solver_type].free ( clmd ); } + + // Free the verts. + if ( cloth->verts != NULL ) + MEM_freeN ( cloth->verts ); + + cloth->verts = NULL; + cloth->numverts = 0; + + // Free the springs. + if ( cloth->springs != NULL ) + { + LinkNode *search = cloth->springs; + while(search) + { + ClothSpring *spring = search->link; + + MEM_freeN ( spring ); + search = search->next; + } + BLI_linklist_free(cloth->springs, NULL); + + cloth->springs = NULL; + } + + cloth->springs = NULL; + cloth->numsprings = 0; + + // free BVH collision tree + if ( cloth->tree ) + bvh_free ( ( BVH * ) cloth->tree ); + + // we save our faces for collision objects + if ( cloth->mfaces ) + MEM_freeN ( cloth->mfaces ); + /* + if(clmd->clothObject->facemarks) + MEM_freeN(clmd->clothObject->facemarks); + */ + MEM_freeN ( cloth ); + clmd->clothObject = NULL; } - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_RESET; } /****************************************************************************** @@ -847,24 +861,25 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd ) /** * cloth_to_object - copies the deformed vertices to the object. * -* This function is a modified version of the softbody.c:softbody_to_object() function. **/ -static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ) +static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm) { - ClothVertex *verts = NULL; unsigned int i = 0; + MVert *mvert = NULL; + unsigned int numverts; + Cloth *cloth = clmd->clothObject; - if ( clmd->clothObject ) - { - verts = clmd->clothObject->verts; - + if (clmd->clothObject) { /* inverse matrix is not uptodate... */ - Mat4Invert ( ob->imat, ob->obmat ); + Mat4Invert (ob->imat, ob->obmat); - for ( i = 0; i < numverts; i++, verts++ ) + mvert = CDDM_get_verts(dm); + numverts = dm->getNumVerts(dm); + + for (i = 0; i < numverts; i++) { - VECCOPY ( vertexCos[i], verts->x ); - Mat4MulVecfl ( ob->imat, vertexCos[i] ); /* cloth is in global coords */ + VECCOPY (mvert[i].co, cloth->verts[i].x); + Mat4MulVecfl (ob->imat, mvert[i].co); /* cloth is in global coords */ } } } @@ -948,20 +963,18 @@ float cloth_globallen ( float *v1,float *v2,Object *ob ) return VecLenf ( p1,p2 ); } -// only meshes supported at the moment -static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts, float framenr ) +static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr) { unsigned int i = 0; - // dm->getNumVerts(dm); - MVert *mvert = NULL; // CDDM_get_verts(dm); + MVert *mvert = NULL; ClothVertex *verts = NULL; float tnull[3] = {0,0,0}; - /* If we have a clothObject, free it. */ + // If we have a clothObject, free it. if ( clmd->clothObject != NULL ) cloth_free_modifier ( ob, clmd ); - /* Allocate a new cloth object. */ + // Allocate a new cloth object. clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" ); if ( clmd->clothObject ) { @@ -974,88 +987,74 @@ static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh return 0; } - switch ( ob->type ) + // mesh input objects need DerivedMesh + if ( !dm ) + return 0; + + cloth_from_mesh ( ob, clmd, dm ); + + if ( clmd->clothObject != NULL ) { - case OB_MESH: + // create springs + clmd->clothObject->springs = NULL; + clmd->clothObject->numsprings = -1; + + mvert = CDDM_get_verts ( dm ); + verts = clmd->clothObject->verts; - // mesh input objects need DerivedMesh - if ( !dm ) - return 0; + // set initial values + for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) + { + VECCOPY ( verts->x, mvert[i].co ); + Mat4MulVecfl ( ob->obmat, verts->x ); - cloth_from_mesh ( ob, clmd, dm ); + verts->mass = clmd->sim_parms->mass; - if ( clmd->clothObject != NULL ) - { - /* create springs */ - clmd->clothObject->springs = NULL; - clmd->clothObject->numsprings = -1; - - mvert = CDDM_get_verts ( dm ); - verts = clmd->clothObject->verts; + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + verts->goal= clmd->sim_parms->defgoal; + else + verts->goal= 0.0f; - /* set initial values */ - for ( i = 0; i < numverts; i++, verts++ ) - { - VECCOPY ( verts->x, mvert[i].co ); - Mat4MulVecfl ( ob->obmat, verts->x ); + verts->flags = 0; + VECCOPY ( verts->xold, verts->x ); + VECCOPY ( verts->xconst, verts->x ); + VECCOPY ( verts->txold, verts->x ); + VecMulf ( verts->v, 0.0f ); - verts->mass = clmd->sim_parms->mass; - - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - verts->goal= clmd->sim_parms->defgoal; - else - verts->goal= 0.0f; - - verts->flags = 0; - VECCOPY ( verts->xold, verts->x ); - VECCOPY ( verts->xconst, verts->x ); - VECCOPY ( verts->txold, verts->x ); - VecMulf ( verts->v, 0.0f ); - - verts->impulse_count = 0; - VECCOPY ( verts->impulse, tnull ); - } - - if ( !cloth_build_springs ( clmd, dm ) ) - { - cloth_free_modifier ( ob, clmd ); - modifier_setError ( & ( clmd->modifier ), "Can't build springs." ); - return 0; - } - - // apply / set vertex groups - if ( clmd->sim_parms->vgroup_mass > 0 ) - cloth_apply_vgroup ( clmd, dm, clmd->sim_parms->vgroup_mass ); - - // init our solver - if ( solvers [clmd->sim_parms->solver_type].init ) - solvers [clmd->sim_parms->solver_type].init ( ob, clmd ); - - clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); - - cloth_write_cache(ob, clmd, framenr-1); - } - - return 1; - case OB_LATTICE: - printf ( "Not supported: OB_LATTICE\n" ); - // lattice_to_softbody(ob); + verts->impulse_count = 0; + VECCOPY ( verts->impulse, tnull ); + } + + if ( !cloth_build_springs ( clmd, dm ) ) + { + cloth_free_modifier ( ob, clmd ); + modifier_setError ( & ( clmd->modifier ), "Can't build springs." ); return 0; - case OB_CURVE: - case OB_SURF: - printf ( "Not supported: OB_SURF| OB_CURVE\n" ); - return 0; - default: return 0; // TODO - we do not support changing meshes + } + + // apply / set vertex groups + if ( clmd->sim_parms->vgroup_mass > 0 ) + cloth_apply_vgroup ( clmd, dm, clmd->sim_parms->vgroup_mass ); + + // init our solver + if ( solvers [clmd->sim_parms->solver_type].init ) + solvers [clmd->sim_parms->solver_type].init ( ob, clmd ); + + clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); + + cloth_write_cache(ob, clmd, framenr-1); + + return 1; } - return 0; } + static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) { unsigned int numverts = dm->getNumVerts ( dm ); unsigned int numfaces = dm->getNumFaces ( dm ); - MFace *mface = dm->getFaceArray ( dm ); + MFace *mface = CDDM_get_faces(dm); unsigned int i = 0; /* Allocate our vertices. diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 3f21bf2bfc5..69cc3b165c2 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -569,33 +569,35 @@ DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) /* SPARSE SYMMETRIC multiply big matrix with long vector*/ /* STATUS: verified */ -DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (*fLongVector)[3]) +DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector) { unsigned int i = 0; + lfVector *temp = create_lfvector(from[0].vcount); + zero_lfvector(to, from[0].vcount); - /* process diagonal elements */ - for(i = 0; i < from[0].vcount; i++) - { - muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); - } - /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */ - // TODO: pragma below is wrong, correct it! - // #pragma omp parallel for shared(to,from, fLongVector) private(i) - for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) +#pragma omp parallel sections private(i) { - // muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); - - to[from[i].c][0] += INPR(from[i].m[0],fLongVector[from[i].r]); - to[from[i].c][1] += INPR(from[i].m[1],fLongVector[from[i].r]); - to[from[i].c][2] += INPR(from[i].m[2],fLongVector[from[i].r]); - - // muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); - - to[from[i].r][0] += INPR(from[i].m[0],fLongVector[from[i].c]); - to[from[i].r][1] += INPR(from[i].m[1],fLongVector[from[i].c]); - to[from[i].r][2] += INPR(from[i].m[2],fLongVector[from[i].c]); +#pragma omp section + { + for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) + { + muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); + } + } +#pragma omp section + { + for(i = 0; i < from[0].vcount+from[0].scount; i++) + { + muladd_fmatrix_fvector(temp[from[i].r], from[i].m, fLongVector[from[i].c]); + } + } } + add_lfvector_lfvector(to, to, temp, from[0].vcount); + + del_lfvector(temp); + + } /* SPARSE SYMMETRIC multiply big matrix with long vector (for diagonal preconditioner) */ @@ -1088,7 +1090,6 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float bending_force[3] = {0,0,0}; float damping_force[3] = {0,0,0}; float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; - Cloth *cloth = clmd->clothObject; VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 3ea4d4fb584..428c136a7fe 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4958,29 +4958,23 @@ static void clothModifier_initData(ModifierData *md) cloth_init (clmd); } -static void clothModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) +static DerivedMesh *clothModifier_applyModifier(ModifierData *md, Object *ob, + DerivedMesh *derivedData, int useRenderParams, int isFinalCalc) { - DerivedMesh *dm = NULL; + ClothModifierData *clmd = (ClothModifierData*) md; + DerivedMesh *result=NULL; + + /* check for alloc failing */ + if(!clmd->sim_parms || !clmd->coll_parms) + return derivedData; - /* if possible use/create DerivedMesh */ - - if(derivedData) dm = CDDM_copy(derivedData); - else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); - - if(dm) + result = clothModifier_do(clmd, ob, derivedData, useRenderParams, isFinalCalc); + + if(result) { - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); + return result; } - - /* TODO: check for sim_parms / coll_parms NOT NULL */ - - clothModifier_do((ClothModifierData *)md, ob, dm, vertexCos, numVerts); - - if(dm) - dm->release(dm); + return derivedData; } static void clothModifier_updateDepgraph( @@ -5035,8 +5029,6 @@ static int clothModifier_dependsOnTime(ModifierData *md) static void clothModifier_freeData(ModifierData *md) { ClothModifierData *clmd = (ClothModifierData*) md; - Object *ob = NULL; - ClothModifierData *clmd2 = NULL; if (clmd) { @@ -7017,10 +7009,10 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->deformVerts = softbodyModifier_deformVerts; mti = INIT_TYPE(Cloth); - mti->type = eModifierTypeType_OnlyDeform; + mti->type = eModifierTypeType_Nonconstructive; mti->initData = clothModifier_initData; - mti->flags = eModifierTypeFlag_AcceptsCVs; - // | eModifierTypeFlag_RequiresOriginalData; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_RequiresOriginalData; // | eModifierTypeFlag_SupportsMapping // | eModifierTypeFlag_SupportsEditmode // | eModifierTypeFlag_EnableInEditmode; @@ -7028,7 +7020,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->freeData = clothModifier_freeData; mti->requiredDataMask = clothModifier_requiredDataMask; // mti->copyData = clothModifier_copyData; - mti->deformVerts = clothModifier_deformVerts; + // mti->deformVerts = clothModifier_deformVerts; + mti->applyModifier = clothModifier_applyModifier; mti->updateDepgraph = clothModifier_updateDepgraph; mti = INIT_TYPE(Collision); diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 1d7a1972d36..a064e266d6d 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -5087,7 +5087,7 @@ static void object_panel_cloth_II(Object *ob) } else { - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,120,300,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed"); + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache & 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."); if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) { diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 8bd397b0da4..7b51d50ae7b 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -76,6 +76,7 @@ #include "BKE_modifier.h" #include "BKE_multires.h" #include "BKE_object.h" +#include "BKE_pointcache.h" #include "BKE_texture.h" #include "BKE_utildefines.h" @@ -804,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){ @@ -839,10 +843,43 @@ 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, (float) G.scene->r.cfra, stack_index)) + { + cloth_enabled = 1; + + /* inverse matrix is not uptodate... */ + Mat4Invert ( G.obedit->imat, G.obedit->obmat ); + } + } + } evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist"); for(a=0; aco, 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 @@ -971,7 +1008,10 @@ 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) { @@ -1038,9 +1078,52 @@ 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, (float) G.scene->r.cfra, stack_index)) + { + cloth_enabled = 1; + + /* inverse matrix is not uptodate... */ + Mat4Invert ( G.obedit->imat, G.obedit->obmat ); + dt = 1.0f / clmd->sim_parms->stepsPerFrame; + } + } + } + + i=0; while(eve) { - VECCOPY(mvert->co, eve->co); + + if(cloth_enabled) + { + 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); + } + i++; + } + else + VECCOPY(mvert->co, eve->co); mvert->mat_nr= 255; /* what was this for, halos? */ /* vertex normal */ @@ -1068,6 +1151,10 @@ void load_editMesh(void) eve= eve->next; mvert++; } + + /* burn changes to cache */ + if(cloth_enabled) + cloth_write_cache(G.obedit, clmd, (float) G.scene->r.cfra); /* the edges */ a= 0; @@ -1330,7 +1417,13 @@ void load_editMesh(void) if(base->object->data==me) { if(modifiers_isClothEnabled(base->object)) { ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(base->object, eModifierType_Cloth); - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; + + /* only reset cloth when no cache was used */ + if(!cloth_enabled) + { + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; + } + } base->object->softflag |= OB_SB_REDO; diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 882a16bb9ce..5d2e7cd7410 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -3404,7 +3404,7 @@ void special_aftertrans_update(TransInfo *t) ob= base->object; if (modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO; - else if(modifiers_isClothEnabled(ob)) { + else if((ob == OBACT) && modifiers_isClothEnabled(ob)) { ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; } diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c index dec15f96b8a..163b93468fe 100644 --- a/source/blender/src/vpaint.c +++ b/source/blender/src/vpaint.c @@ -1353,6 +1353,7 @@ void weight_paint(void) if(modifiers_isClothEnabled(ob)) { ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; + printf("vpaint.c\n"); } BIF_undo_push("Weight Paint"); From e7f5d077810004467066d627f34d433a61e68fb2 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 25 Jan 2008 08:55:27 +0000 Subject: [PATCH 080/101] New: load cached data on file load; Fixed: Don't destroy cache on fileload, calculate normals correctly, don't reset all data when pressing partial free, making also cache free buttons available when cache is protected, duplicating cloth with shift-d should work properly now --- source/blender/blenkernel/BKE_cloth.h | 17 +++++++---- source/blender/blenkernel/intern/cloth.c | 29 ++++++++++++------- source/blender/blenkernel/intern/implicit.c | 2 +- source/blender/blenkernel/intern/modifier.c | 26 ++++++++++++++--- source/blender/makesdna/DNA_cloth_types.h | 4 +-- source/blender/src/buttons_object.c | 32 +++++++-------------- 6 files changed, 64 insertions(+), 46 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index e3fdb9e0f25..4c017cfaf06 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -128,17 +128,19 @@ ClothSpring; /* 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_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_NEW = ( 1 << 6 ), // unsued, true if cloth was just enabled } CLOTH_SIMSETTINGS_FLAGS; -/* SPRING FLAGS */ +/* COLLISION FLAGS */ typedef enum { - CLOTH_COLLISIONSETTINGS_FLAG_ENABLED = ( 1 << 1 ), + 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.*/ @@ -205,6 +207,9 @@ void bvh_update_from_cloth(ClothModifierData *clmd, int moving); // needed for editmesh.c void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr); +// needed for button_object.c +void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr); + //////////////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index f22fd28d96e..70c6857f14b 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -153,7 +153,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->mass = 1.0f; clmd->sim_parms->stepsPerFrame = 5; clmd->sim_parms->sim_time = 1.0; - clmd->sim_parms->flags = CLOTH_SIMSETTINGS_FLAG_RESET; + clmd->sim_parms->flags = CLOTH_SIMSETTINGS_FLAG_NEW; clmd->sim_parms->solver_type = 0; clmd->sim_parms->preroll = 0; clmd->sim_parms->maxspringlen = 10; @@ -166,7 +166,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->coll_parms->friction = 10.0; clmd->coll_parms->loop_count = 1; clmd->coll_parms->epsilon = 0.01f; - clmd->coll_parms->flags = CLOTH_COLLISIONSETTINGS_FLAG_ENABLED; + clmd->coll_parms->flags = CLOTH_COLLSETTINGS_FLAG_ENABLED; /* These defaults are copied from softbody.c's * softbody_calc_forces() function. @@ -533,7 +533,8 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) { int stack_index = -1; - if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) + /* clear cache if specific frame cleaning requested or cache is not protected */ + if((!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) || (framenr > 1.0)) { stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); @@ -635,8 +636,6 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d return result; } - // printf("ct: %f, st: %f, r.cfra: %f, dt: %f\n", current_time, clmd->sim_parms->sim_time, ( float ) G.scene->r.cfra, deltaTime); - // unused in the moment, calculated seperately in implicit.c clmd->sim_parms->dt = 1.0f / clmd->sim_parms->stepsPerFrame; @@ -659,6 +658,8 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d { cloth_clear_cache(ob, clmd, 0); + // printf("v1: %d, v2: %d\n", numverts, clmd->clothObject->numverts); + if ( !cloth_from_object ( ob, clmd, result, framenr ) ) return result; @@ -718,6 +719,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d else { cloth_clear_cache(ob, clmd, 0); + + if ( !cloth_from_object ( ob, clmd, result, framenr ) ) + return result; } } @@ -743,9 +747,9 @@ void cloth_free_modifier ( Object *ob, ClothModifierData *clmd ) cloth_clear_cache ( ob, clmd, 0 ); // If our solver provides a free function, call it - if ( cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free ) + if ( solvers [clmd->sim_parms->solver_type].free ) { - solvers [cloth->old_solver_type].free ( clmd ); + solvers [clmd->sim_parms->solver_type].free ( clmd ); } // Free the verts. @@ -805,9 +809,9 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd ) if ( cloth ) { // If our solver provides a free function, call it - if ( cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free ) + if ( solvers [clmd->sim_parms->solver_type].free ) { - solvers [cloth->old_solver_type].free ( clmd ); + solvers [clmd->sim_parms->solver_type].free ( clmd ); } // Free the verts. @@ -972,7 +976,9 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d // If we have a clothObject, free it. if ( clmd->clothObject != NULL ) + { cloth_free_modifier ( ob, clmd ); + } // Allocate a new cloth object. clmd->clothObject = MEM_callocN ( sizeof ( Cloth ), "cloth" ); @@ -1041,8 +1047,9 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d solvers [clmd->sim_parms->solver_type].init ( ob, clmd ); clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); - - cloth_write_cache(ob, clmd, framenr-1); + + if(!cloth_read_cache(ob, clmd, framenr)) + cloth_write_cache(ob, clmd, framenr); return 1; } diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 69cc3b165c2..557a664b5ea 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1389,7 +1389,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); - if(clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + if(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) { // collisions // itstart(); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index d18d5ae3fd0..a10210cbf3a 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4972,6 +4972,7 @@ static DerivedMesh *clothModifier_applyModifier(ModifierData *md, Object *ob, if(result) { + CDDM_calc_normals(result); return result; } return derivedData; @@ -5020,6 +5021,22 @@ CustomDataMask clothModifier_requiredDataMask(ModifierData *md) 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) { @@ -5035,8 +5052,10 @@ static void clothModifier_freeData(ModifierData *md) cloth_free_modifier_extern (clmd); - MEM_freeN(clmd->sim_parms); - MEM_freeN(clmd->coll_parms); + if(clmd->sim_parms) + MEM_freeN(clmd->sim_parms); + if(clmd->coll_parms) + MEM_freeN(clmd->coll_parms); } } @@ -7033,8 +7052,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->dependsOnTime = clothModifier_dependsOnTime; mti->freeData = clothModifier_freeData; mti->requiredDataMask = clothModifier_requiredDataMask; - // mti->copyData = clothModifier_copyData; - // mti->deformVerts = clothModifier_deformVerts; + mti->copyData = clothModifier_copyData; mti->applyModifier = clothModifier_applyModifier; mti->updateDepgraph = clothModifier_updateDepgraph; diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 661ad9547d5..d24ee2f0eb8 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -69,7 +69,7 @@ typedef struct SimulationSettings float eff_force_scale;/* Scaling of effector forces (see softbody_calc_forces).*/ float eff_wind_scale; /* Scaling of effector wind (see softbody_calc_forces). */ float sim_time_old; - struct LinkNode *cache; + struct LinkNode *cache; /* UNUSED atm */ float defgoal; int goalfrict; float goalspring; @@ -113,7 +113,7 @@ typedef struct Cloth unsigned int numverts; /* The number of verts == m * n. */ unsigned int numsprings; /* The count of springs. */ unsigned int numfaces; - unsigned char old_solver_type; + unsigned char old_solver_type; /* unused, only 1 solver here */ unsigned char pad2; short pad3; struct BVH *tree; /* collision tree for this cloth object */ diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 0b30f0b3cba..79dc890c462 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2320,7 +2320,8 @@ void do_object_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - cloth_clear_cache(ob, clmd, MAX2(1.0,G.scene->r.cfra + 1.0)); + cloth_clear_cache(ob, clmd, MAX2(1.0,G.scene->r.cfra)); + // MAX2(1.0,G.scene->r.cfra + 1.0) allqueue(REDRAWBUTSOBJECT, 0); } } @@ -5071,18 +5072,12 @@ static void object_panel_cloth(Object *ob) 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, 1.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)"); - uiBlockEndAlign(block); - uiBlockBeginAlign(block); + 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"); - uiBlockEndAlign(block); - uiClearButLock(); - - uiBlockBeginAlign(block); uiDefBut(block, LABEL, 0, "Gravity:", 10,100,60,20, NULL, 0.0, 0, 0, 0, ""); - // uiClearButLock(); uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,100,80,20, &clmd->sim_parms->gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,100,80,20, &clmd->sim_parms->gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); @@ -5202,17 +5197,10 @@ static void object_panel_cloth_II(Object *ob) { 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."); - if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) - { - 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, ""); - } - else - { - uiDefBut(block, LABEL, 0, " ", 10,100,300,40, NULL, 0.0, 0, 0, 0, ""); - } + 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, ""); } /* @@ -5222,8 +5210,8 @@ static void object_panel_cloth_II(Object *ob) uiDefBut(block, LABEL, 0, " ", 10,80,145,20, NULL, 0.0, 0, 0, 0, ""); */ - uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "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_COLLISIONSETTINGS_FLAG_ENABLED) + uiDefButBitI(block, TOG, CLOTH_COLLSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "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, B_CLOTH_RENEW, "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"); } From 589870100dc6734a20c99f572baeb2c401e6509f Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 25 Jan 2008 10:33:19 +0000 Subject: [PATCH 081/101] Fix: clear cache button works again even with protected cache, edited cache doesn't get saved to wrong frame anymore when moving frames forward in editmode --- source/blender/blenkernel/BKE_cloth.h | 2 ++ source/blender/blenkernel/intern/cloth.c | 14 +++++++++----- source/blender/blenkernel/intern/collision.c | 2 +- source/blender/makesdna/DNA_cloth_types.h | 2 +- source/blender/src/buttons_object.c | 5 +++++ source/blender/src/editmesh.c | 16 ++++++++++++++-- 6 files changed, 32 insertions(+), 9 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 4c017cfaf06..3a3d6612a23 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -134,6 +134,7 @@ typedef enum 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_NEW = ( 1 << 6 ), // unsued, true if cloth was just enabled + CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE = (1 << 7), /* force cache freeing */ } CLOTH_SIMSETTINGS_FLAGS; /* COLLISION FLAGS */ @@ -206,6 +207,7 @@ 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); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 70c6857f14b..e1b97362e08 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -145,9 +145,9 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->gravity [0] = 0.0; clmd->sim_parms->gravity [1] = 0.0; clmd->sim_parms->gravity [2] = -9.81; - clmd->sim_parms->structural = 100.0; - clmd->sim_parms->shear = 100.0; - clmd->sim_parms->bending = 1.0; + clmd->sim_parms->structural = 200.0; + clmd->sim_parms->shear = 200.0; + clmd->sim_parms->bending = 0.1; clmd->sim_parms->Cdis = 5.0; clmd->sim_parms->Cvi = 1.0; clmd->sim_parms->mass = 1.0f; @@ -161,6 +161,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->lastframe = 250; clmd->sim_parms->vgroup_mass = 0; clmd->sim_parms->lastcachedframe = 0; + clmd->sim_parms->editedframe = 0; clmd->coll_parms->self_friction = 5.0; clmd->coll_parms->friction = 10.0; @@ -485,7 +486,7 @@ DerivedMesh *CDDM_create_tearing ( ClothModifierData *clmd, DerivedMesh *dm ) int modifiers_indexInObject(Object *ob, ModifierData *md_seek); -static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) +int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) { FILE *fp = NULL; int stack_index = -1; @@ -534,7 +535,7 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) int stack_index = -1; /* clear cache if specific frame cleaning requested or cache is not protected */ - if((!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) || (framenr > 1.0)) + if((!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) || (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE)) { stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); @@ -545,6 +546,9 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) { cloth_read_cache(ob, clmd, framenr); } + + /* delete cache free request */ + clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; } void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) { diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 75201bbcea3..3d967655f70 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -694,7 +694,7 @@ void cloth_collision_static(ClothModifierData *clmd, CollisionModifierData *coll Normalize(collpair->normal); collpair->distance = distance; - BLI_linklist_append(&clmd->coll_parms->collision_list, collpair); + BLI_linklist_prepend(&clmd->coll_parms->collision_list, collpair); } else diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index d24ee2f0eb8..ab47d00d1b5 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -77,7 +77,7 @@ typedef struct SimulationSettings int lastframe; /* frame on which simulation stops */ int firstframe; /* frame on which simulation starts */ int lastcachedframe; - int pad3; + int editedframe; /* which frame is in buffer */ } SimulationSettings; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 79dc890c462..5ec89c6534e 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2306,6 +2306,9 @@ void do_object_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { + /* force freeing because user wants */ + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; + CFRA= 1; update_for_newframe_muted(); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); @@ -2320,6 +2323,8 @@ void do_object_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { + /* force freeing because user wants */ + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; cloth_clear_cache(ob, clmd, MAX2(1.0,G.scene->r.cfra)); // MAX2(1.0,G.scene->r.cfra + 1.0) allqueue(REDRAWBUTSOBJECT, 0); diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 7b51d50ae7b..9c00d8b71bc 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -861,6 +861,8 @@ void make_editMesh() { cloth_enabled = 1; + clmd->sim_parms->editedframe = (float) G.scene->r.cfra; + /* inverse matrix is not uptodate... */ Mat4Invert ( G.obedit->imat, G.obedit->obmat ); } @@ -1092,7 +1094,7 @@ void load_editMesh(void) /* 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, (float) G.scene->r.cfra, stack_index)) + if(BKE_ptcache_id_exist((ID *)G.obedit, clmd->sim_parms->editedframe, stack_index)) { cloth_enabled = 1; @@ -1108,9 +1110,11 @@ void load_editMesh(void) if(cloth_enabled) { + 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); @@ -1154,7 +1158,15 @@ void load_editMesh(void) /* burn changes to cache */ if(cloth_enabled) - cloth_write_cache(G.obedit, clmd, (float) G.scene->r.cfra); + { + 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 != (float) G.scene->r.cfra) + { + cloth_read_cache(G.obedit, clmd, (float) G.scene->r.cfra); + } + } /* the edges */ a= 0; From a01a606b1fdc2f855d84f855033116cc2ff5191d Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 25 Jan 2008 16:14:54 +0000 Subject: [PATCH 082/101] Weekend commit -> New: 3rd tab for advanced users mit many things to play with. Fixed: Free modifier correctly when deactivating cloth on panel, be carefull: could eventually put weird values on the GUI due to changed DNA --- source/blender/blenkernel/BKE_cloth.h | 7 +- source/blender/blenkernel/intern/cloth.c | 90 ++++++++---- source/blender/blenkernel/intern/collision.c | 5 +- source/blender/blenkernel/intern/implicit.c | 13 +- source/blender/makesdna/DNA_cloth_types.h | 20 +-- source/blender/src/buttons_object.c | 140 ++++++++++++++++--- source/blender/src/vpaint.c | 1 - 7 files changed, 216 insertions(+), 60 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 3a3d6612a23..5bcd40c5905 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -80,7 +80,10 @@ typedef struct ClothVertex 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 avg_spring_len; /* average length of connected springs, UNUSED ATM */ + float struct_stiff; + float bend_stiff; + float shear_stiff; } ClothVertex; @@ -99,6 +102,7 @@ typedef struct ClothSpring float dfdx[3][3]; float dfdv[3][3]; float f[3]; + float stiffness; /* stiffness factor from the vertex groups */ } ClothSpring; @@ -135,6 +139,7 @@ typedef enum CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ), // true if tearing is enabled CLOTH_SIMSETTINGS_FLAG_NEW = ( 1 << 6 ), // unsued, true if cloth was just enabled CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE = (1 << 7), /* force cache freeing */ + CLOTH_SIMSETTINGS_FLAG_SCALING = (1 << 8), /* is advanced scaling active? */ } CLOTH_SIMSETTINGS_FLAGS; /* COLLISION FLAGS */ diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index e1b97362e08..8ffb7ef2d19 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -125,7 +125,7 @@ static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh * static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr); int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); -static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ); +static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup, int mode ); /****************************************************************************** @@ -162,10 +162,11 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->vgroup_mass = 0; clmd->sim_parms->lastcachedframe = 0; clmd->sim_parms->editedframe = 0; + clmd->sim_parms->autoprotect = 10; clmd->coll_parms->self_friction = 5.0; clmd->coll_parms->friction = 10.0; - clmd->coll_parms->loop_count = 1; + clmd->coll_parms->loop_count = 5; clmd->coll_parms->epsilon = 0.01f; clmd->coll_parms->flags = CLOTH_COLLSETTINGS_FLAG_ENABLED; @@ -482,8 +483,6 @@ DerivedMesh *CDDM_create_tearing ( ClothModifierData *clmd, DerivedMesh *dm ) return result; } - - int modifiers_indexInObject(Object *ob, ModifierData *md_seek); int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) @@ -522,10 +521,10 @@ int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) } fclose(fp); - - if(clmd->sim_parms->solver_type == 0) - implicit_set_positions(clmd); } + + if(clmd->sim_parms->solver_type == 0) + implicit_set_positions(clmd); return ret; } @@ -655,6 +654,14 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d { cloth_free_modifier (ob, clmd); } + + // sanity check for correctness of GUI values + if(clmd->sim_parms->max_structsim_parms->structural) + clmd->sim_parms->max_struct=clmd->sim_parms->structural; + if(clmd->sim_parms->max_bendsim_parms->bending) + clmd->sim_parms->max_struct=clmd->sim_parms->bending; + if(clmd->sim_parms->max_shearsim_parms->shear) + clmd->sim_parms->max_shear=clmd->sim_parms->shear; if ( deltaTime == 1.0f ) { @@ -693,7 +700,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d VECCOPY ( verts->xconst, mvert[i].co ); Mat4MulVecfl ( ob->obmat, verts->xconst ); } - + tstart(); // Call the solver. @@ -704,6 +711,10 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d // printf ( "Cloth simulation time: %f\n", ( float ) tval() ); cloth_write_cache(ob, clmd, framenr); + + // check for autoprotection + if(framenr >= clmd->sim_parms->autoprotect) + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; } // Copy the result back to the object. @@ -897,7 +908,8 @@ static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh * * cloth_apply_vgroup - applies a vertex group as specified by type * **/ -static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ) +/* can be optimized to do all groups in one loop */ +static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup, int mode ) { unsigned int i = 0; unsigned int j = 0; @@ -922,7 +934,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short for ( i = 0; i < numverts; i++, verts++ ) { // LATER ON, support also mass painting here - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )||(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING)) { dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT ); if ( dvert ) @@ -931,25 +943,37 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short { if ( dvert->dw[j].def_nr == vgroup ) { - verts->goal = dvert->dw [j].weight; - - goalfac= 1.0f; - - /* - // Kicking goal factor to simplify things...who uses that anyway? - // ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); - */ - - verts->goal = ( float ) pow ( verts->goal , 4.0f ); - - if ( verts->goal >=SOFTGOALSNAP ) + if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) { - verts->flags |= CLOTH_VERT_FLAG_PINNED; + verts->goal = dvert->dw [j].weight; + goalfac= 1.0f; + + /* + // Kicking goal factor to simplify things...who uses that anyway? + // ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); + */ + + verts->goal = ( float ) pow ( verts->goal , 4.0f ); + if ( verts->goal >=SOFTGOALSNAP ) + verts->flags |= CLOTH_VERT_FLAG_PINNED; + + break; + } + + if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING ) + { + if(mode==2) + { + verts->struct_stiff = dvert->dw [j].weight; + verts->shear_stiff = dvert->dw [j].weight; + } + else if(mode==1) + { + verts->bend_stiff = dvert->dw [j].weight; + } + break; } - // TODO enable mass painting here, for the moment i let "goals" go first - - break; } } } @@ -1044,7 +1068,15 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d // apply / set vertex groups if ( clmd->sim_parms->vgroup_mass > 0 ) - cloth_apply_vgroup ( clmd, dm, clmd->sim_parms->vgroup_mass ); + cloth_apply_vgroup ( clmd, dm, clmd->sim_parms->vgroup_mass, 0 ); + + // apply / set vertex groups + if ( clmd->sim_parms->vgroup_bend > 0 ) + cloth_apply_vgroup ( clmd, dm, clmd->sim_parms->vgroup_bend, 1 ); + + // apply / set vertex groups + if ( clmd->sim_parms->vgroup_struct > 0 ) + cloth_apply_vgroup ( clmd, dm, clmd->sim_parms->vgroup_struct, 2 ); // init our solver if ( solvers [clmd->sim_parms->solver_type].init ) @@ -1181,6 +1213,7 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) clmd->coll_parms->avg_spring_len += spring->restlen; spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; spring->flags = 0; + spring->stiffness = (cloth->verts[spring->kl].struct_stiff + cloth->verts[spring->ij].struct_stiff) / 2.0; struct_springs++; if(!i) @@ -1203,6 +1236,7 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_SHEAR; + spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0; BLI_linklist_append ( &edgelist[spring->ij], spring ); BLI_linklist_append ( &edgelist[spring->kl], spring ); @@ -1220,6 +1254,7 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_SHEAR; + spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0; BLI_linklist_append ( &edgelist[spring->ij], spring ); BLI_linklist_append ( &edgelist[spring->kl], spring ); @@ -1257,6 +1292,7 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) VECSUB ( temp, cloth->verts[index2].x, cloth->verts[tspring2->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_BENDING; + spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0; BLI_edgehash_insert ( edgehash, spring->ij, index2, NULL ); bend_springs++; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 3d967655f70..1ce19e878fa 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -978,9 +978,6 @@ void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clm cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); } -// CLOTH_MAX_THRESHOLD defines how much collision rounds/loops should be taken -#define CLOTH_MAX_THRESHOLD 10 - // cloth - object collisions int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) { @@ -1092,7 +1089,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) } rounds++; } - while(result && (CLOTH_MAX_THRESHOLD>rounds)); + while(result && (clmd->coll_parms->loop_count>rounds)); //////////////////////////////////////////////////////////// // update positions diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 557a664b5ea..7ea48d6629b 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1091,6 +1091,8 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float damping_force[3] = {0,0,0}; float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; + float scaling = 0.0; + VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); cp_fmatrix(s->dfdv, nulldfdx); @@ -1122,15 +1124,17 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, mul_fvector_S(dir, extent, 0.0f); } - // calculate force of structural + shear springs if(s->type != CLOTH_SPRING_TYPE_BENDING) { if(length > L) // only on elonglation { s->flags |= CLOTH_SPRING_FLAG_NEEDED; - - k = clmd->sim_parms->structural; + + k = clmd->sim_parms->structural; + + scaling = k + s->stiffness * (clmd->sim_parms->max_struct-k); + k = scaling; mul_fvector_S(stretch_force, dir, (k*(length-L))); @@ -1152,6 +1156,9 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, s->flags |= CLOTH_SPRING_FLAG_NEEDED; k = clmd->sim_parms->bending; + + scaling = k + s->stiffness * (clmd->sim_parms->max_bend-k); + cb = k = scaling; mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); VECADD(s->f, s->f, bending_force); diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index ab47d00d1b5..93aa09db349 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -47,24 +47,24 @@ **/ typedef struct SimulationSettings { - short vgroup_mass; /* optional vertexgroup name for assigning weight. */ - short pad; + 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. */ + 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 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 pad2; + 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). */ @@ -77,7 +77,11 @@ typedef struct SimulationSettings int lastframe; /* frame on which simulation stops */ int firstframe; /* frame on which simulation starts */ int lastcachedframe; - int editedframe; /* which frame is in buffer */ + 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 */ } SimulationSettings; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 5ec89c6534e..7b87dd2108c 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2325,6 +2325,7 @@ void do_object_panels(unsigned short event) { /* force freeing because user wants */ clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; + cloth_clear_cache(ob, clmd, MAX2(1.0,G.scene->r.cfra)); // MAX2(1.0,G.scene->r.cfra + 1.0) allqueue(REDRAWBUTSOBJECT, 0); @@ -5036,13 +5037,31 @@ static void object_cloth__enabletoggle(void *ob_v, void *arg2) if (!md) { md = modifier_new(eModifierType_Cloth); BLI_addhead(&ob->modifiers, md); + + allqueue(REDRAWBUTSEDIT, 0); } else { - BLI_remlink(&ob->modifiers, md); - modifier_free(md); - } + Object *ob = ob_v; + ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + + if (!md) + return; - allqueue(REDRAWBUTSEDIT, 0); + 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(); + } } @@ -5068,7 +5087,7 @@ static void object_panel_cloth(Object *ob) { int defCount; char *clvg1, *clvg2; - char clmvg [] = "Weight Paint Groups%t|"; + char clmvg [] = "Vertex Groups%t|"; val2=0; @@ -5177,22 +5196,12 @@ static void object_panel_cloth_II(Object *ob) clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) - { - // char str[128]; - + { uiDefButI(block, NUM, B_DIFF, "First Frame:", 10,160,150,20, &clmd->sim_parms->firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts"); uiDefButI(block, NUM, B_DIFF, "Last Frame:", 160,160,150,20, &clmd->sim_parms->lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops"); uiDefBut(block, LABEL, 0, "",10,140,300,20, NULL, 0.0, 0, 0, 0, ""); - /* correct spelling if only 1 frame cacheed --> only gimmick */ - /* - if(length-clmd->sim_parms->preroll>1) - sprintf (str, "Frame 1 - %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length); - else - sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length); - */ - if (!G.relbase_valid) { uiDefBut(block, LABEL, 0, "Cache deactivated until file is saved.", 10,120,300,20, NULL, 0.0, 0, 0, 0, ""); @@ -5209,6 +5218,7 @@ static void object_panel_cloth_II(Object *ob) } /* + 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 @@ -5219,6 +5229,7 @@ static void object_panel_cloth_II(Object *ob) if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) { uiDefButF(block, NUM, B_CLOTH_RENEW, "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"); + uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Collision Quality:", 10,40,300,20, &clmd->coll_parms->loop_count, 1.0, 100.0, 1.0, 0, "How many collision iterations should be done. (higher = better = slower), je be changed for each frame"); } else uiDefBut(block, LABEL, 0, "",160,60,150,20, NULL, 0.0, 0, 0, 0, ""); @@ -5228,6 +5239,102 @@ static void object_panel_cloth_II(Object *ob) } +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, MAXFRAME, 1, 0, "Frame on which the simulation gets cache protection enabled automatically (To prevent accidently cleaning it)."); + + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_SCALING, REDRAWVIEW3D, "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, 1000.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, 1000.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; @@ -5259,6 +5366,7 @@ void physics_panels() object_softbodies_solver(ob); object_panel_cloth(ob); object_panel_cloth_II(ob); + object_panel_cloth_III(ob); object_panel_fluidsim(ob); } } diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c index 163b93468fe..dec15f96b8a 100644 --- a/source/blender/src/vpaint.c +++ b/source/blender/src/vpaint.c @@ -1353,7 +1353,6 @@ void weight_paint(void) if(modifiers_isClothEnabled(ob)) { ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - printf("vpaint.c\n"); } BIF_undo_push("Weight Paint"); From a1a9e011b8d1f545a5db3144b22b48a7a4df2786 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 25 Jan 2008 21:47:43 +0000 Subject: [PATCH 083/101] untested fixes for vgroups --- source/blender/blenkernel/intern/cloth.c | 32 +++++++++++++----------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 8ffb7ef2d19..b5bd1c68dda 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -945,19 +945,22 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short { if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) { - verts->goal = dvert->dw [j].weight; - goalfac= 1.0f; - - /* - // Kicking goal factor to simplify things...who uses that anyway? - // ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); - */ - - verts->goal = ( float ) pow ( verts->goal , 4.0f ); - if ( verts->goal >=SOFTGOALSNAP ) - verts->flags |= CLOTH_VERT_FLAG_PINNED; - - break; + if(mode==0) + { + verts->goal = dvert->dw [j].weight; + goalfac= 1.0f; + + /* + // Kicking goal factor to simplify things...who uses that anyway? + // ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); + */ + + verts->goal = ( float ) pow ( verts->goal , 4.0f ); + if ( verts->goal >=SOFTGOALSNAP ) + verts->flags |= CLOTH_VERT_FLAG_PINNED; + + break; + } } if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING ) @@ -966,12 +969,13 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short { verts->struct_stiff = dvert->dw [j].weight; verts->shear_stiff = dvert->dw [j].weight; + break; } else if(mode==1) { verts->bend_stiff = dvert->dw [j].weight; + break; } - break; } } From 9c1fa1ff4d5d5d21170d7a56c00abc6476b85dda Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 29 Jan 2008 02:24:37 +0000 Subject: [PATCH 084/101] WIP commit, many debug outputs, extensive log comes after bug is killed --- source/blender/blenkernel/BKE_cloth.h | 6 +- source/blender/blenkernel/CMakeLists.txt | 2 +- source/blender/blenkernel/intern/cloth.c | 522 +++++++++++-------- source/blender/blenkernel/intern/collision.c | 88 ++-- source/blender/blenkernel/intern/modifier.c | 3 + source/blender/src/buttons_editing.c | 2 +- source/blender/src/buttons_object.c | 39 +- source/blender/src/editmesh.c | 38 +- 8 files changed, 391 insertions(+), 309 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 5bcd40c5905..1a3feed0a0c 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -62,9 +62,7 @@ struct CollisionTree; #define CLOTH_MAX_THREAD 2 /** - * Pin and unpin frames are the frames on which the vertices stop moving. - * They will assume the position they had prior to pinFrame until unpinFrame - * is reached. + * The definition of a cloth vertex. */ typedef struct ClothVertex { @@ -87,7 +85,6 @@ typedef struct ClothVertex } ClothVertex; - /** * The definition of a spring. */ @@ -106,7 +103,6 @@ typedef struct ClothSpring } ClothSpring; - /* goal defines */ #define SOFTGOALSNAP 0.999f diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 0b87f0c1d98..30f21ef83cc 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -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} diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index b5bd1c68dda..0870bf2efa3 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -125,7 +125,7 @@ static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh * static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr); int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); -static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup, int mode ); +static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ); /****************************************************************************** @@ -162,12 +162,12 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->vgroup_mass = 0; clmd->sim_parms->lastcachedframe = 0; clmd->sim_parms->editedframe = 0; - clmd->sim_parms->autoprotect = 10; + clmd->sim_parms->autoprotect = 25; clmd->coll_parms->self_friction = 5.0; clmd->coll_parms->friction = 10.0; - clmd->coll_parms->loop_count = 5; - clmd->coll_parms->epsilon = 0.01f; + clmd->coll_parms->loop_count = 3; + clmd->coll_parms->epsilon = 0.015f; clmd->coll_parms->flags = CLOTH_COLLSETTINGS_FLAG_ENABLED; /* These defaults are copied from softbody.c's @@ -182,8 +182,6 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->defgoal = 0.0f; clmd->sim_parms->goalspring = 100.0f; clmd->sim_parms->goalfrict = 0.0f; - - clmd->sim_parms->cache = NULL; } @@ -521,17 +519,38 @@ int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) } fclose(fp); + + /* + // belongs to another location ?!? + if((clmd->sim_parms->solver_type == 0) && (ret!=0)) + { + implicit_set_positions(clmd); + } + */ + + if(clmd->sim_parms->lastcachedframe < framenr) + { + printf("cloth_read_cache problem: lnex - f#: %f, lastCF: %d\n", framenr, clmd->sim_parms->lastcachedframe); + } } - if(clmd->sim_parms->solver_type == 0) - implicit_set_positions(clmd); - + printf("cloth_read_cache: %f\n", framenr); + return ret; } void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) { int stack_index = -1; + printf("cloth_clear_cache: %f\n", framenr); + + /* + // belongs to another location ?!? + if(framenr>0) + { + cloth_read_cache(ob, clmd, framenr); + } + */ /* clear cache if specific frame cleaning requested or cache is not protected */ if((!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) || (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE)) @@ -541,13 +560,13 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) BKE_ptcache_id_clear((ID *)ob, PTCACHE_CLEAR_AFTER, framenr, stack_index); } - if(framenr>0) - { - cloth_read_cache(ob, clmd, framenr); - } + /* update last cached frame # */ + clmd->sim_parms->lastcachedframe = framenr; /* delete cache free request */ clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; + + } void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) { @@ -556,8 +575,11 @@ void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) unsigned int a; Cloth *cloth = clmd->clothObject; + printf("cloth_write_cache: %f\n", framenr); + if(!cloth) { + printf("cloth_write_cache: no cloth\n"); return; } @@ -566,6 +588,7 @@ void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) fp = BKE_ptcache_id_fopen((ID *)ob, 'w', framenr, stack_index); if(!fp) { + printf("cloth_write_cache: no fp\n"); return; } @@ -578,6 +601,8 @@ void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) clmd->sim_parms->lastcachedframe = MAX2(clmd->sim_parms->lastcachedframe, framenr); + printf("lcf: %d, framenr: %f\n", clmd->sim_parms->lastcachedframe, framenr); + fclose(fp); } @@ -591,7 +616,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d { unsigned int i; Cloth *cloth = clmd->clothObject; - unsigned int framenr = ( float ) G.scene->r.cfra; + float framenr = G.scene->r.cfra; float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); ListBase *effectors = NULL; ClothVertex *verts = NULL; @@ -604,6 +629,8 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d MFace *mface = NULL; DerivedMesh *result = NULL; + printf("clothModifier_do start\n"); + result = CDDM_copy(dm); if(!result) @@ -614,134 +641,182 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d numverts = result->getNumVerts(result); numedges = result->getNumEdges(result); numfaces = result->getNumFaces(result); - mvert = CDDM_get_verts(result); - medge = CDDM_get_edges(result); - mface = CDDM_get_faces(result); - - // only be active during a specific period: - // that's "first frame" and "last frame" on GUI - if ( current_time < clmd->sim_parms->firstframe ) - { - return result; - } - else if ( current_time > clmd->sim_parms->lastframe ) - { - int stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); - - if(BKE_ptcache_id_exist((ID *)ob, clmd->sim_parms->lastcachedframe, stack_index)) - { - if(cloth_read_cache(ob, clmd, framenr)) - { - // Copy the result back to the object. - cloth_to_object (ob, clmd, result); - } - } - return result; - } - - // unused in the moment, calculated seperately in implicit.c - clmd->sim_parms->dt = 1.0f / clmd->sim_parms->stepsPerFrame; - - clmd->sim_parms->sim_time = current_time; + mvert = dm->getVertArray(result); + medge = dm->getEdgeArray(result); + mface = dm->getFaceArray(result); /* check if cache is active / if file is already saved */ + /* if ((!G.relbase_valid) && ( deltaTime != 1.0f )) { clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; } - + */ + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_RESET) { cloth_free_modifier (ob, clmd); + printf("clothModifier_do CLOTH_SIMSETTINGS_FLAG_RESET\n"); } - // sanity check for correctness of GUI values - if(clmd->sim_parms->max_structsim_parms->structural) - clmd->sim_parms->max_struct=clmd->sim_parms->structural; - if(clmd->sim_parms->max_bendsim_parms->bending) - clmd->sim_parms->max_struct=clmd->sim_parms->bending; - if(clmd->sim_parms->max_shearsim_parms->shear) - clmd->sim_parms->max_shear=clmd->sim_parms->shear; - - if ( deltaTime == 1.0f ) + // unused in the moment, calculated seperately in implicit.c + clmd->sim_parms->dt = 1.0f / clmd->sim_parms->stepsPerFrame; + + if ( ( clmd->clothObject == NULL ) || (clmd->clothObject && (numverts != clmd->clothObject->numverts )) ) { - if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) ) + /* only force free the cache if we have a different number of verts */ + if(clmd->clothObject && (numverts != clmd->clothObject->numverts )) { - cloth_clear_cache(ob, clmd, 0); - - // printf("v1: %d, v2: %d\n", numverts, clmd->clothObject->numverts); - - if ( !cloth_from_object ( ob, clmd, result, framenr ) ) - return result; - - if ( clmd->clothObject == NULL ) - return result; - - cloth = clmd->clothObject; + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; + cloth_free_modifier ( ob, clmd ); } - - clmd->clothObject->old_solver_type = clmd->sim_parms->solver_type; - - // Insure we have a clmd->clothObject, in case allocation failed. - if ( clmd->clothObject != NULL ) - { - if(!cloth_read_cache(ob, clmd, framenr)) - { - verts = cloth->verts; - - // Force any pinned verts to their constrained location. - for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) - { - // Save the previous position. - VECCOPY ( verts->xold, verts->xconst ); - VECCOPY ( verts->txold, verts->x ); - - // Get the current position. - VECCOPY ( verts->xconst, mvert[i].co ); - Mat4MulVecfl ( ob->obmat, verts->xconst ); - } + + cloth_clear_cache(ob, clmd, 0); - tstart(); - - // Call the solver. - if ( solvers [clmd->sim_parms->solver_type].solver ) - solvers [clmd->sim_parms->solver_type].solver ( ob, framenr, clmd, effectors ); - - tend(); - // printf ( "Cloth simulation time: %f\n", ( float ) tval() ); - - cloth_write_cache(ob, clmd, framenr); - - // check for autoprotection - if(framenr >= clmd->sim_parms->autoprotect) - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; - } - - // Copy the result back to the object. - cloth_to_object (ob, clmd, result); - } - - } - else - { - if ( clmd->clothObject != NULL ) + if ( !cloth_from_object ( ob, clmd, result, framenr ) ) + return result; + + if ( clmd->clothObject == NULL ) + return result; + + cloth = clmd->clothObject; + + if(!cloth_read_cache(ob, clmd, framenr)) { - if(cloth_read_cache(ob, clmd, framenr)) - { - cloth_to_object (ob, clmd, result); - } + /* save first frame in case we have a reseted object + and we move one frame forward. + In that case we would only start with the SECOND frame + if we don't save the current state before + TODO PROBLEM: IMHO we can't track external movement from the + first frame in this case! */ + /* + if ( deltaTime == 1.0f ) + cloth_write_cache(ob, clmd, framenr-1.0); + */ + printf("cloth_from_object NO cloth_read_cache cloth_write_cache\n"); } else { + printf("cloth_from_object cloth_read_cache\n"); + + implicit_set_positions(clmd); + } + + clmd->sim_parms->sim_time = current_time; + } + + // only be active during a specific period: + // that's "first frame" and "last frame" on GUI + /* + // TODO: enable later again after refactoring + if ( current_time < clmd->sim_parms->firstframe ) + { + return result; +} + else if ( current_time > clmd->sim_parms->lastframe ) + { + int stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); + + if(BKE_ptcache_id_exist((ID *)ob, clmd->sim_parms->lastcachedframe, stack_index)) + { + if(cloth_read_cache(ob, clmd, framenr)) + { + // Copy the result back to the object. + cloth_to_object (ob, clmd, result); +} +} + return result; +} + */ + + /* nice moving one frame forward */ + if ( deltaTime == 1.0f ) + { + clmd->sim_parms->sim_time = current_time; + + printf("clothModifier_do deltaTime=1\n"); + + if(!cloth_read_cache(ob, clmd, framenr)) + { + verts = cloth->verts; + + // Force any pinned verts to their constrained location. + for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) + { + // Save the previous position. + VECCOPY ( verts->xold, verts->xconst ); + VECCOPY ( verts->txold, verts->x ); + + // Get the current position. + VECCOPY ( verts->xconst, mvert[i].co ); + Mat4MulVecfl ( ob->obmat, verts->xconst ); + } + + tstart(); + + // Call the solver. + if ( solvers [clmd->sim_parms->solver_type].solver ) + solvers [clmd->sim_parms->solver_type].solver ( ob, framenr, clmd, effectors ); + + tend(); + // printf ( "Cloth simulation time: %f\n", ( float ) tval() ); + + cloth_write_cache(ob, clmd, framenr); + + // check for autoprotection + if(framenr >= clmd->sim_parms->autoprotect) + { + printf("fr#: %f, auto: %d\n", framenr, clmd->sim_parms->autoprotect); + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; + } + + printf("clothModifier_do deltaTime=1 cachewrite\n"); + } + else + { + printf("clothModifier_do deltaTime=1 cacheread\n"); + implicit_set_positions(clmd); + } + + // Copy the result back to the object. + cloth_to_object (ob, clmd, result); + } + else if(deltaTime == 0.0f) + { + printf("clothModifier_do deltaTime!=1 clmd->clothObject != NULL\n"); + if(cloth_read_cache(ob, clmd, framenr)) + { + cloth_to_object (ob, clmd, result); + implicit_set_positions(clmd); + } + else /* same cache parts are missing */ + { + /* + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; + */ + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; cloth_clear_cache(ob, clmd, 0); - if ( !cloth_from_object ( ob, clmd, result, framenr ) ) - return result; + cloth_write_cache(ob, clmd, framenr); + } + } + else + { + printf("clothModifier_do deltaTime!=1 clmd->clothObject != NULL\n"); + if(cloth_read_cache(ob, clmd, framenr)) + { + cloth_to_object (ob, clmd, result); + implicit_set_positions(clmd); + clmd->sim_parms->sim_time = current_time; + } + else + { + /* jump to a non-existing frame makes sim reset */ + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; } } return result; - } /* frees all */ @@ -754,59 +829,54 @@ void cloth_free_modifier ( Object *ob, ClothModifierData *clmd ) cloth = clmd->clothObject; - if ( ! ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT ) ) - { - if ( cloth ) + + if ( cloth ) + { + // If our solver provides a free function, call it + if ( solvers [clmd->sim_parms->solver_type].free ) { - // free our frame cache, TODO: but get to first position before - cloth_clear_cache ( ob, clmd, 0 ); - - // If our solver provides a free function, call it - if ( solvers [clmd->sim_parms->solver_type].free ) - { - solvers [clmd->sim_parms->solver_type].free ( clmd ); - } - - // Free the verts. - if ( cloth->verts != NULL ) - MEM_freeN ( cloth->verts ); - - cloth->verts = NULL; - cloth->numverts = 0; - - // Free the springs. - if ( cloth->springs != NULL ) - { - LinkNode *search = cloth->springs; - while(search) - { - ClothSpring *spring = search->link; - - MEM_freeN ( spring ); - search = search->next; - } - BLI_linklist_free(cloth->springs, NULL); - - cloth->springs = NULL; - } - - cloth->springs = NULL; - cloth->numsprings = 0; - - // free BVH collision tree - if ( cloth->tree ) - bvh_free ( ( BVH * ) cloth->tree ); - - // we save our faces for collision objects - if ( cloth->mfaces ) - MEM_freeN ( cloth->mfaces ); - /* - if(clmd->clothObject->facemarks) - MEM_freeN(clmd->clothObject->facemarks); - */ - MEM_freeN ( cloth ); - clmd->clothObject = NULL; + solvers [clmd->sim_parms->solver_type].free ( clmd ); } + + // Free the verts. + if ( cloth->verts != NULL ) + MEM_freeN ( cloth->verts ); + + cloth->verts = NULL; + cloth->numverts = 0; + + // Free the springs. + if ( cloth->springs != NULL ) + { + LinkNode *search = cloth->springs; + while(search) + { + ClothSpring *spring = search->link; + + MEM_freeN ( spring ); + search = search->next; + } + BLI_linklist_free(cloth->springs, NULL); + + cloth->springs = NULL; + } + + cloth->springs = NULL; + cloth->numsprings = 0; + + // free BVH collision tree + if ( cloth->tree ) + bvh_free ( ( BVH * ) cloth->tree ); + + // we save our faces for collision objects + if ( cloth->mfaces ) + MEM_freeN ( cloth->mfaces ); + /* + if(clmd->clothObject->facemarks) + MEM_freeN(clmd->clothObject->facemarks); + */ + MEM_freeN ( cloth ); + clmd->clothObject = NULL; } clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_RESET; } @@ -816,6 +886,8 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd ) { Cloth *cloth = NULL; + printf("cloth_free_modifier_extern\n"); + if ( !clmd ) return; @@ -823,6 +895,8 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd ) if ( cloth ) { + printf("cloth_free_modifier_extern in\n"); + // If our solver provides a free function, call it if ( solvers [clmd->sim_parms->solver_type].free ) { @@ -909,7 +983,7 @@ static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh * * **/ /* can be optimized to do all groups in one loop */ -static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup, int mode ) +static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) { unsigned int i = 0; unsigned int j = 0; @@ -918,66 +992,57 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short unsigned int numverts = dm->getNumVerts ( dm ); float goalfac = 0; ClothVertex *verts = NULL; + // clmd->sim_parms->vgroup_mass clothObj = clmd->clothObject; if ( !dm ) return; - + numverts = dm->getNumVerts ( dm ); - /* vgroup is 1 based, decrement so we can match the right group. */ - --vgroup; - verts = clothObj->verts; - - for ( i = 0; i < numverts; i++, verts++ ) + + if (((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING ) || + (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )) && + ((clmd->sim_parms->vgroup_mass>0) || + (clmd->sim_parms->vgroup_struct>0)|| + (clmd->sim_parms->vgroup_bend>0))) { - // LATER ON, support also mass painting here - if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )||(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING)) + for ( i = 0; i < numverts; i++, verts++ ) { dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT ); if ( dvert ) { for ( j = 0; j < dvert->totweight; j++ ) { - if ( dvert->dw[j].def_nr == vgroup ) + if (( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_mass-1)) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )) { - if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + verts->goal = dvert->dw [j].weight; + goalfac= 1.0f; + + /* + // Kicking goal factor to simplify things...who uses that anyway? + // ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); + */ + + verts->goal = ( float ) pow ( verts->goal , 4.0f ); + if ( verts->goal >=SOFTGOALSNAP ) + verts->flags |= CLOTH_VERT_FLAG_PINNED; + } + + if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING ) + { + if( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_struct-1)) { - if(mode==0) - { - verts->goal = dvert->dw [j].weight; - goalfac= 1.0f; - - /* - // Kicking goal factor to simplify things...who uses that anyway? - // ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); - */ - - verts->goal = ( float ) pow ( verts->goal , 4.0f ); - if ( verts->goal >=SOFTGOALSNAP ) - verts->flags |= CLOTH_VERT_FLAG_PINNED; - - break; - } + verts->struct_stiff = dvert->dw [j].weight; + verts->shear_stiff = dvert->dw [j].weight; } - if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING ) + if( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_bend-1)) { - if(mode==2) - { - verts->struct_stiff = dvert->dw [j].weight; - verts->shear_stiff = dvert->dw [j].weight; - break; - } - else if(mode==1) - { - verts->bend_stiff = dvert->dw [j].weight; - break; - } + verts->bend_stiff = dvert->dw [j].weight; } - } } } @@ -1010,6 +1075,8 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if ( clmd->clothObject != NULL ) { cloth_free_modifier ( ob, clmd ); + + printf("cloth_free_modifier cloth_from_object\n"); } // Allocate a new cloth object. @@ -1037,14 +1104,21 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject->springs = NULL; clmd->clothObject->numsprings = -1; - mvert = CDDM_get_verts ( dm ); + mvert = dm->getVertArray ( dm ); verts = clmd->clothObject->verts; // set initial values for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) { VECCOPY ( verts->x, mvert[i].co ); + + if(i<5) + printf("i: %d, verts->x[0]: %f\n", i, verts->x[0]); + Mat4MulVecfl ( ob->obmat, verts->x ); + + if(i<5) + printf("i: %d, verts->x[0]: %f\n\n", i, verts->x[0]); verts->mass = clmd->sim_parms->mass; @@ -1063,34 +1137,24 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d VECCOPY ( verts->impulse, tnull ); } + // apply / set vertex groups + // has to be happen before springs are build! + cloth_apply_vgroup (clmd, dm); + if ( !cloth_build_springs ( clmd, dm ) ) { cloth_free_modifier ( ob, clmd ); modifier_setError ( & ( clmd->modifier ), "Can't build springs." ); + printf("cloth_free_modifier cloth_build_springs\n"); return 0; } - - // apply / set vertex groups - if ( clmd->sim_parms->vgroup_mass > 0 ) - cloth_apply_vgroup ( clmd, dm, clmd->sim_parms->vgroup_mass, 0 ); - // apply / set vertex groups - if ( clmd->sim_parms->vgroup_bend > 0 ) - cloth_apply_vgroup ( clmd, dm, clmd->sim_parms->vgroup_bend, 1 ); - - // apply / set vertex groups - if ( clmd->sim_parms->vgroup_struct > 0 ) - cloth_apply_vgroup ( clmd, dm, clmd->sim_parms->vgroup_struct, 2 ); - // init our solver if ( solvers [clmd->sim_parms->solver_type].init ) solvers [clmd->sim_parms->solver_type].init ( ob, clmd ); clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); - if(!cloth_read_cache(ob, clmd, framenr)) - cloth_write_cache(ob, clmd, framenr); - return 1; } return 0; @@ -1112,6 +1176,7 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh * { cloth_free_modifier ( ob, clmd ); modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." ); + printf("cloth_free_modifier clmd->clothObject->verts\n"); return; } @@ -1122,6 +1187,7 @@ static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh * { cloth_free_modifier ( ob, clmd ); modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->mfaces." ); + printf("cloth_free_modifier clmd->clothObject->mfaces\n"); return; } for ( i = 0; i < numfaces; i++ ) @@ -1214,6 +1280,14 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring->kl = medge[i].v2; VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); + /* + if(spring->restlen > 1.0) + { + printf("i: %d, L: %f\n", i, spring->restlen); + printf("%d, x: %f, y: %f, z: %f\n", cloth->verts[spring->ij].x[0], cloth->verts[spring->ij].x[1], spring->ij, cloth->verts[spring->ij].x[2]); + printf("%d, x: %f, y: %f, z: %f\n\n",spring->kl, cloth->verts[spring->kl].x[0], cloth->verts[spring->kl].x[1], cloth->verts[spring->kl].x[2]); + } + */ clmd->coll_parms->avg_spring_len += spring->restlen; spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; spring->flags = 0; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 1ce19e878fa..083ae5a2b46 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -991,6 +991,7 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) ClothVertex *verts = NULL; float tnull[3] = {0,0,0}; int ret = 0; + ClothModifierData *tclmd; if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) { @@ -1025,6 +1026,10 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) if (!collmd) continue; + tclmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if(tclmd == clmd) + continue; + if (collmd->tree) { BVH *coll_bvh = collmd->tree; @@ -1035,57 +1040,50 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) } else printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); - } - // process all collisions (calculate impulses, TODO: also repulses if distance too short) - result = 1; - for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence - { - result = 0; - - // handle all collision objects - for (base = G.scene->base.first; base; base = base->next) + + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence { - - coll_ob = base->object; - collmd = (CollisionModifierData *) modifiers_findByType (coll_ob, eModifierType_Collision); - if (!collmd) - continue; - - result += cloth_collision_response_static(clmd, collmd); - } - - // apply impulses in parallel - ic=0; - for(i = 0; i < numverts; i++) - { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if(verts[i].impulse_count) - { - VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); - VECCOPY(verts[i].impulse, tnull); - verts[i].impulse_count = 0; + result = 0; - ic++; - ret++; + if (collmd->tree) + result += cloth_collision_response_static(clmd, collmd); + + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } } } - } - - // free collision list - if(clmd->coll_parms->collision_list) - { - LinkNode *search = clmd->coll_parms->collision_list; - while(search) - { - CollPair *coll_pair = search->link; - - MEM_freeN(coll_pair); - search = search->next; - } - BLI_linklist_free(clmd->coll_parms->collision_list,NULL); - clmd->coll_parms->collision_list = NULL; + // free collision list + if(clmd->coll_parms->collision_list) + { + LinkNode *search = clmd->coll_parms->collision_list; + while(search) + { + CollPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(clmd->coll_parms->collision_list,NULL); + + clmd->coll_parms->collision_list = NULL; + } } rounds++; } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index a10210cbf3a..475009c8fa6 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4956,6 +4956,7 @@ static void clothModifier_initData(ModifierData *md) return; cloth_init (clmd); + printf("clothModifier_initData\n"); } static DerivedMesh *clothModifier_applyModifier(ModifierData *md, Object *ob, @@ -5050,6 +5051,8 @@ static void clothModifier_freeData(ModifierData *md) if (clmd) { + printf("clothModifier_freeData\n"); + cloth_free_modifier_extern (clmd); if(clmd->sim_parms) diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index d3a474a57a5..3ea7788f87c 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1788,7 +1788,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco } else if (md->type==eModifierType_Softbody) { height = 31; } else if (md->type==eModifierType_Cloth) { - height = 26; + height = 31; } else if (md->type==eModifierType_Collision) { height = 19; } else if (md->type==eModifierType_Boolean) { diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index eb81c256289..4f23d60cd67 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2355,10 +2355,13 @@ void do_object_panels(unsigned short event) /* 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, 1); + cloth_clear_cache(ob, clmd, 0); allqueue(REDRAWBUTSOBJECT, 0); allqueue(REDRAWVIEW3D, 0); } @@ -2372,7 +2375,7 @@ void do_object_panels(unsigned short event) /* force freeing because user wants */ clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; - cloth_clear_cache(ob, clmd, MAX2(1.0,G.scene->r.cfra)); + cloth_clear_cache(ob, clmd, MAX2(0.0,G.scene->r.cfra)); // MAX2(1.0,G.scene->r.cfra + 1.0) allqueue(REDRAWBUTSOBJECT, 0); } @@ -2383,14 +2386,11 @@ void do_object_panels(unsigned short event) ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - if(clmd->sim_parms->cache) - { - CFRA= 1; - update_for_newframe_muted(); - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - allqueue(REDRAWBUTSOBJECT, 0); - allqueue(REDRAWVIEW3D, 0); - } + CFRA= 1; + update_for_newframe_muted(); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); } } break; @@ -2401,6 +2401,9 @@ void do_object_panels(unsigned short event) 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; @@ -5047,7 +5050,9 @@ static void object_cloth__enabletoggle(void *ob_v, void *arg2) 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; @@ -5121,7 +5126,7 @@ static void object_panel_cloth(Object *ob) uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Pinning of cloth", 10,70,150,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); + 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)) { @@ -5207,7 +5212,7 @@ static void object_panel_cloth_II(Object *ob) if(clmd) { uiDefButI(block, NUM, B_DIFF, "First Frame:", 10,160,150,20, &clmd->sim_parms->firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts"); - uiDefButI(block, NUM, B_DIFF, "Last Frame:", 160,160,150,20, &clmd->sim_parms->lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops"); + uiDefButI(block, NUM, B_DIFF, "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, ""); @@ -5234,11 +5239,11 @@ static void object_panel_cloth_II(Object *ob) uiDefBut(block, LABEL, 0, " ", 10,80,145,20, NULL, 0.0, 0, 0, 0, ""); */ - uiDefButBitI(block, TOG, CLOTH_COLLSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,60,150,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable collisions with this object"); + 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, B_CLOTH_RENEW, "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"); - uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Collision Quality:", 10,40,300,20, &clmd->coll_parms->loop_count, 1.0, 100.0, 1.0, 0, "How many collision iterations should be done. (higher = better = slower), je be changed for each frame"); + 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,300,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"); } else uiDefBut(block, LABEL, 0, "",160,60,150,20, NULL, 0.0, 0, 0, 0, ""); @@ -5268,9 +5273,9 @@ static void object_panel_cloth_III(Object *ob) 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, MAXFRAME, 1, 0, "Frame on which the simulation gets cache protection enabled automatically (To prevent accidently cleaning it)."); + 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, REDRAWVIEW3D, "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."); + 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)) { diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 9c00d8b71bc..712c9ddc4a9 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -857,14 +857,16 @@ void make_editMesh() /* 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, (float) G.scene->r.cfra, stack_index)) + if(BKE_ptcache_id_exist((ID *)G.obedit, G.scene->r.cfra, stack_index)) { cloth_enabled = 1; - clmd->sim_parms->editedframe = (float) G.scene->r.cfra; + clmd->sim_parms->editedframe = G.scene->r.cfra; /* inverse matrix is not uptodate... */ Mat4Invert ( G.obedit->imat, G.obedit->obmat ); + + printf("make_editmesh --> cloth_enabled\n"); } } } @@ -1014,6 +1016,8 @@ void load_editMesh(void) ClothModifierData *clmd = NULL; Cloth *cloth = NULL; float temp[3], dt = 0.0; + + printf("loadmesh\n"); #ifdef WITH_VERSE if(em->vnode) { @@ -1102,6 +1106,7 @@ void load_editMesh(void) Mat4Invert ( G.obedit->imat, G.obedit->obmat ); dt = 1.0f / clmd->sim_parms->stepsPerFrame; } + printf("loadmesh --> tot: %d, num: %d\n", G.totvert, cloth->numverts); } } @@ -1110,6 +1115,7 @@ void load_editMesh(void) if(cloth_enabled) { + printf("loadmesh --> cloth_enabled\n"); VECCOPY(temp, cloth->verts[i].x); VECCOPY(cloth->verts[i].x, eve->co); @@ -1123,6 +1129,7 @@ void load_editMesh(void) */ if(oldverts) { VECCOPY(mvert->co, oldverts[i].co); + printf("loadmesh --> cloth_enabled oldverts\n"); } i++; } @@ -1159,12 +1166,22 @@ void load_editMesh(void) /* burn changes to cache */ if(cloth_enabled) { + 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 != (float) G.scene->r.cfra) + if(clmd->sim_parms->editedframe != G.scene->r.cfra) { - cloth_read_cache(G.obedit, clmd, (float) G.scene->r.cfra); + cloth_read_cache(G.obedit, clmd, G.scene->r.cfra); + } + } + else + { + if(modifiers_isClothEnabled(G.obedit)) { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(G.obedit, eModifierType_Cloth); + printf("loadmesh --> CLOTH_SIMSETTINGS_FLAG_RESET\n"); + /* only reset cloth when no cache was used */ + clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; } } @@ -1426,18 +1443,7 @@ void load_editMesh(void) if(me->id.us>1) { Base *base; for(base= G.scene->base.first; base; base= base->next) { - if(base->object->data==me) { - if(modifiers_isClothEnabled(base->object)) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(base->object, eModifierType_Cloth); - - /* only reset cloth when no cache was used */ - if(!cloth_enabled) - { - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - } - - } - + if(base->object->data==me) { base->object->softflag |= OB_SB_REDO; base->object->recalc |= OB_RECALC_DATA; } From 5da7f4df472f41997a1f424315f94d0d04b3dd30 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 29 Jan 2008 16:32:42 +0000 Subject: [PATCH 085/101] -= Cloth cleanup =- Fixes: - Cloth event refactor to solve 2 unknown cache bugs - Cloth vgroup refactor (faster + scalable stinnes now working) - Cloth + Collision modifier on one object crash - Editmode + faceextrude on baked cloth crash - Stiffness groups would get pinned - Correct scaled stiffness calculation - Fixes freeing error under some circumstances - Deactivating reset/cache freeing when in editmode - Autobaking setting doesn't get screwed up anymore - More than 1 collision object in a scene could explode - Pinning + not protected cache didn't reset cloth - Start simulation on first frame and not on 2nd - Maximum structstiff now correct (copy-paste error) - Loading file with baked cloth calculate the spring length correctly - Loading file behaviour improved with cache - Collision object is evaluated first (untested) - Debug output activated with rt>0 Be carefull: Files with some cloth cache or something should be regenerated. --- source/blender/blenkernel/BKE_cloth.h | 3 +- source/blender/blenkernel/intern/cloth.c | 213 +++++++++++-------- source/blender/blenkernel/intern/collision.c | 10 +- source/blender/blenkernel/intern/implicit.c | 95 ++++++--- source/blender/blenkernel/intern/modifier.c | 13 +- source/blender/blenloader/intern/readfile.c | 3 + source/blender/makesdna/DNA_cloth_types.h | 2 + source/blender/src/buttons_object.c | 21 +- source/blender/src/editmesh.c | 12 +- 9 files changed, 244 insertions(+), 128 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 1a3feed0a0c..80d09cde342 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -133,9 +133,10 @@ typedef enum 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_NEW = ( 1 << 6 ), // unsued, true if cloth was just 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 */ diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 0870bf2efa3..a99ac705c0b 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -153,7 +153,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->mass = 1.0f; clmd->sim_parms->stepsPerFrame = 5; clmd->sim_parms->sim_time = 1.0; - clmd->sim_parms->flags = CLOTH_SIMSETTINGS_FLAG_NEW; + clmd->sim_parms->flags = 0; clmd->sim_parms->solver_type = 0; clmd->sim_parms->preroll = 0; clmd->sim_parms->maxspringlen = 10; @@ -163,6 +163,7 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->lastcachedframe = 0; clmd->sim_parms->editedframe = 0; clmd->sim_parms->autoprotect = 25; + clmd->sim_parms->firstcachedframe = -1.0; clmd->coll_parms->self_friction = 5.0; clmd->coll_parms->friction = 10.0; @@ -520,20 +521,14 @@ int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) fclose(fp); - /* - // belongs to another location ?!? - if((clmd->sim_parms->solver_type == 0) && (ret!=0)) - { - implicit_set_positions(clmd); - } - */ - if(clmd->sim_parms->lastcachedframe < framenr) { + if(G.rt > 0) printf("cloth_read_cache problem: lnex - f#: %f, lastCF: %d\n", framenr, clmd->sim_parms->lastcachedframe); } } + if(G.rt > 0) printf("cloth_read_cache: %f\n", framenr); return ret; @@ -542,15 +537,15 @@ int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) { int stack_index = -1; - printf("cloth_clear_cache: %f\n", framenr); - /* - // belongs to another location ?!? - if(framenr>0) + // don't do anything as long as we're in editmode! + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE) { - cloth_read_cache(ob, clmd, framenr); + /* delete cache free request */ + clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; + + return; } - */ /* clear cache if specific frame cleaning requested or cache is not protected */ if((!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) || (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE)) @@ -558,11 +553,18 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); BKE_ptcache_id_clear((ID *)ob, PTCACHE_CLEAR_AFTER, framenr, stack_index); + + /* update last cached frame # */ + clmd->sim_parms->lastcachedframe = framenr; + + /* update first cached frame # */ + if((framenr < clmd->sim_parms->firstcachedframe) && (clmd->sim_parms->firstcachedframe >=0.0)) + clmd->sim_parms->firstcachedframe = -1.0; + + if(G.rt > 0) + printf("cloth_clear_cache: %f\n", framenr); } - /* update last cached frame # */ - clmd->sim_parms->lastcachedframe = framenr; - /* delete cache free request */ clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; @@ -575,10 +577,12 @@ void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) unsigned int a; Cloth *cloth = clmd->clothObject; + if(G.rt > 0) printf("cloth_write_cache: %f\n", framenr); if(!cloth) { + if(G.rt > 0) printf("cloth_write_cache: no cloth\n"); return; } @@ -588,6 +592,7 @@ void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) fp = BKE_ptcache_id_fopen((ID *)ob, 'w', framenr, stack_index); if(!fp) { + if(G.rt > 0) printf("cloth_write_cache: no fp\n"); return; } @@ -599,8 +604,14 @@ void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) fwrite(&cloth->verts[a].v, sizeof(float),3,fp); } + /* update last cached frame # */ clmd->sim_parms->lastcachedframe = MAX2(clmd->sim_parms->lastcachedframe, framenr); + /* update first cached frame # */ + if((clmd->sim_parms->firstcachedframe < 0.0) || ((framenr < clmd->sim_parms->firstcachedframe) && (clmd->sim_parms->firstcachedframe > 0.0))) + clmd->sim_parms->firstcachedframe = framenr; + + if(G.rt > 0) printf("lcf: %d, framenr: %f\n", clmd->sim_parms->lastcachedframe, framenr); fclose(fp); @@ -629,8 +640,18 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d MFace *mface = NULL; DerivedMesh *result = NULL; + if(G.rt > 0) printf("clothModifier_do start\n"); + /* we're getting called two times during file load, + resulting in a not valid G.relbase on the first time (cache makes problems) + --> just return back */ + if((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_LOADED)&& (!G.relbase_valid)) + { + clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_LOADED; + return dm; + } + result = CDDM_copy(dm); if(!result) @@ -656,6 +677,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_RESET) { cloth_free_modifier (ob, clmd); + if(G.rt > 0) printf("clothModifier_do CLOTH_SIMSETTINGS_FLAG_RESET\n"); } @@ -693,10 +715,12 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d if ( deltaTime == 1.0f ) cloth_write_cache(ob, clmd, framenr-1.0); */ + if(G.rt > 0) printf("cloth_from_object NO cloth_read_cache cloth_write_cache\n"); } else { + if(G.rt > 0) printf("cloth_from_object cloth_read_cache\n"); implicit_set_positions(clmd); @@ -707,33 +731,35 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d // only be active during a specific period: // that's "first frame" and "last frame" on GUI - /* + // TODO: enable later again after refactoring if ( current_time < clmd->sim_parms->firstframe ) { - return result; -} + return result; + } else if ( current_time > clmd->sim_parms->lastframe ) { - int stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); - - if(BKE_ptcache_id_exist((ID *)ob, clmd->sim_parms->lastcachedframe, stack_index)) - { - if(cloth_read_cache(ob, clmd, framenr)) - { + int stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); + + if(BKE_ptcache_id_exist((ID *)ob, clmd->sim_parms->lastcachedframe, stack_index)) + { + if(cloth_read_cache(ob, clmd, clmd->sim_parms->lastcachedframe)) + { + implicit_set_positions(clmd); + // Copy the result back to the object. - cloth_to_object (ob, clmd, result); -} -} - return result; -} - */ + cloth_to_object (ob, clmd, result); + } + } + return result; + } /* nice moving one frame forward */ if ( deltaTime == 1.0f ) { clmd->sim_parms->sim_time = current_time; + if(G.rt > 0) printf("clothModifier_do deltaTime=1\n"); if(!cloth_read_cache(ob, clmd, framenr)) @@ -766,14 +792,16 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d // check for autoprotection if(framenr >= clmd->sim_parms->autoprotect) { + if(G.rt > 0) printf("fr#: %f, auto: %d\n", framenr, clmd->sim_parms->autoprotect); clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; } - + if(G.rt > 0) printf("clothModifier_do deltaTime=1 cachewrite\n"); } else { + if(G.rt > 0) printf("clothModifier_do deltaTime=1 cacheread\n"); implicit_set_positions(clmd); } @@ -783,6 +811,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d } else if(deltaTime == 0.0f) { + if(G.rt > 0) printf("clothModifier_do deltaTime!=1 clmd->clothObject != NULL\n"); if(cloth_read_cache(ob, clmd, framenr)) { @@ -802,6 +831,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d } else { + if(G.rt > 0) printf("clothModifier_do deltaTime!=1 clmd->clothObject != NULL\n"); if(cloth_read_cache(ob, clmd, framenr)) { @@ -885,7 +915,7 @@ void cloth_free_modifier ( Object *ob, ClothModifierData *clmd ) void cloth_free_modifier_extern ( ClothModifierData *clmd ) { Cloth *cloth = NULL; - + if(G.rt > 0) printf("cloth_free_modifier_extern\n"); if ( !clmd ) @@ -895,6 +925,7 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd ) if ( cloth ) { + if(G.rt > 0) printf("cloth_free_modifier_extern in\n"); // If our solver provides a free function, call it @@ -1070,12 +1101,13 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d MVert *mvert = NULL; ClothVertex *verts = NULL; float tnull[3] = {0,0,0}; + int cache_there = 0; // If we have a clothObject, free it. if ( clmd->clothObject != NULL ) { cloth_free_modifier ( ob, clmd ); - + if(G.rt > 0) printf("cloth_free_modifier cloth_from_object\n"); } @@ -1098,66 +1130,73 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d cloth_from_mesh ( ob, clmd, dm ); - if ( clmd->clothObject != NULL ) + if((clmd->sim_parms->firstcachedframe < 0.0) || ((clmd->sim_parms->firstcachedframe >= 0.0) && (!cloth_read_cache(ob, clmd, clmd->sim_parms->firstcachedframe)))) { - // create springs - clmd->clothObject->springs = NULL; - clmd->clothObject->numsprings = -1; - - mvert = dm->getVertArray ( dm ); - verts = clmd->clothObject->verts; + // no cache there + cache_there = 0; + if(G.rt > 0) + printf("cache_there = 0\n"); + } + else + { + // we have a cache + cache_there = 1; + if(G.rt > 0) + printf("cache_there = 1, fcf: %d\n", clmd->sim_parms->firstcachedframe); + } + + // create springs + clmd->clothObject->springs = NULL; + clmd->clothObject->numsprings = -1; + + mvert = dm->getVertArray ( dm ); + verts = clmd->clothObject->verts; - // set initial values - for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) + // set initial values + for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) + { + if(!cache_there) { VECCOPY ( verts->x, mvert[i].co ); - - if(i<5) - printf("i: %d, verts->x[0]: %f\n", i, verts->x[0]); - Mat4MulVecfl ( ob->obmat, verts->x ); - - if(i<5) - printf("i: %d, verts->x[0]: %f\n\n", i, verts->x[0]); - - verts->mass = clmd->sim_parms->mass; - - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - verts->goal= clmd->sim_parms->defgoal; - else - verts->goal= 0.0f; - - verts->flags = 0; - VECCOPY ( verts->xold, verts->x ); - VECCOPY ( verts->xconst, verts->x ); - VECCOPY ( verts->txold, verts->x ); - VecMulf ( verts->v, 0.0f ); - - verts->impulse_count = 0; - VECCOPY ( verts->impulse, tnull ); } - // apply / set vertex groups - // has to be happen before springs are build! - cloth_apply_vgroup (clmd, dm); - - if ( !cloth_build_springs ( clmd, dm ) ) - { - cloth_free_modifier ( ob, clmd ); - modifier_setError ( & ( clmd->modifier ), "Can't build springs." ); - printf("cloth_free_modifier cloth_build_springs\n"); - return 0; - } - - // init our solver - if ( solvers [clmd->sim_parms->solver_type].init ) - solvers [clmd->sim_parms->solver_type].init ( ob, clmd ); + verts->mass = clmd->sim_parms->mass; - clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); - - return 1; + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + verts->goal= clmd->sim_parms->defgoal; + else + verts->goal= 0.0f; + + verts->flags = 0; + VECCOPY ( verts->xold, verts->x ); + VECCOPY ( verts->xconst, verts->x ); + VECCOPY ( verts->txold, verts->x ); + VecMulf ( verts->v, 0.0f ); + + verts->impulse_count = 0; + VECCOPY ( verts->impulse, tnull ); } - return 0; + + // apply / set vertex groups + // has to be happen before springs are build! + cloth_apply_vgroup (clmd, dm); + + if ( !cloth_build_springs ( clmd, dm ) ) + { + cloth_free_modifier ( ob, clmd ); + modifier_setError ( & ( clmd->modifier ), "Can't build springs." ); + printf("cloth_free_modifier cloth_build_springs\n"); + return 0; + } + + // init our solver + if ( solvers [clmd->sim_parms->solver_type].init ) + solvers [clmd->sim_parms->solver_type].init ( ob, clmd ); + + clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); + + return 1; } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 083ae5a2b46..0689b8b6dd2 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -561,7 +561,7 @@ int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierDa // Apply the impulse and increase impulse counters. - /* + /* // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms->friction*0.01, magtangent); VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); // VecMulf(vrel_t_pre, clmd->coll_parms->friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); @@ -1097,6 +1097,14 @@ int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) // verts come from clmd for(i = 0; i < numverts; i++) { + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + { + if(verts [i].goal >= SOFTGOALSNAP) + { + continue; + } + } + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); } //////////////////////////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 7ea48d6629b..cda56f5b601 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -82,7 +82,7 @@ void itend(void) double itval() { return ((double)_itend.QuadPart - - (double)_itstart.QuadPart)/((double)ifreq.QuadPart); + (double)_itstart.QuadPart)/((double)ifreq.QuadPart); } #else #include @@ -91,9 +91,9 @@ double itval() // #include // #include -static struct timeval _itstart, _itend; -static struct timezone itz; -void itstart(void) + static struct timeval _itstart, _itend; + static struct timezone itz; + void itstart(void) { gettimeofday(&_itstart, &itz); } @@ -331,7 +331,7 @@ DO_INLINE void cp_fmatrix(float to[3][3], float from[3][3]) DO_INLINE float det_fmatrix(float m[3][3]) { return m[0][0]*m[1][1]*m[2][2] + m[1][0]*m[2][1]*m[0][2] + m[0][1]*m[1][2]*m[2][0] - -m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2]; + -m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2]; } DO_INLINE void inverse_fmatrix(float to[3][3], float from[3][3]) { @@ -719,6 +719,9 @@ int implicit_init (Object *ob, ClothModifierData *clmd) ClothSpring *spring = NULL; Implicit_Data *id = NULL; LinkNode *search = NULL; + + if(G.rt > 0) + printf("implicit_init\n"); // init memory guard // MEMORY_BASE.first = MEMORY_BASE.last = NULL; @@ -776,7 +779,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) // dFdV_start[i].c = big_I[i].c = big_zero[i].c = id->A[i+cloth->numverts].c = id->dFdV[i+cloth->numverts].c = id->dFdX[i+cloth->numverts].c = - id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = spring->kl; + id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = spring->kl; spring->matrix_index = i + cloth->numverts; @@ -1023,7 +1026,7 @@ int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fma del_lfvector(p); del_lfvector(r); - // printf("iterations: %d\n", iterations); + printf("iterations: %d\n", iterations); return iterationsL) { - if((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) - && ((((length-L)*100.0f/L) > clmd->sim_parms->maxspringlen))) // cut spring! - { - s->flags |= CSPRING_FLAG_DEACTIVATE; - return; - } - } + if((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) + && ((((length-L)*100.0f/L) > clmd->sim_parms->maxspringlen))) // cut spring! + { + s->flags |= CSPRING_FLAG_DEACTIVATE; + return; + } + } */ mul_fvector_S(dir, extent, 1.0f/length); } @@ -1133,8 +1136,18 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, k = clmd->sim_parms->structural; - scaling = k + s->stiffness * (clmd->sim_parms->max_struct-k); + scaling = k + s->stiffness * ABS(clmd->sim_parms->max_struct-k); k = scaling; + + // printf("scaling: %f, stiffness: %f\n", k, s->stiffness); + /* + if((s->ij == 109) || (s->kl == 109)) + { + printf("length-L: %f, f: %f, len: %f, L: %f\n", length-L, (k*(length-L)), length, L); + printf("kl X-x: %f, f-y: %f, f-z: %f\n", X[s->kl][0], X[s->kl][1], X[s->kl][2]); + printf("ij X-x: %f, f-y: %f, f-z: %f\n\n", X[s->ij][0], X[s->ij][1], X[s->ij][2]); + } + */ mul_fvector_S(stretch_force, dir, (k*(length-L))); @@ -1157,7 +1170,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, k = clmd->sim_parms->bending; - scaling = k + s->stiffness * (clmd->sim_parms->max_bend-k); + scaling = k + s->stiffness * ABS(clmd->sim_parms->max_bend-k); cb = k = scaling; mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); @@ -1166,6 +1179,12 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, dfdx_spring_type2(s->dfdx, dir,length,L,k, cb); } } + /* + if((s->ij == 109) || (s->kl == 109)) + { + printf("type: %d, f-x: %f, f-y: %f, f-z: %f\n", s->type, s->f[0], s->f[1], s->f[2]); +} + */ } DO_INLINE void cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) @@ -1258,7 +1277,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec init_lfvector(lF, gravity, numverts); submul_lfvectorS(lF, lV, spring_air, numverts); - + /* do goal stuff */ if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { @@ -1275,22 +1294,24 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms->goalspring)-1.0f ; VECADDS(lF[i], lF[i], auxvect, -ks); - // calulate damping forces generated by goals + // calulate damping forces generated by goals + VECSUB(velgoal,verts[i].xold, verts[i].xconst); kd = clmd->sim_parms->goalfrict * 0.01f; // friction force scale taken from SB VECSUBADDSS(lF[i], velgoal, kd, lV[i], kd); + } } } - + /* handle external forces like wind */ if(effectors) { float speed[3] = {0.0f, 0.0f,0.0f}; float force[3]= {0.0f, 0.0f, 0.0f}; - #pragma omp parallel for private (i) shared(lF) +#pragma omp parallel for private (i) shared(lF) for(i = 0; i < cloth->numverts; i++) { float vertexnormal[3]={0,0,0}; @@ -1308,7 +1329,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec VECADDS(lF[i], lF[i], wind_normalized, -calculateVertexWindForce(speed, vertexnormal)); } } - + // calculate spring forces search = cloth->springs; while(search) @@ -1329,6 +1350,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); search = search->next; } + // printf("\n"); } void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv) @@ -1391,11 +1413,23 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase effectors= pdInitEffectors(ob,NULL); // calculate - cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); + cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); + + // printf("F -> x: %f, y: %f; z: %f\n\n", id->F[109][0], id->F[109][1], id->F[109][2]); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); + /* + printf("dt: %f\n", dt); + printf("Xnew -> x: %f, y: %f; z: %f\n", id->Xnew[109][0], id->Xnew[109][1], id->Xnew[109][2]); + printf("X -> x: %f, y: %f; z: %f\n", id->X[109][0], id->X[109][1], id->X[109][2]); + printf("Vnew -> x: %f, y: %f; z: %f\n\n", id->Vnew[109][0], id->Vnew[109][1], id->Vnew[109][2]); + */ + + // clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_ENABLED; + if(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) { // collisions @@ -1404,7 +1438,8 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // update verts to current positions for(i = 0; i < numverts; i++) { - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ + + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { if(verts [i].goal >= SOFTGOALSNAP) { @@ -1431,6 +1466,16 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase { if(result) { + + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + { + if(verts [i].goal >= SOFTGOALSNAP) + { + continue; + } + } + + // VECADD(verts[i].tx, verts[i].txold, verts[i].tv); VECCOPY(verts[i].txold, verts[i].tx); @@ -1515,5 +1560,7 @@ void implicit_set_positions (ClothModifierData *clmd) { VECCOPY(id->X[i], verts[i].x); VECCOPY(id->V[i], verts[i].v); - } + } + if(G.rt > 0) + printf("implicit_set_positions\n"); } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 475009c8fa6..7f378f136b6 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -4987,7 +4987,6 @@ static void clothModifier_updateDepgraph( Base *base; - /* TODO: this belongs to collision modifier */ if(clmd) { for(base = G.scene->base.first; base; base= base->next) @@ -4995,14 +4994,11 @@ static void clothModifier_updateDepgraph( Object *ob1= base->object; if(ob1 != ob) { - ClothModifierData *coll_clmd = (ClothModifierData *)modifiers_findByType(ob1, eModifierType_Cloth); + CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision); if(coll_clmd) - { - if (coll_clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) - { - DagNode *curNode = dag_get_node(forest, ob1); - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA); - } + { + DagNode *curNode = dag_get_node(forest, ob1); + dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA); } } } @@ -5220,6 +5216,7 @@ static void collisionModifier_deformVerts( dm->release(dm); } + /* Boolean */ static void booleanModifier_copyData(ModifierData *md, ModifierData *target) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a9d2e7d05a1..4feb8c00659 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3015,6 +3015,9 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) 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) { diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 93aa09db349..7d2ec9b96b4 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -82,6 +82,8 @@ typedef struct SimulationSettings 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; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 4f23d60cd67..e6046203c4f 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2352,6 +2352,10 @@ void do_object_panels(unsigned short event) 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; @@ -2372,6 +2376,10 @@ void do_object_panels(unsigned short event) 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; @@ -2386,6 +2394,10 @@ void do_object_panels(unsigned short event) 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); @@ -5211,8 +5223,8 @@ static void object_panel_cloth_II(Object *ob) if(clmd) { - uiDefButI(block, NUM, B_DIFF, "First Frame:", 10,160,150,20, &clmd->sim_parms->firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts"); - uiDefButI(block, NUM, B_DIFF, "Last Frame:", 160,160,150,20, &clmd->sim_parms->lastframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation stops"); + 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, ""); @@ -5244,6 +5256,7 @@ static void object_panel_cloth_II(Object *ob) { 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,300,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"); + uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Friction:", 10,40,300,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, ""); @@ -5330,9 +5343,9 @@ static void object_panel_cloth_III(Object *ob) 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, 1000.0, 0.01f, 0, "Maximum structural stiffness value"); + 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, 1000.0, 0.01f, 0, "Maximum bending 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) diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 712c9ddc4a9..94ac17ebd6c 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -862,10 +862,11 @@ void make_editMesh() 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"); } } @@ -1017,8 +1018,6 @@ void load_editMesh(void) Cloth *cloth = NULL; float temp[3], dt = 0.0; - printf("loadmesh\n"); - #ifdef WITH_VERSE if(em->vnode) { struct VNode *vnode = (VNode*)em->vnode; @@ -1106,6 +1105,7 @@ void load_editMesh(void) 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); } } @@ -1115,6 +1115,7 @@ void load_editMesh(void) if(cloth_enabled) { + if(G.rt > 0) printf("loadmesh --> cloth_enabled\n"); VECCOPY(temp, cloth->verts[i].x); @@ -1129,6 +1130,7 @@ void load_editMesh(void) */ if(oldverts) { VECCOPY(mvert->co, oldverts[i].co); + if(G.rt > 0) printf("loadmesh --> cloth_enabled oldverts\n"); } i++; @@ -1166,6 +1168,7 @@ void load_editMesh(void) /* 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); @@ -1174,14 +1177,17 @@ void load_editMesh(void) { 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; } } From 3a36304bd908f15a5a5605e6939698e73b41e8b7 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 7 May 2008 20:06:28 +0000 Subject: [PATCH 086/101] Resolved other bad files in branch, had to kick old bullet, will have to copy from trunk --- extern/bullet2/CMakeLists.txt | 46 - extern/bullet2/Makefile | 64 - .../bullet2/make/msvc_7_0/Bullet_vc7.vcproj | 921 ------------ extern/bullet2/readme.txt | 12 - extern/bullet2/src/Bullet-C-Api.h | 37 - .../BroadphaseCollision/btAxisSweep3.cpp | 38 - .../BroadphaseCollision/btAxisSweep3.h | 880 ------------ .../btBroadphaseInterface.h | 46 - .../BroadphaseCollision/btBroadphaseProxy.cpp | 17 - .../BroadphaseCollision/btBroadphaseProxy.h | 232 --- .../btCollisionAlgorithm.cpp | 23 - .../btCollisionAlgorithm.h | 77 - .../BroadphaseCollision/btDispatcher.cpp | 22 - .../BroadphaseCollision/btDispatcher.h | 99 -- .../btMultiSapBroadphase.cpp | 204 --- .../btMultiSapBroadphase.h | 119 -- .../btOverlappingPairCache.cpp | 474 ------ .../btOverlappingPairCache.h | 323 ----- .../btOverlappingPairCallback.h | 37 - .../btSimpleBroadphase.cpp | 312 ---- .../BroadphaseCollision/btSimpleBroadphase.h | 147 -- .../src/BulletCollision/CMakeLists.txt | 68 - .../SphereTriangleDetector.cpp | 200 --- .../SphereTriangleDetector.h | 49 - .../btCollisionConfiguration.h | 47 - .../CollisionDispatch/btCollisionCreateFunc.h | 46 - .../btCollisionDispatcher.cpp | 287 ---- .../CollisionDispatch/btCollisionDispatcher.h | 145 -- .../CollisionDispatch/btCollisionObject.cpp | 62 - .../CollisionDispatch/btCollisionObject.h | 349 ----- .../CollisionDispatch/btCollisionWorld.cpp | 370 ----- .../CollisionDispatch/btCollisionWorld.h | 259 ---- .../btCompoundCollisionAlgorithm.cpp | 142 -- .../btCompoundCollisionAlgorithm.h | 67 - .../btConvexConcaveCollisionAlgorithm.cpp | 314 ---- .../btConvexConcaveCollisionAlgorithm.h | 113 -- .../btConvexConvexAlgorithm.cpp | 249 ---- .../btConvexConvexAlgorithm.h | 77 - .../btDefaultCollisionConfiguration.cpp | 237 --- .../btDefaultCollisionConfiguration.h | 87 -- .../btEmptyCollisionAlgorithm.cpp | 34 - .../btEmptyCollisionAlgorithm.h | 50 - .../CollisionDispatch/btManifoldResult.cpp | 114 -- .../CollisionDispatch/btManifoldResult.h | 102 -- .../btSimulationIslandManager.cpp | 359 ----- .../btSimulationIslandManager.h | 69 - .../btSphereBoxCollisionAlgorithm.cpp | 260 ---- .../btSphereBoxCollisionAlgorithm.h | 67 - .../btSphereSphereCollisionAlgorithm.cpp | 93 -- .../btSphereSphereCollisionAlgorithm.h | 59 - .../btSphereTriangleCollisionAlgorithm.cpp | 82 -- .../btSphereTriangleCollisionAlgorithm.h | 62 - .../CollisionDispatch/btUnionFind.cpp | 84 -- .../CollisionDispatch/btUnionFind.h | 124 -- .../CollisionShapes/btBoxShape.cpp | 54 - .../CollisionShapes/btBoxShape.h | 323 ----- .../btBvhTriangleMeshShape.cpp | 200 --- .../CollisionShapes/btBvhTriangleMeshShape.h | 90 -- .../CollisionShapes/btCapsuleShape.cpp | 146 -- .../CollisionShapes/btCapsuleShape.h | 60 - .../CollisionShapes/btCollisionMargin.h | 26 - .../CollisionShapes/btCollisionShape.cpp | 85 -- .../CollisionShapes/btCollisionShape.h | 94 -- .../CollisionShapes/btCompoundShape.cpp | 107 -- .../CollisionShapes/btCompoundShape.h | 136 -- .../CollisionShapes/btConcaveShape.cpp | 28 - .../CollisionShapes/btConcaveShape.h | 50 - .../CollisionShapes/btConeShape.cpp | 133 -- .../CollisionShapes/btConeShape.h | 103 -- .../CollisionShapes/btConvexHullShape.cpp | 179 --- .../CollisionShapes/btConvexHullShape.h | 77 - .../CollisionShapes/btConvexInternalShape.cpp | 78 - .../CollisionShapes/btConvexInternalShape.h | 99 -- .../CollisionShapes/btConvexShape.cpp | 18 - .../CollisionShapes/btConvexShape.h | 77 - .../btConvexTriangleMeshShape.cpp | 205 --- .../btConvexTriangleMeshShape.h | 55 - .../CollisionShapes/btCylinderShape.cpp | 206 --- .../CollisionShapes/btCylinderShape.h | 138 -- .../CollisionShapes/btEmptyShape.cpp | 49 - .../CollisionShapes/btEmptyShape.h | 70 - .../btHeightfieldTerrainShape.cpp | 339 ----- .../btHeightfieldTerrainShape.h | 88 -- .../CollisionShapes/btMinkowskiSumShape.cpp | 57 - .../CollisionShapes/btMinkowskiSumShape.h | 62 - .../CollisionShapes/btMultiSphereShape.cpp | 148 -- .../CollisionShapes/btMultiSphereShape.h | 74 - .../CollisionShapes/btOptimizedBvh.cpp | 1181 --------------- .../CollisionShapes/btOptimizedBvh.h | 393 ----- .../btPolyhedralConvexShape.cpp | 148 -- .../CollisionShapes/btPolyhedralConvexShape.h | 93 -- .../CollisionShapes/btSphereShape.cpp | 77 - .../CollisionShapes/btSphereShape.h | 65 - .../CollisionShapes/btStaticPlaneShape.cpp | 105 -- .../CollisionShapes/btStaticPlaneShape.h | 61 - .../btStridingMeshInterface.cpp | 124 -- .../CollisionShapes/btStridingMeshInterface.h | 89 -- .../CollisionShapes/btTetrahedronShape.cpp | 195 --- .../CollisionShapes/btTetrahedronShape.h | 75 - .../CollisionShapes/btTriangleBuffer.cpp | 42 - .../CollisionShapes/btTriangleBuffer.h | 61 - .../CollisionShapes/btTriangleCallback.cpp | 28 - .../CollisionShapes/btTriangleCallback.h | 40 - .../btTriangleIndexVertexArray.cpp | 78 - .../btTriangleIndexVertexArray.h | 105 -- .../CollisionShapes/btTriangleMesh.cpp | 60 - .../CollisionShapes/btTriangleMesh.h | 75 - .../CollisionShapes/btTriangleMeshShape.cpp | 202 --- .../CollisionShapes/btTriangleMeshShape.h | 80 -- .../CollisionShapes/btTriangleShape.h | 179 --- .../CollisionShapes/btUniformScalingShape.cpp | 114 -- .../CollisionShapes/btUniformScalingShape.h | 86 -- extern/bullet2/src/BulletCollision/Doxyfile | 746 ---------- .../btContinuousConvexCollision.cpp | 210 --- .../btContinuousConvexCollision.h | 52 - .../NarrowPhaseCollision/btConvexCast.cpp | 20 - .../NarrowPhaseCollision/btConvexCast.h | 71 - .../btConvexPenetrationDepthSolver.h | 43 - .../btDiscreteCollisionDetectorInterface.h | 88 -- .../NarrowPhaseCollision/btGjkConvexCast.cpp | 174 --- .../NarrowPhaseCollision/btGjkConvexCast.h | 50 - .../NarrowPhaseCollision/btGjkEpa.cpp | 628 -------- .../NarrowPhaseCollision/btGjkEpa.h | 53 - .../btGjkEpaPenetrationDepthSolver.cpp | 50 - .../btGjkEpaPenetrationDepthSolver.h | 39 - .../btGjkPairDetector.cpp | 299 ---- .../NarrowPhaseCollision/btGjkPairDetector.h | 85 -- .../NarrowPhaseCollision/btManifoldPoint.h | 99 -- .../btMinkowskiPenetrationDepthSolver.cpp | 333 ----- .../btMinkowskiPenetrationDepthSolver.h | 37 - .../btPersistentManifold.cpp | 248 ---- .../btPersistentManifold.h | 179 --- .../NarrowPhaseCollision/btPointCollector.h | 61 - .../btRaycastCallback.cpp | 101 -- .../NarrowPhaseCollision/btRaycastCallback.h | 42 - .../btSimplexSolverInterface.h | 64 - .../btSubSimplexConvexCast.cpp | 139 -- .../btSubSimplexConvexCast.h | 50 - .../btVoronoiSimplexSolver.cpp | 607 -------- .../btVoronoiSimplexSolver.h | 157 -- .../src/BulletCollision/ibmsdk/Makefile | 95 -- .../bullet2/src/BulletDynamics/CMakeLists.txt | 22 - .../btConeTwistConstraint.cpp | 286 ---- .../ConstraintSolver/btConeTwistConstraint.h | 126 -- .../ConstraintSolver/btConstraintSolver.h | 52 - .../ConstraintSolver/btContactConstraint.cpp | 417 ------ .../ConstraintSolver/btContactConstraint.h | 122 -- .../ConstraintSolver/btContactSolverInfo.h | 51 - .../btGeneric6DofConstraint.cpp | 497 ------- .../btGeneric6DofConstraint.h | 433 ------ .../ConstraintSolver/btHingeConstraint.cpp | 400 ------ .../ConstraintSolver/btHingeConstraint.h | 130 -- .../ConstraintSolver/btJacobianEntry.h | 156 -- .../btPoint2PointConstraint.cpp | 117 -- .../btPoint2PointConstraint.h | 89 -- .../btSequentialImpulseConstraintSolver.cpp | 1266 ----------------- .../btSequentialImpulseConstraintSolver.h | 126 -- .../btSolve2LinearConstraint.cpp | 255 ---- .../btSolve2LinearConstraint.h | 107 -- .../ConstraintSolver/btSolverBody.h | 76 - .../ConstraintSolver/btSolverConstraint.h | 69 - .../ConstraintSolver/btTypedConstraint.cpp | 56 - .../ConstraintSolver/btTypedConstraint.h | 112 -- .../BulletDynamics/Dynamics/Bullet-C-API.cpp | 120 -- .../BulletDynamics/Dynamics/Bullet-C-Api.cpp | 91 -- .../Dynamics/btContinuousDynamicsWorld.cpp | 194 --- .../Dynamics/btContinuousDynamicsWorld.h | 46 - .../Dynamics/btDiscreteDynamicsWorld.cpp | 1004 ------------- .../Dynamics/btDiscreteDynamicsWorld.h | 164 --- .../BulletDynamics/Dynamics/btDynamicsWorld.h | 89 -- .../BulletDynamics/Dynamics/btRigidBody.cpp | 350 ----- .../src/BulletDynamics/Dynamics/btRigidBody.h | 385 ----- .../Dynamics/btSimpleDynamicsWorld.cpp | 217 --- .../Dynamics/btSimpleDynamicsWorld.h | 86 -- .../Vehicle/btRaycastVehicle.cpp | 738 ---------- .../BulletDynamics/Vehicle/btRaycastVehicle.h | 201 --- .../Vehicle/btVehicleRaycaster.h | 35 - .../BulletDynamics/Vehicle/btWheelInfo.cpp | 56 - .../src/BulletDynamics/Vehicle/btWheelInfo.h | 116 -- .../src/BulletDynamics/ibmsdk/Makefile | 45 - extern/bullet2/src/CMakeLists.txt | 1 - extern/bullet2/src/LinearMath/CMakeLists.txt | 11 - extern/bullet2/src/LinearMath/btAabbUtil2.h | 125 -- .../src/LinearMath/btAlignedAllocator.cpp | 155 -- .../src/LinearMath/btAlignedAllocator.h | 94 -- .../src/LinearMath/btAlignedObjectArray.h | 386 ----- .../src/LinearMath/btDefaultMotionState.h | 38 - .../bullet2/src/LinearMath/btGeometryUtil.cpp | 178 --- .../bullet2/src/LinearMath/btGeometryUtil.h | 41 - extern/bullet2/src/LinearMath/btIDebugDraw.h | 102 -- extern/bullet2/src/LinearMath/btList.h | 73 - extern/bullet2/src/LinearMath/btMatrix3x3.h | 410 ------ extern/bullet2/src/LinearMath/btMinMax.h | 69 - extern/bullet2/src/LinearMath/btMotionState.h | 40 - extern/bullet2/src/LinearMath/btPoint3.h | 24 - .../bullet2/src/LinearMath/btPoolAllocator.h | 94 -- extern/bullet2/src/LinearMath/btQuadWord.h | 135 -- extern/bullet2/src/LinearMath/btQuaternion.h | 321 ----- extern/bullet2/src/LinearMath/btQuickprof.cpp | 38 - extern/bullet2/src/LinearMath/btQuickprof.h | 712 --------- extern/bullet2/src/LinearMath/btRandom.h | 42 - extern/bullet2/src/LinearMath/btScalar.h | 394 ----- extern/bullet2/src/LinearMath/btSimdMinMax.h | 41 - extern/bullet2/src/LinearMath/btStackAlloc.h | 115 -- extern/bullet2/src/LinearMath/btTransform.h | 200 --- .../bullet2/src/LinearMath/btTransformUtil.h | 142 -- extern/bullet2/src/LinearMath/btVector3.h | 452 ------ extern/bullet2/src/LinearMath/ibmsdk/Makefile | 30 - extern/bullet2/src/Makefile | 71 - extern/bullet2/src/SConscript | 98 -- extern/bullet2/src/btBulletCollisionCommon.h | 63 - extern/bullet2/src/btBulletDynamicsCommon.h | 44 - extern/bullet2/src/ibmsdk/Makefile | 10 - source/blender/include/BIF_imasel.h | 1 + source/blender/include/BSE_drawview.h | 2 +- source/blender/include/BSE_filesel.h | 1 + source/blender/makesdna/DNA_userdef_types.h | 5 +- 217 files changed, 6 insertions(+), 34741 deletions(-) delete mode 100644 extern/bullet2/CMakeLists.txt delete mode 100644 extern/bullet2/Makefile delete mode 100644 extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj delete mode 100644 extern/bullet2/readme.txt delete mode 100644 extern/bullet2/src/Bullet-C-Api.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h delete mode 100644 extern/bullet2/src/BulletCollision/CMakeLists.txt delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h delete mode 100644 extern/bullet2/src/BulletCollision/Doxyfile delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h delete mode 100644 extern/bullet2/src/BulletCollision/ibmsdk/Makefile delete mode 100644 extern/bullet2/src/BulletDynamics/CMakeLists.txt delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h delete mode 100644 extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h delete mode 100644 extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h delete mode 100644 extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h delete mode 100644 extern/bullet2/src/BulletDynamics/ibmsdk/Makefile delete mode 100644 extern/bullet2/src/CMakeLists.txt delete mode 100644 extern/bullet2/src/LinearMath/CMakeLists.txt delete mode 100644 extern/bullet2/src/LinearMath/btAabbUtil2.h delete mode 100644 extern/bullet2/src/LinearMath/btAlignedAllocator.cpp delete mode 100644 extern/bullet2/src/LinearMath/btAlignedAllocator.h delete mode 100644 extern/bullet2/src/LinearMath/btAlignedObjectArray.h delete mode 100644 extern/bullet2/src/LinearMath/btDefaultMotionState.h delete mode 100644 extern/bullet2/src/LinearMath/btGeometryUtil.cpp delete mode 100644 extern/bullet2/src/LinearMath/btGeometryUtil.h delete mode 100644 extern/bullet2/src/LinearMath/btIDebugDraw.h delete mode 100644 extern/bullet2/src/LinearMath/btList.h delete mode 100644 extern/bullet2/src/LinearMath/btMatrix3x3.h delete mode 100644 extern/bullet2/src/LinearMath/btMinMax.h delete mode 100644 extern/bullet2/src/LinearMath/btMotionState.h delete mode 100644 extern/bullet2/src/LinearMath/btPoint3.h delete mode 100755 extern/bullet2/src/LinearMath/btPoolAllocator.h delete mode 100644 extern/bullet2/src/LinearMath/btQuadWord.h delete mode 100644 extern/bullet2/src/LinearMath/btQuaternion.h delete mode 100644 extern/bullet2/src/LinearMath/btQuickprof.cpp delete mode 100644 extern/bullet2/src/LinearMath/btQuickprof.h delete mode 100644 extern/bullet2/src/LinearMath/btRandom.h delete mode 100644 extern/bullet2/src/LinearMath/btScalar.h delete mode 100644 extern/bullet2/src/LinearMath/btSimdMinMax.h delete mode 100644 extern/bullet2/src/LinearMath/btStackAlloc.h delete mode 100644 extern/bullet2/src/LinearMath/btTransform.h delete mode 100644 extern/bullet2/src/LinearMath/btTransformUtil.h delete mode 100644 extern/bullet2/src/LinearMath/btVector3.h delete mode 100644 extern/bullet2/src/LinearMath/ibmsdk/Makefile delete mode 100644 extern/bullet2/src/Makefile delete mode 100644 extern/bullet2/src/SConscript delete mode 100644 extern/bullet2/src/btBulletCollisionCommon.h delete mode 100644 extern/bullet2/src/btBulletDynamicsCommon.h delete mode 100644 extern/bullet2/src/ibmsdk/Makefile diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt deleted file mode 100644 index 19dc6e2ba77..00000000000 --- a/extern/bullet2/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -# $Id$ -# ***** 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, Blender Foundation -# All rights reserved. -# -# The Original Code is: all of this file. -# -# Contributor(s): Jacques Beaurai, Erwin Coumans -# -# ***** END GPL/BL DUAL LICENSE BLOCK ***** - -SET(INC . src) - -FILE(GLOB SRC - src/LinearMath/*.cpp - src/BulletCollision/BroadphaseCollision/*.cpp - src/BulletCollision/CollisionShapes/*.cpp - src/BulletCollision/NarrowPhaseCollision/*.cpp - src/BulletCollision//CollisionDispatch/*.cpp - src/BulletDynamics/ConstraintSolver/*.cpp - src/BulletDynamics/Vehicle/*.cpp - src/BulletDynamics/Dynamics/*.cpp -) - -ADD_DEFINITIONS(-D_LIB) - -BLENDERLIB(extern_bullet "${SRC}" "${INC}") -#, libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) diff --git a/extern/bullet2/Makefile b/extern/bullet2/Makefile deleted file mode 100644 index be242c290ff..00000000000 --- a/extern/bullet2/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -# -# $Id$ -# -# ***** 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) 2002 by Hans Lambermont -# All rights reserved. -# -# The Original Code is: all of this file. -# -# Contributor(s): -# -# ***** END GPL/BL DUAL LICENSE BLOCK ***** -LIBNAME = bullet2 -include nan_definitions.mk -SOURCEDIR = extern/$(LIBNAME) -DIR = $(OCGDIR)/extern/$(LIBNAME) -DIRS = src -DISTDIR = src - -BULLETDIRS = \ -LinearMath \ -BulletCollision/BroadphaseCollision \ -BulletCollision/CollisionShapes \ -BulletCollision/NarrowPhaseCollision \ -BulletCollision//CollisionDispatch \ -BulletDynamics/ConstraintSolver \ -BulletDynamics/Vehicle \ -BulletDynamics/Dynamics - -include nan_subdirs.mk - -CP = $(NANBLENDERHOME)/intern/tools/cpifdiff.sh - -install: all debug - @[ -d $(NAN_BULLET2) ] || mkdir -p $(NAN_BULLET2) - @[ -d $(NAN_BULLET2)/include ] || mkdir -p $(NAN_BULLET2)/include - @for i in $(BULLETDIRS); do \ - [ -d $(NAN_BULLET2)/include/$$i ] || mkdir -p $(NAN_BULLET2)/include/$$i; \ - $(CP) $(DISTDIR)/$$i/*.h $(NAN_BULLET2)/include/$$i; \ - done - @[ -d $(NAN_BULLET2)/lib ] || mkdir -p $(NAN_BULLET2)/lib - @$(CP) $(DISTDIR)/*.h $(NAN_BULLET2)/include - @$(CP) $(OCGDIR)/extern/bullet2/libbullet2.a $(NAN_BULLET2)/lib -ifeq ($(OS),darwin) - ranlib $(NAN_BULLET2)/lib/libbullet2.a -endif diff --git a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj deleted file mode 100644 index 87a1e4546d1..00000000000 --- a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj +++ /dev/null @@ -1,921 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/extern/bullet2/readme.txt b/extern/bullet2/readme.txt deleted file mode 100644 index 4d1a4c11706..00000000000 --- a/extern/bullet2/readme.txt +++ /dev/null @@ -1,12 +0,0 @@ - -*** These files in extern/bullet2 are NOT part of the Blender build yet *** - -This is the new refactored version of Bullet physics library version 2.x - -Soon this will replace the old Bullet version in extern/bullet. -First the integration in Blender Game Engine needs to be updated. -Once that is done all build systems can be updated to use/build extern/bullet2 files. - -Questions? mail blender at erwincoumans.com, or check the bf-blender mailing list. -Thanks, -Erwin diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h deleted file mode 100644 index 078dcae63bb..00000000000 --- a/extern/bullet2/src/Bullet-C-Api.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -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 - diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp deleted file mode 100644 index d7eea33ea41..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp +++ /dev/null @@ -1,38 +0,0 @@ - -//Bullet Continuous Collision Detection and Physics Library -//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - - -// -// btAxisSweep3 -// -// Copyright (c) 2006 Simon Hobbs -// -// 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. -#include "btAxisSweep3.h" - -#include - -btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache) -:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache) -{ - // 1 handle is reserved as sentinel - btAssert(maxHandles > 1 && maxHandles < 32767); - -} - - -bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache ) -:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache) -{ - // 1 handle is reserved as sentinel - btAssert(maxHandles > 1 && maxHandles < 2147483647); -} diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h deleted file mode 100644 index d36df6e6621..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h +++ /dev/null @@ -1,880 +0,0 @@ -//Bullet Continuous Collision Detection and Physics Library -//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -// -// btAxisSweep3.h -// -// Copyright (c) 2006 Simon Hobbs -// -// 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. - -#ifndef AXIS_SWEEP_3_H -#define AXIS_SWEEP_3_H - -#include "LinearMath/btPoint3.h" -#include "LinearMath/btVector3.h" -#include "btOverlappingPairCache.h" -#include "btBroadphaseInterface.h" -#include "btBroadphaseProxy.h" -#include "btOverlappingPairCallback.h" - -//#define DEBUG_BROADPHASE 1 - -/// btAxisSweep3Internal is an internal template class that implements sweep and prune. -/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead. -template -class btAxisSweep3Internal : public btBroadphaseInterface -{ -protected: - - BP_FP_INT_TYPE m_bpHandleMask; - BP_FP_INT_TYPE m_handleSentinel; - -public: - - - class Edge - { - public: - BP_FP_INT_TYPE m_pos; // low bit is min/max - BP_FP_INT_TYPE m_handle; - - BP_FP_INT_TYPE IsMax() const {return m_pos & 1;} - }; - -public: - ATTRIBUTE_ALIGNED16(class) Handle : public btBroadphaseProxy - { - public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - // indexes into the edge arrays - BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12 -// BP_FP_INT_TYPE m_uniqueId; - BP_FP_INT_TYPE m_pad; - - //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject - - SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} - SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} - }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry - - -protected: - btPoint3 m_worldAabbMin; // overall system bounds - btPoint3 m_worldAabbMax; // overall system bounds - - btVector3 m_quantize; // scaling factor for quantization - - BP_FP_INT_TYPE m_numHandles; // number of active handles - BP_FP_INT_TYPE m_maxHandles; // max number of handles - Handle* m_pHandles; // handles pool - BP_FP_INT_TYPE m_firstFreeHandle; // free handles list - - Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries) - - btOverlappingPairCache* m_pairCache; - - ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. - btOverlappingPairCallback* m_userPairCallback; - - bool m_ownsPairCache; - - int m_invalidPair; - - // allocation/deallocation - BP_FP_INT_TYPE allocHandle(); - void freeHandle(BP_FP_INT_TYPE handle); - - - bool testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB); - -#ifdef DEBUG_BROADPHASE - void debugPrintAxis(int axis,bool checkCardinality=true); -#endif //DEBUG_BROADPHASE - - //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB); - //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB); - - void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const; - - void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); - void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); - void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); - void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); - -public: - - btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0); - - virtual ~btAxisSweep3Internal(); - - - virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - - BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher); - void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher); - void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher); - SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} - - void processAllOverlappingPairs(btOverlapCallback* callback); - - //Broadphase Interface - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher); - virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); - - bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - - btOverlappingPairCache* getOverlappingPairCache() - { - return m_pairCache; - } - const btOverlappingPairCache* getOverlappingPairCache() const - { - return m_pairCache; - } - - void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback) - { - m_userPairCallback = pairCallback; - } - const btOverlappingPairCallback* getOverlappingPairUserCallback() const - { - return m_userPairCallback; - } -}; - -//////////////////////////////////////////////////////////////////// - - - - -#ifdef DEBUG_BROADPHASE -#include - -template -void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) -{ - int numEdges = m_pHandles[0].m_maxEdges[axis]; - printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); - - int i; - for (i=0;im_handle); - int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; - char beginOrEnd; - beginOrEnd=pEdge->IsMax()?'E':'B'; - printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); - } - - if (checkCardinality) - assert(numEdges == m_numHandles*2+1); -} -#endif //DEBUG_BROADPHASE - -template -btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher) -{ - (void)shapeType; - BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher); - - Handle* handle = getHandle(handleId); - - return handle; -} - - - -template -void btAxisSweep3Internal::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) -{ - Handle* handle = static_cast(proxy); - removeHandle(handle->m_uniqueId,dispatcher); -} - -template -void btAxisSweep3Internal::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) -{ - Handle* handle = static_cast(proxy); - updateHandle(handle->m_uniqueId,aabbMin,aabbMax,dispatcher); - -} - - - - - -template -btAxisSweep3Internal::btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE maxHandles, btOverlappingPairCache* pairCache ) -:m_bpHandleMask(handleMask), -m_handleSentinel(handleSentinel), -m_pairCache(pairCache), -m_userPairCallback(0), -m_ownsPairCache(false), -m_invalidPair(0) -{ - if (!m_pairCache) - { - void* ptr = btAlignedAlloc(sizeof(btOverlappingPairCache),16); - m_pairCache = new(ptr) btOverlappingPairCache(); - m_ownsPairCache = true; - } - - //assert(bounds.HasVolume()); - - // init bounds - m_worldAabbMin = worldAabbMin; - m_worldAabbMax = worldAabbMax; - - btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; - - BP_FP_INT_TYPE maxInt = m_handleSentinel; - - m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; - - // allocate handles buffer and put all handles on free list - void* ptr = btAlignedAlloc(sizeof(Handle)*maxHandles,16); - m_pHandles = new(ptr) Handle[maxHandles]; - m_maxHandles = maxHandles; - m_numHandles = 0; - - // handle 0 is reserved as the null index, and is also used as the sentinel - m_firstFreeHandle = 1; - { - for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) - m_pHandles[i].SetNextFree(i + 1); - m_pHandles[maxHandles - 1].SetNextFree(0); - } - - { - // allocate edge buffers - for (int i = 0; i < 3; i++) - { - void* ptr = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16); - m_pEdges[i] = new(ptr) Edge[maxHandles * 2]; - } - } - //removed overlap management - - // make boundary sentinels - - m_pHandles[0].m_clientObject = 0; - - for (int axis = 0; axis < 3; axis++) - { - m_pHandles[0].m_minEdges[axis] = 0; - m_pHandles[0].m_maxEdges[axis] = 1; - - m_pEdges[axis][0].m_pos = 0; - m_pEdges[axis][0].m_handle = 0; - m_pEdges[axis][1].m_pos = m_handleSentinel; - m_pEdges[axis][1].m_handle = 0; -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - - } - -} - -template -btAxisSweep3Internal::~btAxisSweep3Internal() -{ - - for (int i = 2; i >= 0; i--) - { - btAlignedFree(m_pEdges[i]); - } - btAlignedFree(m_pHandles); - - if (m_ownsPairCache) - { - m_pairCache->~btOverlappingPairCache(); - btAlignedFree(m_pairCache); - } -} - -template -void btAxisSweep3Internal::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const -{ - btPoint3 clampedPoint(point); - - - - clampedPoint.setMax(m_worldAabbMin); - clampedPoint.setMin(m_worldAabbMax); - - btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; - out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax); - out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax); - out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax); - -} - - -template -BP_FP_INT_TYPE btAxisSweep3Internal::allocHandle() -{ - assert(m_firstFreeHandle); - - BP_FP_INT_TYPE handle = m_firstFreeHandle; - m_firstFreeHandle = getHandle(handle)->GetNextFree(); - m_numHandles++; - - return handle; -} - -template -void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle) -{ - assert(handle > 0 && handle < m_maxHandles); - - getHandle(handle)->SetNextFree(m_firstFreeHandle); - m_firstFreeHandle = handle; - - m_numHandles--; -} - - -template -BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher) -{ - // quantize the bounds - BP_FP_INT_TYPE min[3], max[3]; - quantize(min, aabbMin, 0); - quantize(max, aabbMax, 1); - - // allocate a handle - BP_FP_INT_TYPE handle = allocHandle(); - - - Handle* pHandle = getHandle(handle); - - pHandle->m_uniqueId = handle; - //pHandle->m_pOverlaps = 0; - pHandle->m_clientObject = pOwner; - pHandle->m_collisionFilterGroup = collisionFilterGroup; - pHandle->m_collisionFilterMask = collisionFilterMask; - - // compute current limit of edge arrays - BP_FP_INT_TYPE limit = m_numHandles * 2; - - - // insert new edges just inside the max boundary edge - for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) - { - - m_pHandles[0].m_maxEdges[axis] += 2; - - m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; - - m_pEdges[axis][limit - 1].m_pos = min[axis]; - m_pEdges[axis][limit - 1].m_handle = handle; - - m_pEdges[axis][limit].m_pos = max[axis]; - m_pEdges[axis][limit].m_handle = handle; - - pHandle->m_minEdges[axis] = limit - 1; - pHandle->m_maxEdges[axis] = limit; - } - - // now sort the new edges to their correct position - sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false); - sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false); - sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false); - sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false); - sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true); - sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true); - - - return handle; -} - - -template -void btAxisSweep3Internal::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher) -{ - - Handle* pHandle = getHandle(handle); - - //explicitly remove the pairs containing the proxy - //we could do it also in the sortMinUp (passing true) - //todo: compare performance - m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher); - - - // compute current limit of edge arrays - int limit = m_numHandles * 2; - - int axis; - - for (axis = 0;axis<3;axis++) - { - m_pHandles[0].m_maxEdges[axis] -= 2; - } - - // remove the edges by sorting them up to the end of the list - for ( axis = 0; axis < 3; axis++) - { - Edge* pEdges = m_pEdges[axis]; - BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; - pEdges[max].m_pos = m_handleSentinel; - - sortMaxUp(axis,max,dispatcher,false); - - - BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; - pEdges[i].m_pos = m_handleSentinel; - - - sortMinUp(axis,i,dispatcher,false); - - pEdges[limit-1].m_handle = 0; - pEdges[limit-1].m_pos = m_handleSentinel; - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis,false); -#endif //DEBUG_BROADPHASE - - - } - - - // free the handle - freeHandle(handle); - - -} - -extern int gOverlappingPairs; -#include - -template -void btAxisSweep3Internal::calculateOverlappingPairs(btDispatcher* dispatcher) -{ -#ifdef USE_LAZY_REMOVAL - - if (m_ownsPairCache) - { - - btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); - - //perform a sort, to find duplicates and to sort 'invalid' pairs to the end - overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - - - int i; - - btBroadphasePair previousPair; - previousPair.m_pProxy0 = 0; - previousPair.m_pProxy1 = 0; - previousPair.m_algorithm = 0; - - - for (i=0;iprocessOverlap(pair); - } else - { - needsRemoval = true; - } - } else - { - //remove duplicate - needsRemoval = true; - //should have no algorithm - btAssert(!pair.m_algorithm); - } - - if (needsRemoval) - { - m_pairCache->cleanOverlappingPair(pair,dispatcher); - - // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); - // m_overlappingPairArray.pop_back(); - pair.m_pProxy0 = 0; - pair.m_pProxy1 = 0; - m_invalidPair++; - gOverlappingPairs--; - } - - } - - ///if you don't like to skip the invalid pairs in the array, execute following code: - #define CLEAN_INVALID_PAIRS 1 - #ifdef CLEAN_INVALID_PAIRS - - //perform a sort, to sort 'invalid' pairs to the end - overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - #endif//CLEAN_INVALID_PAIRS - - //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); - } -#endif //USE_LAZY_REMOVAL - - - - -} - - -template -bool btAxisSweep3Internal::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - const Handle* pHandleA = static_cast(proxy0); - const Handle* pHandleB = static_cast(proxy1); - - //optimization 1: check the array index (memory address), instead of the m_pos - - for (int axis = 0; axis < 3; axis++) - { - if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || - pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) - { - return false; - } - } - return true; -} - -template -bool btAxisSweep3Internal::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB) -{ - //optimization 1: check the array index (memory address), instead of the m_pos - - for (int axis = 0; axis < 3; axis++) - { - if (axis != ignoreAxis) - { - if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || - pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) - { - return false; - } - } - } - - //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization) - - /*for (int axis = 0; axis < 3; axis++) - { - if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos || - m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos) - { - return false; - } - } - */ - - return true; -} - -template -void btAxisSweep3Internal::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher) -{ -// assert(bounds.IsFinite()); - //assert(bounds.HasVolume()); - - Handle* pHandle = getHandle(handle); - - // quantize the new bounds - BP_FP_INT_TYPE min[3], max[3]; - quantize(min, aabbMin, 0); - quantize(max, aabbMax, 1); - - // update changed edges - for (int axis = 0; axis < 3; axis++) - { - BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; - BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; - - int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; - int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; - - m_pEdges[axis][emin].m_pos = min[axis]; - m_pEdges[axis][emax].m_pos = max[axis]; - - // expand (only adds overlaps) - if (dmin < 0) - sortMinDown(axis, emin,dispatcher,true); - - if (dmax > 0) - sortMaxUp(axis, emax,dispatcher,true); - - // shrink (only removes overlaps) - if (dmin > 0) - sortMinUp(axis, emin,dispatcher,true); - - if (dmax < 0) - sortMaxDown(axis, emax,dispatcher,true); - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - } - - -} - - - - -// sorting a min edge downwards can only ever *add* overlaps -template -void btAxisSweep3Internal::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) -{ - - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pPrev = pEdge - 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pEdge->m_pos < pPrev->m_pos) - { - Handle* pHandlePrev = getHandle(pPrev->m_handle); - - if (pPrev->IsMax()) - { - // if previous edge is a maximum check the bounds and add an overlap if necessary - if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev)) - { - m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev); - if (m_userPairCallback) - m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev); - - //AddOverlap(pEdge->m_handle, pPrev->m_handle); - - } - - // update edge reference in other handle - pHandlePrev->m_maxEdges[axis]++; - } - else - pHandlePrev->m_minEdges[axis]++; - - pHandleEdge->m_minEdges[axis]--; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pPrev; - *pPrev = swap; - - // decrement - pEdge--; - pPrev--; - } - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - -} - -// sorting a min edge upwards can only ever *remove* overlaps -template -void btAxisSweep3Internal::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) -{ - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pNext = pEdge + 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) - { - Handle* pHandleNext = getHandle(pNext->m_handle); - - if (pNext->IsMax()) - { -#ifndef USE_LAZY_REMOVAL - // if next edge is maximum remove any overlap between the two handles - if (updateOverlaps) - { - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pNext->m_handle); - - m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); - if (m_userPairCallback) - m_userPairCallback->removeOverlappingPair(handle0,handle1); - - } -#endif //USE_LAZY_REMOVAL - - // update edge reference in other handle - pHandleNext->m_maxEdges[axis]--; - } - else - pHandleNext->m_minEdges[axis]--; - - pHandleEdge->m_minEdges[axis]++; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pNext; - *pNext = swap; - - // increment - pEdge++; - pNext++; - } - - -} - -// sorting a max edge downwards can only ever *remove* overlaps -template -void btAxisSweep3Internal::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) -{ - - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pPrev = pEdge - 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pEdge->m_pos < pPrev->m_pos) - { - Handle* pHandlePrev = getHandle(pPrev->m_handle); - - if (!pPrev->IsMax()) - { - // if previous edge was a minimum remove any overlap between the two handles - if (updateOverlaps) - { - //this is done during the overlappingpairarray iteration/narrowphase collision -#ifndef USE_LAZY_REMOVAL - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pPrev->m_handle); - m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); - if (m_userPairCallback) - m_userPairCallback->removeOverlappingPair(handle0,handle1); - -#endif //USE_LAZY_REMOVAL - - } - - // update edge reference in other handle - pHandlePrev->m_minEdges[axis]++;; - } - else - pHandlePrev->m_maxEdges[axis]++; - - pHandleEdge->m_maxEdges[axis]--; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pPrev; - *pPrev = swap; - - // decrement - pEdge--; - pPrev--; - } - - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - -} - -// sorting a max edge upwards can only ever *add* overlaps -template -void btAxisSweep3Internal::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) -{ - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pNext = pEdge + 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) - { - Handle* pHandleNext = getHandle(pNext->m_handle); - - if (!pNext->IsMax()) - { - // if next edge is a minimum check the bounds and add an overlap if necessary - if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext)) - { - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pNext->m_handle); - m_pairCache->addOverlappingPair(handle0,handle1); - if (m_userPairCallback) - m_userPairCallback->addOverlappingPair(handle0,handle1); - } - - // update edge reference in other handle - pHandleNext->m_minEdges[axis]--; - } - else - pHandleNext->m_maxEdges[axis]--; - - pHandleEdge->m_maxEdges[axis]++; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pNext; - *pNext = swap; - - // increment - pEdge++; - pNext++; - } - -} - - - -//////////////////////////////////////////////////////////////////// - - -/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. -/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats. -/// For large worlds and many objects, use bt32BitAxisSweep3 instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance. -class btAxisSweep3 : public btAxisSweep3Internal -{ -public: - - btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0); - -}; - -/// bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune. -/// This comes at the cost of more memory per handle, and a bit slower performance. -/// It uses arrays rather then lists for storage of the 3 axis. -class bt32BitAxisSweep3 : public btAxisSweep3Internal -{ -public: - - bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0); - -}; - -#endif - diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h deleted file mode 100644 index 97ba20743d2..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -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. -*/ - -#ifndef BROADPHASE_INTERFACE_H -#define BROADPHASE_INTERFACE_H - - - -struct btDispatcherInfo; -class btDispatcher; -#include "btBroadphaseProxy.h" -class btOverlappingPairCache; - -#include "LinearMath/btVector3.h" - -///BroadphaseInterface for aabb-overlapping object pairs -class btBroadphaseInterface -{ -public: - virtual ~btBroadphaseInterface() {} - - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher) =0; - virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0; - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0; - - ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb - virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0; - - virtual btOverlappingPairCache* getOverlappingPairCache()=0; - virtual const btOverlappingPairCache* getOverlappingPairCache() const =0; - -}; - -#endif //BROADPHASE_INTERFACE_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp deleted file mode 100644 index f4d7341f8dd..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* -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. -*/ - -#include "btBroadphaseProxy.h" - diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h deleted file mode 100644 index f0a462cce02..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h +++ /dev/null @@ -1,232 +0,0 @@ -/* -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. -*/ - -#ifndef BROADPHASE_PROXY_H -#define BROADPHASE_PROXY_H - -#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE -#include "LinearMath/btAlignedAllocator.h" - - -/// btDispatcher uses these types -/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave -/// to facilitate type checking -enum BroadphaseNativeTypes -{ -// polyhedral convex shapes - BOX_SHAPE_PROXYTYPE, - TRIANGLE_SHAPE_PROXYTYPE, - TETRAHEDRAL_SHAPE_PROXYTYPE, - CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE, - CONVEX_HULL_SHAPE_PROXYTYPE, -//implicit convex shapes -IMPLICIT_CONVEX_SHAPES_START_HERE, - SPHERE_SHAPE_PROXYTYPE, - MULTI_SPHERE_SHAPE_PROXYTYPE, - CAPSULE_SHAPE_PROXYTYPE, - CONE_SHAPE_PROXYTYPE, - CONVEX_SHAPE_PROXYTYPE, - CYLINDER_SHAPE_PROXYTYPE, - UNIFORM_SCALING_SHAPE_PROXYTYPE, - MINKOWSKI_SUM_SHAPE_PROXYTYPE, - MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, -//concave shapes -CONCAVE_SHAPES_START_HERE, - //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy! - TRIANGLE_MESH_SHAPE_PROXYTYPE, - ///used for demo integration FAST/Swift collision library and Bullet - FAST_CONCAVE_MESH_PROXYTYPE, - //terrain - TERRAIN_SHAPE_PROXYTYPE, -///Used for GIMPACT Trimesh integration - GIMPACT_SHAPE_PROXYTYPE, - - EMPTY_SHAPE_PROXYTYPE, - STATIC_PLANE_PROXYTYPE, -CONCAVE_SHAPES_END_HERE, - - COMPOUND_SHAPE_PROXYTYPE, - - MAX_BROADPHASE_COLLISION_TYPES -}; - - -///btBroadphaseProxy -ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy -{ - -BT_DECLARE_ALIGNED_ALLOCATOR(); - - ///optional filtering to cull potential collisions - enum CollisionFilterGroups - { - DefaultFilter = 1, - StaticFilter = 2, - KinematicFilter = 4, - DebrisFilter = 8, - SensorTrigger = 16, - AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger - }; - - //Usually the client btCollisionObject or Rigidbody class - void* m_clientObject; - - ///in the case of btMultiSapBroadphase, we store the collifionFilterGroup/Mask in the m_multiSapParentProxy - union - { - struct - { - short int m_collisionFilterGroup; - short int m_collisionFilterMask; - }; - - void* m_multiSapParentProxy; - - }; - - int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc. - int m_unusedPadding; //making the structure 16 bytes, better for alignment etc. - - SIMD_FORCE_INLINE int getUid() - { - return m_uniqueId;//(int)this; - } - - //used for memory pools - btBroadphaseProxy() :m_clientObject(0){} - - btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) - :m_clientObject(userPtr), - m_collisionFilterGroup(collisionFilterGroup), - m_collisionFilterMask(collisionFilterMask) - { - } - - - - static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType) - { - return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE); - } - - static SIMD_FORCE_INLINE bool isConvex(int proxyType) - { - return (proxyType < CONCAVE_SHAPES_START_HERE); - } - - static SIMD_FORCE_INLINE bool isConcave(int proxyType) - { - return ((proxyType > CONCAVE_SHAPES_START_HERE) && - (proxyType < CONCAVE_SHAPES_END_HERE)); - } - static SIMD_FORCE_INLINE bool isCompound(int proxyType) - { - return (proxyType == COMPOUND_SHAPE_PROXYTYPE); - } - static SIMD_FORCE_INLINE bool isInfinite(int proxyType) - { - return (proxyType == STATIC_PLANE_PROXYTYPE); - } - -} -; - -class btCollisionAlgorithm; - -struct btBroadphaseProxy; - - - -/// contains a pair of aabb-overlapping objects -ATTRIBUTE_ALIGNED16(struct) btBroadphasePair -{ - btBroadphasePair () - : - m_pProxy0(0), - m_pProxy1(0), - m_algorithm(0), - m_userInfo(0) - { - } - -BT_DECLARE_ALIGNED_ALLOCATOR(); - - btBroadphasePair(const btBroadphasePair& other) - : m_pProxy0(other.m_pProxy0), - m_pProxy1(other.m_pProxy1), - m_algorithm(other.m_algorithm), - m_userInfo(other.m_userInfo) - { - } - btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1) - { - - //keep them sorted, so the std::set operations work - if (&proxy0 < &proxy1) - { - m_pProxy0 = &proxy0; - m_pProxy1 = &proxy1; - } - else - { - m_pProxy0 = &proxy1; - m_pProxy1 = &proxy0; - } - - m_algorithm = 0; - m_userInfo = 0; - - } - - btBroadphaseProxy* m_pProxy0; - btBroadphaseProxy* m_pProxy1; - - mutable btCollisionAlgorithm* m_algorithm; - mutable void* m_userInfo; - -}; - -/* -//comparison for set operation, see Solid DT_Encounter -SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b) -{ - return a.m_pProxy0 < b.m_pProxy0 || - (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1); -} -*/ - - - -class btBroadphasePairSortPredicate -{ - public: - - bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) - { - return a.m_pProxy0 > b.m_pProxy0 || - (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 > b.m_pProxy1) || - (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm); - } -}; - - -SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b) -{ - return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1); -} - - -#endif //BROADPHASE_PROXY_H - diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp deleted file mode 100644 index c95d1be0f2c..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp +++ /dev/null @@ -1,23 +0,0 @@ -/* -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. -*/ - -#include "btCollisionAlgorithm.h" -#include "btDispatcher.h" - -btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) -{ - m_dispatcher = ci.m_dispatcher1; -} - diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h deleted file mode 100644 index 610eab4ce5e..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -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. -*/ - -#ifndef COLLISION_ALGORITHM_H -#define COLLISION_ALGORITHM_H - -#include "LinearMath/btScalar.h" - -struct btBroadphaseProxy; -class btDispatcher; -class btManifoldResult; -class btCollisionObject; -struct btDispatcherInfo; -class btPersistentManifold; - - -struct btCollisionAlgorithmConstructionInfo -{ - btCollisionAlgorithmConstructionInfo() - :m_dispatcher1(0), - m_manifold(0) - { - } - btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp) - :m_dispatcher1(dispatcher) - { - (void)temp; - } - - btDispatcher* m_dispatcher1; - btPersistentManifold* m_manifold; - - int getDispatcherId(); - -}; - - -///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher. -///It is persistent over frames -class btCollisionAlgorithm -{ - -protected: - - btDispatcher* m_dispatcher; - -protected: - int getDispatcherId(); - -public: - - btCollisionAlgorithm() {}; - - btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci); - - virtual ~btCollisionAlgorithm() {}; - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; - -}; - - -#endif //COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp deleted file mode 100644 index 20768225b3a..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* -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. -*/ - -#include "btDispatcher.h" - -btDispatcher::~btDispatcher() -{ - -} - diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h deleted file mode 100644 index daea11f7788..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -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. -*/ - -#ifndef _DISPATCHER_H -#define _DISPATCHER_H - -#include "LinearMath/btScalar.h" - -class btCollisionAlgorithm; -struct btBroadphaseProxy; -class btRigidBody; -class btCollisionObject; -class btOverlappingPairCache; - - -class btPersistentManifold; -class btStackAlloc; - -struct btDispatcherInfo -{ - enum DispatchFunc - { - DISPATCH_DISCRETE = 1, - DISPATCH_CONTINUOUS - }; - btDispatcherInfo() - :m_timeStep(btScalar(0.)), - m_stepCount(0), - m_dispatchFunc(DISPATCH_DISCRETE), - m_timeOfImpact(btScalar(1.)), - m_useContinuous(false), - m_debugDraw(0), - m_enableSatConvex(false), - m_enableSPU(false), - m_stackAllocator(0) - { - - } - btScalar m_timeStep; - int m_stepCount; - int m_dispatchFunc; - btScalar m_timeOfImpact; - bool m_useContinuous; - class btIDebugDraw* m_debugDraw; - bool m_enableSatConvex; - bool m_enableSPU; - btStackAlloc* m_stackAllocator; - -}; - -/// btDispatcher can be used in combination with broadphase to dispatch overlapping pairs. -/// For example for pairwise collision detection or user callbacks (game logic). -class btDispatcher -{ - - -public: - virtual ~btDispatcher() ; - - virtual btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold=0) = 0; - - virtual btPersistentManifold* getNewManifold(void* body0,void* body1)=0; - - virtual void releaseManifold(btPersistentManifold* manifold)=0; - - virtual void clearManifold(btPersistentManifold* manifold)=0; - - virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1) = 0; - - virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0; - - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)=0; - - virtual int getNumManifolds() const = 0; - - virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0; - - virtual btPersistentManifold** getInternalManifoldPointer() = 0; - - virtual void* allocateCollisionAlgorithm(int size) = 0; - - virtual void freeCollisionAlgorithm(void* ptr) = 0; - -}; - - -#endif //_DISPATCHER_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp deleted file mode 100644 index 41406ff49f9..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* -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. -*/ - -#include "btMultiSapBroadphase.h" - -#include "btSimpleBroadphase.h" -#include "LinearMath/btAabbUtil2.h" - -/// btSapBroadphaseArray m_sapBroadphases; - -/// btOverlappingPairCache* m_overlappingPairs; -extern int gOverlappingPairs; - -btMultiSapBroadphase::btMultiSapBroadphase(int maxProxies,btOverlappingPairCache* pairCache) -:m_overlappingPairs(pairCache), -m_ownsPairCache(false), -m_invalidPair(0) -{ - if (!m_overlappingPairs) - { - m_ownsPairCache = true; - void* mem = btAlignedAlloc(sizeof(btOverlappingPairCache),16); - m_overlappingPairs = new (mem)btOverlappingPairCache(); - } - - struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback - { - virtual ~btMultiSapOverlapFilterCallback() - {} - // return true when pairs need collision - virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const - { - btMultiSapBroadphase::btMultiSapProxy* multiSapProxy0 = (btMultiSapBroadphase::btMultiSapProxy*)childProxy0->m_multiSapParentProxy; - btMultiSapBroadphase::btMultiSapProxy* multiSapProxy1 = (btMultiSapBroadphase::btMultiSapProxy*)childProxy1->m_multiSapParentProxy; - - bool collides = (multiSapProxy0->m_collisionFilterGroup & multiSapProxy1->m_collisionFilterMask) != 0; - collides = collides && (multiSapProxy1->m_collisionFilterGroup & multiSapProxy0->m_collisionFilterMask); - - return collides; - } - }; - - void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16); - m_filterCallback = new (mem)btMultiSapOverlapFilterCallback(); - - m_overlappingPairs->setOverlapFilterCallback(m_filterCallback); - mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16); - m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs); -} - -btMultiSapBroadphase::~btMultiSapBroadphase() -{ - if (m_ownsPairCache) - { - btAlignedFree(m_overlappingPairs); - } -} - -btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher) -{ - void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16); - btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask); - m_multiSapProxies.push_back(proxy); - - ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision - ///this is needed to be able to calculate the aabb overlap - btBroadphaseProxy* simpleProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask, dispatcher); - simpleProxy->m_multiSapParentProxy = proxy; - - mem = btAlignedAlloc(sizeof(btChildProxy),16); - btChildProxy* childProxyRef = new btChildProxy(); - childProxyRef->m_proxy = simpleProxy; - childProxyRef->m_childBroadphase = m_simpleBroadphase; - proxy->m_childProxies.push_back(childProxyRef); - - ///this should deal with inserting/removal into child broadphases - setAabb(proxy,aabbMin,aabbMax,dispatcher); - return proxy; -} - -void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) -{ - ///not yet - btAssert(0); - -} -void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) -{ - btMultiSapProxy* multiProxy = static_cast(proxy); - multiProxy->m_aabbMin = aabbMin; - multiProxy->m_aabbMax = aabbMax; - - for (int i=0;im_childProxies.size();i++) - { - btChildProxy* childProxyRef = multiProxy->m_childProxies[i]; - childProxyRef->m_childBroadphase->setAabb(childProxyRef->m_proxy,aabbMin,aabbMax,dispatcher); - } - -} - - ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb -void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) -{ - m_simpleBroadphase->calculateOverlappingPairs(dispatcher); - -#ifndef USE_HASH_PAIRCACHE - - btBroadphasePairArray& overlappingPairArray = m_overlappingPairs->getOverlappingPairArray(); - - //perform a sort, to find duplicates and to sort 'invalid' pairs to the end - overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - - - btBroadphasePair previousPair; - previousPair.m_pProxy0 = 0; - previousPair.m_pProxy1 = 0; - previousPair.m_algorithm = 0; - - int i; - - for (i=0;iprocessOverlap(pair); - } else - { - needsRemoval = true; - } - } else - { - //remove duplicate - needsRemoval = true; - //should have no algorithm - btAssert(!pair.m_algorithm); - } - - if (needsRemoval) - { - m_overlappingPairs->cleanOverlappingPair(pair,dispatcher); - - // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); - // m_overlappingPairArray.pop_back(); - pair.m_pProxy0 = 0; - pair.m_pProxy1 = 0; - m_invalidPair++; - gOverlappingPairs--; - } - - } - -///if you don't like to skip the invalid pairs in the array, execute following code: -#define CLEAN_INVALID_PAIRS 1 -#ifdef CLEAN_INVALID_PAIRS - - //perform a sort, to sort 'invalid' pairs to the end - overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; -#endif//CLEAN_INVALID_PAIRS - -#endif //USE_HASH_PAIRCACHE - -} - - -bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) -{ - btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy; - btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy; - - return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax, - multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax); - -} diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h deleted file mode 100644 index 1ee609b8d1f..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -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. -*/ -#ifndef BT_MULTI_SAP_BROADPHASE -#define BT_MULTI_SAP_BROADPHASE - -#include "btBroadphaseInterface.h" -#include "LinearMath/btAlignedObjectArray.h" -#include "btOverlappingPairCache.h" - -class btAxisSweep3; -class btSimpleBroadphase; - - -typedef btAlignedObjectArray btSapBroadphaseArray; - -///multi SAP broadphase -///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328 -///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 -class btMultiSapBroadphase :public btBroadphaseInterface -{ - btSapBroadphaseArray m_sapBroadphases; - - btSimpleBroadphase* m_simpleBroadphase; - - btOverlappingPairCache* m_overlappingPairs; - - bool m_ownsPairCache; - - btOverlapFilterCallback* m_filterCallback; - - int m_invalidPair; - - struct btChildProxy - { - btBroadphaseProxy* m_proxy; - btBroadphaseInterface* m_childBroadphase; - }; - -public: - - struct btMultiSapProxy : public btBroadphaseProxy - { - - ///array with all the entries that this proxy belongs to - btAlignedObjectArray m_childProxies; - btVector3 m_aabbMin; - btVector3 m_aabbMax; - - int m_shapeType; - void* m_userPtr; - short int m_collisionFilterGroup; - short int m_collisionFilterMask; - - btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) - :m_aabbMin(aabbMin), - m_aabbMax(aabbMax), - m_shapeType(shapeType), - m_userPtr(userPtr), - m_collisionFilterGroup(collisionFilterGroup), - m_collisionFilterMask(collisionFilterMask) - { - - } - - - }; - -protected: - - btAlignedObjectArray m_multiSapProxies; - -public: - - btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0); - - btSapBroadphaseArray getBroadphaseArray() - { - return m_sapBroadphases; - } - - const btSapBroadphaseArray getBroadphaseArray() const - { - return m_sapBroadphases; - } - - virtual ~btMultiSapBroadphase(); - - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher); - virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); - - ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb - virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - - bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - - virtual btOverlappingPairCache* getOverlappingPairCache() - { - return m_overlappingPairs; - } - virtual const btOverlappingPairCache* getOverlappingPairCache() const - { - return m_overlappingPairs; - } -}; - -#endif //BT_MULTI_SAP_BROADPHASE diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp deleted file mode 100644 index e4ef043f064..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp +++ /dev/null @@ -1,474 +0,0 @@ - -/* -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. -*/ - - - -#include "btOverlappingPairCache.h" - -#include "btDispatcher.h" -#include "btCollisionAlgorithm.h" - -int gOverlappingPairs = 0; - -int gRemovePairs =0; -int gAddedPairs =0; -int gFindPairs =0; - -btOverlappingPairCache::btOverlappingPairCache(): - m_overlapFilterCallback(0), - m_blockedForChanges(false) -{ - int initialAllocatedSize= 2; - m_overlappingPairArray.reserve(initialAllocatedSize); -#ifdef USE_HASH_PAIRCACHE - growTables(); -#endif //USE_HASH_PAIRCACHE -} - - -btOverlappingPairCache::~btOverlappingPairCache() -{ - //todo/test: show we erase/delete data, or is it automatic -} - -void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) -{ - if (pair.m_algorithm) - { - { - pair.m_algorithm->~btCollisionAlgorithm(); - dispatcher->freeCollisionAlgorithm(pair.m_algorithm); - pair.m_algorithm=0; - } - } -} - - -void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) -{ - - class CleanPairCallback : public btOverlapCallback - { - btBroadphaseProxy* m_cleanProxy; - btOverlappingPairCache* m_pairCache; - btDispatcher* m_dispatcher; - - public: - CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) - :m_cleanProxy(cleanProxy), - m_pairCache(pairCache), - m_dispatcher(dispatcher) - { - } - virtual bool processOverlap(btBroadphasePair& pair) - { - if ((pair.m_pProxy0 == m_cleanProxy) || - (pair.m_pProxy1 == m_cleanProxy)) - { - m_pairCache->cleanOverlappingPair(pair,m_dispatcher); - } - return false; - } - - }; - - CleanPairCallback cleanPairs(proxy,this,dispatcher); - - processAllOverlappingPairs(&cleanPairs,dispatcher); - -} - -void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) -{ - - class RemovePairCallback : public btOverlapCallback - { - btBroadphaseProxy* m_obsoleteProxy; - - public: - RemovePairCallback(btBroadphaseProxy* obsoleteProxy) - :m_obsoleteProxy(obsoleteProxy) - { - } - virtual bool processOverlap(btBroadphasePair& pair) - { - return ((pair.m_pProxy0 == m_obsoleteProxy) || - (pair.m_pProxy1 == m_obsoleteProxy)); - } - - }; - - - RemovePairCallback removeCallback(proxy); - - processAllOverlappingPairs(&removeCallback,dispatcher); -} - - -#ifdef USE_HASH_PAIRCACHE - - - - - - - -btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) -{ - gFindPairs++; - - int proxyId1 = proxy0->getUid(); - int proxyId2 = proxy1->getUid(); - - if (proxyId1 > proxyId2) - btSwap(proxyId1, proxyId2); - - int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1); - - int index = m_hashTable[hash]; - while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) - { - index = m_next[index]; - } - - if (index == BT_NULL_PAIR) - { - return NULL; - } - - btAssert(index < m_overlappingPairArray.size()); - - return &m_overlappingPairArray[index]; -} - -#include - -void btOverlappingPairCache::growTables() -{ - - int newCapacity = m_overlappingPairArray.capacity(); - - if (m_hashTable.size() < newCapacity) - { - //grow hashtable and next table - int curHashtableSize = m_hashTable.size(); - - m_hashTable.resize(newCapacity); - m_next.resize(newCapacity); - - - int i; - - for (i= 0; i < newCapacity; ++i) - { - m_hashTable[i] = BT_NULL_PAIR; - } - for (i = 0; i < newCapacity; ++i) - { - m_next[i] = BT_NULL_PAIR; - } - - for(i=0;igetUid(); - int proxyId2 = pair.m_pProxy1->getUid(); - if (proxyId1 > proxyId2) - btSwap(proxyId1, proxyId2); - int hashValue = getHash(proxyId1,proxyId2) & (m_overlappingPairArray.capacity()-1); // New hash value with new mask - m_next[i] = m_hashTable[hashValue]; - m_hashTable[hashValue] = i; - } - - - } -} - -btBroadphasePair* btOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) -{ - int proxyId1 = proxy0->getUid(); - int proxyId2 = proxy1->getUid(); - - if (proxyId1 > proxyId2) - btSwap(proxyId1, proxyId2); - - int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1); - - - - btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); - if (pair != NULL) - { - return pair; - } - - int count = m_overlappingPairArray.size(); - int oldCapacity = m_overlappingPairArray.capacity(); - void* mem = &m_overlappingPairArray.expand(); - int newCapacity = m_overlappingPairArray.capacity(); - - if (oldCapacity < newCapacity) - { - growTables(); - //hash with new capacity - hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1); - } - - pair = new (mem) btBroadphasePair(*proxy0,*proxy1); -// pair->m_pProxy0 = proxy0; -// pair->m_pProxy1 = proxy1; - pair->m_algorithm = 0; - pair->m_userInfo = 0; - - - m_next[count] = m_hashTable[hash]; - m_hashTable[hash] = count; - - return pair; -} - - - -void* btOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher) -{ - gRemovePairs++; - - int proxyId1 = proxy0->getUid(); - int proxyId2 = proxy1->getUid(); - - if (proxyId1 > proxyId2) - btSwap(proxyId1, proxyId2); - - int hash = getHash(proxyId1, proxyId2) & (m_overlappingPairArray.capacity()-1); - - btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); - if (pair == NULL) - { - return 0; - } - - cleanOverlappingPair(*pair,dispatcher); - - void* userData = pair->m_userInfo; - - btAssert(pair->m_pProxy0->getUid() == proxyId1); - btAssert(pair->m_pProxy1->getUid() == proxyId2); - - int pairIndex = int(pair - &m_overlappingPairArray[0]); - btAssert(pairIndex < m_overlappingPairArray.size()); - - // Remove the pair from the hash table. - int index = m_hashTable[hash]; - btAssert(index != BT_NULL_PAIR); - - int previous = BT_NULL_PAIR; - while (index != pairIndex) - { - previous = index; - index = m_next[index]; - } - - if (previous != BT_NULL_PAIR) - { - btAssert(m_next[previous] == pairIndex); - m_next[previous] = m_next[pairIndex]; - } - else - { - m_hashTable[hash] = m_next[pairIndex]; - } - - // We now move the last pair into spot of the - // pair being removed. We need to fix the hash - // table indices to support the move. - - int lastPairIndex = m_overlappingPairArray.size() - 1; - - // If the removed pair is the last pair, we are done. - if (lastPairIndex == pairIndex) - { - m_overlappingPairArray.pop_back(); - return userData; - } - - // Remove the last pair from the hash table. - const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex]; - int lastHash = getHash(last->m_pProxy0->getUid(), last->m_pProxy1->getUid()) & (m_overlappingPairArray.capacity()-1); - - index = m_hashTable[lastHash]; - btAssert(index != BT_NULL_PAIR); - - previous = BT_NULL_PAIR; - while (index != lastPairIndex) - { - previous = index; - index = m_next[index]; - } - - if (previous != BT_NULL_PAIR) - { - btAssert(m_next[previous] == lastPairIndex); - m_next[previous] = m_next[lastPairIndex]; - } - else - { - m_hashTable[lastHash] = m_next[lastPairIndex]; - } - - // Copy the last pair into the remove pair's spot. - m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex]; - - // Insert the last pair into the hash table - m_next[pairIndex] = m_hashTable[lastHash]; - m_hashTable[lastHash] = pairIndex; - - m_overlappingPairArray.pop_back(); - - return userData; -} -#include - -void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) -{ - - int i; - -// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size()); - for (i=0;iprocessOverlap(*pair)) - { - removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher); - - gOverlappingPairs--; - } else - { - i++; - } - } -} - -#else - - - - -void* btOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher ) -{ -#ifndef USE_LAZY_REMOVAL - - btBroadphasePair findPair(*proxy0,*proxy1); - - int findIndex = m_overlappingPairArray.findLinearSearch(findPair); - if (findIndex < m_overlappingPairArray.size()) - { - gOverlappingPairs--; - btBroadphasePair& pair = m_overlappingPairArray[findIndex]; - void* userData = pair.m_userInfo; - cleanOverlappingPair(pair,dispatcher); - - m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1); - m_overlappingPairArray.pop_back(); - return userData; - } -#endif //USE_LAZY_REMOVAL - - return 0; -} - - - - - - - - -btBroadphasePair* btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - //don't add overlap with own - assert(proxy0 != proxy1); - - if (!needsBroadphaseCollision(proxy0,proxy1)) - return 0; - - void* mem = &m_overlappingPairArray.expand(); - btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1); - gOverlappingPairs++; - return pair; - -} - -///this findPair becomes really slow. Either sort the list to speedup the query, or -///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed. -///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address) -///Also we can use a 2D bitmap, which can be useful for a future GPU implementation - btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - if (!needsBroadphaseCollision(proxy0,proxy1)) - return 0; - - btBroadphasePair tmpPair(*proxy0,*proxy1); - int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair); - - if (findIndex < m_overlappingPairArray.size()) - { - //assert(it != m_overlappingPairSet.end()); - btBroadphasePair* pair = &m_overlappingPairArray[findIndex]; - return pair; - } - return 0; -} - - - - - - - - - - -#include - -void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) -{ - - int i; - - for (i=0;iprocessOverlap(*pair)) - { - cleanOverlappingPair(*pair,dispatcher); - - m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1); - m_overlappingPairArray.pop_back(); - gOverlappingPairs--; - } else - { - i++; - } - } -} - - - -#endif //USE_HASH_PAIRCACHE diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h deleted file mode 100644 index a387505d1be..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h +++ /dev/null @@ -1,323 +0,0 @@ - -/* -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. -*/ - -#ifndef OVERLAPPING_PAIR_CACHE_H -#define OVERLAPPING_PAIR_CACHE_H - - -#include "btBroadphaseInterface.h" -#include "btBroadphaseProxy.h" -#include "LinearMath/btPoint3.h" -#include "LinearMath/btAlignedObjectArray.h" -class btDispatcher; - -///disable the USE_HASH_PAIRCACHE define to use a pair manager that sorts the pairs to find duplicates/non-overlap -#define USE_HASH_PAIRCACHE 1 - - -struct btOverlapCallback -{ - virtual ~btOverlapCallback() - {} - //return true for deletion of the pair - virtual bool processOverlap(btBroadphasePair& pair) = 0; -}; - -struct btOverlapFilterCallback -{ - virtual ~btOverlapFilterCallback() - {} - // return true when pairs need collision - virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; -}; - -typedef btAlignedObjectArray btBroadphasePairArray; - -#ifdef USE_HASH_PAIRCACHE - - -/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com - -extern int gRemovePairs; -extern int gAddedPairs; -extern int gFindPairs; - -const int BT_NULL_PAIR=0xffffffff; - -class btOverlappingPairCache -{ - btBroadphasePairArray m_overlappingPairArray; - btOverlapFilterCallback* m_overlapFilterCallback; - bool m_blockedForChanges; - - -public: - btOverlappingPairCache(); - virtual ~btOverlappingPairCache(); - - - void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - - void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); - - SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const - { - if (m_overlapFilterCallback) - return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); - - bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; - collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); - - return collides; - } - - // Add a pair and return the new pair. If the pair already exists, - // no new pair is created and the old one is returned. - SIMD_FORCE_INLINE btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) - { - gAddedPairs++; - - if (!needsBroadphaseCollision(proxy0,proxy1)) - return 0; - - return internalAddPair(proxy0,proxy1); - } - - - - void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - - - virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); - - btBroadphasePair* getOverlappingPairArrayPtr() - { - return &m_overlappingPairArray[0]; - } - - const btBroadphasePair* getOverlappingPairArrayPtr() const - { - return &m_overlappingPairArray[0]; - } - - btBroadphasePairArray& getOverlappingPairArray() - { - return m_overlappingPairArray; - } - - const btBroadphasePairArray& getOverlappingPairArray() const - { - return m_overlappingPairArray; - } - - void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); - - - - btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1); - - int GetCount() const { return m_overlappingPairArray.size(); } -// btBroadphasePair* GetPairs() { return m_pairs; } - - btOverlapFilterCallback* getOverlapFilterCallback() - { - return m_overlapFilterCallback; - } - - void setOverlapFilterCallback(btOverlapFilterCallback* callback) - { - m_overlapFilterCallback = callback; - } - - int getNumOverlappingPairs() const - { - return m_overlappingPairArray.size(); - } -private: - - btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - - void growTables(); - - SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2) - { - return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2; - } - - /* - // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm - // This assumes proxyId1 and proxyId2 are 16-bit. - SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2) - { - int key = (proxyId2 << 16) | proxyId1; - key = ~key + (key << 15); - key = key ^ (key >> 12); - key = key + (key << 2); - key = key ^ (key >> 4); - key = key * 2057; - key = key ^ (key >> 16); - return key; - } - */ - - - - SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2) - { - int key = ((unsigned int)proxyId1) | (((unsigned int)proxyId1) <<16); - // Thomas Wang's hash - - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return key; - } - - - - - - SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash) - { - int proxyId1 = proxy0->getUid(); - int proxyId2 = proxy1->getUid(); - if (proxyId1 > proxyId2) - btSwap(proxyId1, proxyId2); - - int index = m_hashTable[hash]; - - while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) - { - index = m_next[index]; - } - - if ( index == BT_NULL_PAIR ) - { - return NULL; - } - - btAssert(index < m_overlappingPairArray.size()); - - return &m_overlappingPairArray[index]; - } - - -public: - - btAlignedObjectArray m_hashTable; - btAlignedObjectArray m_next; - -}; - - - -#else//USE_HASH_PAIRCACHE - -#define USE_LAZY_REMOVAL 1 - -///btOverlappingPairCache maintains the objects with overlapping AABB -///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase -class btOverlappingPairCache -{ - protected: - //avoid brute-force finding all the time - btBroadphasePairArray m_overlappingPairArray; - - //during the dispatch, check that user doesn't destroy/create proxy - bool m_blockedForChanges; - - //if set, use the callback instead of the built in filter in needBroadphaseCollision - btOverlapFilterCallback* m_overlapFilterCallback; - - public: - - btOverlappingPairCache(); - virtual ~btOverlappingPairCache(); - - virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); - - void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); - - void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); - - btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - - btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - - - void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - - void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - - - inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const - { - if (m_overlapFilterCallback) - return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); - - bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; - collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); - - return collides; - } - - btBroadphasePairArray& getOverlappingPairArray() - { - return m_overlappingPairArray; - } - - const btBroadphasePairArray& getOverlappingPairArray() const - { - return m_overlappingPairArray; - } - - - - - btBroadphasePair* getOverlappingPairArrayPtr() - { - return &m_overlappingPairArray[0]; - } - - const btBroadphasePair* getOverlappingPairArrayPtr() const - { - return &m_overlappingPairArray[0]; - } - - int getNumOverlappingPairs() const - { - return m_overlappingPairArray.size(); - } - - btOverlapFilterCallback* getOverlapFilterCallback() - { - return m_overlapFilterCallback; - } - - void setOverlapFilterCallback(btOverlapFilterCallback* callback) - { - m_overlapFilterCallback = callback; - } - -}; -#endif //USE_HASH_PAIRCACHE - -#endif //OVERLAPPING_PAIR_CACHE_H - - diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h deleted file mode 100644 index b8d967dc4b2..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h +++ /dev/null @@ -1,37 +0,0 @@ - -/* -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. -*/ - -#ifndef OVERLAPPING_PAIR_CALLBACK_H -#define OVERLAPPING_PAIR_CALLBACK_H - -///btOverlappingPairCallback provides user callback to keep track of overlap between objects, like a collision sensor -class btOverlappingPairCallback -{ -public: - virtual ~btOverlappingPairCallback() - { - - } - - virtual void addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0; - - virtual void removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0; - - virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0) = 0; - -}; - -#endif //OVERLAPPING_PAIR_CALLBACK_H \ No newline at end of file diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp deleted file mode 100644 index e0bb0992933..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* -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. -*/ - -#include "btSimpleBroadphase.h" -#include -#include - -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransform.h" -#include "LinearMath/btMatrix3x3.h" -#include - -extern int gOverlappingPairs; - -void btSimpleBroadphase::validate() -{ - for (int i=0;i~btOverlappingPairCache(); - btAlignedFree(m_pairCache); - } -} - - -btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher) -{ - if (m_numHandles >= m_maxHandles) - { - btAssert(0); - return 0; //should never happen, but don't let the game crash ;-) - } - assert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]); - - int newHandleIndex = allocHandle(); - btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask); - - return proxy; -} - -class RemovingOverlapCallback : public btOverlapCallback -{ -protected: - virtual bool processOverlap(btBroadphasePair& pair) - { - (void)pair; - btAssert(0); - return false; - } -}; - -class RemovePairContainingProxy -{ - - btBroadphaseProxy* m_targetProxy; - public: - virtual ~RemovePairContainingProxy() - { - } -protected: - virtual bool processOverlap(btBroadphasePair& pair) - { - btSimpleBroadphaseProxy* proxy0 = static_cast(pair.m_pProxy0); - btSimpleBroadphaseProxy* proxy1 = static_cast(pair.m_pProxy1); - - return ((m_targetProxy == proxy0 || m_targetProxy == proxy1)); - }; -}; - -void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher) -{ - - btSimpleBroadphaseProxy* proxy0 = static_cast(proxyOrg); - freeHandle(proxy0); - - m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher); - - //validate(); - -} - -void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) -{ - btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy); - sbp->m_min = aabbMin; - sbp->m_max = aabbMax; -} - - - - - - - - - -bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1) -{ - return proxy0->m_min[0] <= proxy1->m_max[0] && proxy1->m_min[0] <= proxy0->m_max[0] && - proxy0->m_min[1] <= proxy1->m_max[1] && proxy1->m_min[1] <= proxy0->m_max[1] && - proxy0->m_min[2] <= proxy1->m_max[2] && proxy1->m_min[2] <= proxy0->m_max[2]; - -} - - - -//then remove non-overlapping ones -class CheckOverlapCallback : public btOverlapCallback -{ -public: - virtual bool processOverlap(btBroadphasePair& pair) - { - return (!btSimpleBroadphase::aabbOverlap(static_cast(pair.m_pProxy0),static_cast(pair.m_pProxy1))); - } -}; - -void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) -{ - //first check for new overlapping pairs - int i,j; - - if (m_firstAllocatedHandle >= 0) - { - - btSimpleBroadphaseProxy* proxy0 = &m_pHandles[m_firstAllocatedHandle]; - - for (i=0;ifindPair(proxy0,proxy1)) - { - m_pairCache->addOverlappingPair(proxy0,proxy1); - } - } else - { - #ifdef USE_HASH_PAIRCACHE - if ( m_pairCache->findPair(proxy0,proxy1)) - { - m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); - } - #endif //USE_HASH_PAIRCACHE - - } - } - proxy1 = &m_pHandles[proxy1->GetNextAllocated()]; - - } - proxy0 = &m_pHandles[proxy0->GetNextAllocated()]; - - } - - #ifndef USE_HASH_PAIRCACHE - - if (m_ownsPairCache) - { - - btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); - - //perform a sort, to find duplicates and to sort 'invalid' pairs to the end - overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - - - btBroadphasePair previousPair; - previousPair.m_pProxy0 = 0; - previousPair.m_pProxy1 = 0; - previousPair.m_algorithm = 0; - - - for (i=0;iprocessOverlap(pair); - } else - { - needsRemoval = true; - } - } else - { - //remove duplicate - needsRemoval = true; - //should have no algorithm - btAssert(!pair.m_algorithm); - } - - if (needsRemoval) - { - m_pairCache->cleanOverlappingPair(pair,dispatcher); - - // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); - // m_overlappingPairArray.pop_back(); - pair.m_pProxy0 = 0; - pair.m_pProxy1 = 0; - m_invalidPair++; - gOverlappingPairs--; - } - - } - - ///if you don't like to skip the invalid pairs in the array, execute following code: - #define CLEAN_INVALID_PAIRS 1 - #ifdef CLEAN_INVALID_PAIRS - - //perform a sort, to sort 'invalid' pairs to the end - overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - #endif//CLEAN_INVALID_PAIRS - - } - #endif //USE_HASH_PAIRCACHE - } -} - - -bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); - btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); - return aabbOverlap(p0,p1); -} - - - diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h deleted file mode 100644 index 09367a79d2b..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h +++ /dev/null @@ -1,147 +0,0 @@ -/* -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. -*/ - -#ifndef SIMPLE_BROADPHASE_H -#define SIMPLE_BROADPHASE_H - - -#include "btOverlappingPairCache.h" - - -struct btSimpleBroadphaseProxy : public btBroadphaseProxy -{ - btVector3 m_min; - btVector3 m_max; - int m_nextFree; - int m_nextAllocated; -// int m_handleId; - - - btSimpleBroadphaseProxy() {}; - - btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask) - :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask), - m_min(minpt),m_max(maxpt) - { - (void)shapeType; - } - - - SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;} - SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;} - - SIMD_FORCE_INLINE void SetNextAllocated(int next) {m_nextAllocated = next;} - SIMD_FORCE_INLINE int GetNextAllocated() const {return m_nextAllocated;} - - -}; - -///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks -///btSimpleBroadphase is just a unit-test implementation to verify and test other broadphases. -///So please don't use this class, but use bt32BitAxisSweep3 or btAxisSweep3 instead! -class btSimpleBroadphase : public btBroadphaseInterface -{ - -protected: - - int m_numHandles; // number of active handles - int m_maxHandles; // max number of handles - btSimpleBroadphaseProxy* m_pHandles; // handles pool - int m_firstFreeHandle; // free handles list - int m_firstAllocatedHandle; - - int allocHandle() - { - - int freeHandle = m_firstFreeHandle; - m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree(); - - m_pHandles[freeHandle].SetNextAllocated(m_firstAllocatedHandle); - m_firstAllocatedHandle = freeHandle; - - m_numHandles++; - - return freeHandle; - } - - void freeHandle(btSimpleBroadphaseProxy* proxy) - { - int handle = int(proxy-m_pHandles); - btAssert(handle >= 0 && handle < m_maxHandles); - - proxy->SetNextFree(m_firstFreeHandle); - m_firstFreeHandle = handle; - - m_firstAllocatedHandle = proxy->GetNextAllocated(); - proxy->SetNextAllocated(-1); - - m_numHandles--; - } - - - btOverlappingPairCache* m_pairCache; - bool m_ownsPairCache; - - int m_invalidPair; - - - - inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) - { - btSimpleBroadphaseProxy* proxy0 = static_cast(proxy); - return proxy0; - } - - - void validate(); - -protected: - - - - -public: - btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0); - virtual ~btSimpleBroadphase(); - - - static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1); - - - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher); - - virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - - virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); - - btOverlappingPairCache* getOverlappingPairCache() - { - return m_pairCache; - } - const btOverlappingPairCache* getOverlappingPairCache() const - { - return m_pairCache; - } - - bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - - -}; - - - -#endif //SIMPLE_BROADPHASE_H - diff --git a/extern/bullet2/src/BulletCollision/CMakeLists.txt b/extern/bullet2/src/BulletCollision/CMakeLists.txt deleted file mode 100644 index d2d3dc6fabf..00000000000 --- a/extern/bullet2/src/BulletCollision/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ - -INCLUDE_DIRECTORIES( -${BULLET_PHYSICS_SOURCE_DIR}/src } -) - -ADD_LIBRARY(LibBulletCollision - BroadphaseCollision/btAxisSweep3.cpp - BroadphaseCollision/btBroadphaseProxy.cpp - BroadphaseCollision/btCollisionAlgorithm.cpp - BroadphaseCollision/btDispatcher.cpp - BroadphaseCollision/btMultiSapBroadphase.cpp - BroadphaseCollision/btOverlappingPairCache.cpp - BroadphaseCollision/btSimpleBroadphase.cpp - CollisionDispatch/btCollisionDispatcher.cpp - CollisionDispatch/btCollisionObject.cpp - CollisionDispatch/btCollisionWorld.cpp - CollisionDispatch/btCompoundCollisionAlgorithm.cpp - CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp - CollisionDispatch/btDefaultCollisionConfiguration.cpp - CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp - CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp - CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp - CollisionDispatch/btConvexConvexAlgorithm.cpp - CollisionDispatch/btEmptyCollisionAlgorithm.cpp - CollisionDispatch/btManifoldResult.cpp - CollisionDispatch/btSimulationIslandManager.cpp - CollisionDispatch/btUnionFind.cpp - CollisionDispatch/SphereTriangleDetector.cpp - CollisionShapes/btBoxShape.cpp - CollisionShapes/btBvhTriangleMeshShape.cpp - CollisionShapes/btCapsuleShape.cpp - CollisionShapes/btCollisionShape.cpp - CollisionShapes/btCompoundShape.cpp - CollisionShapes/btConcaveShape.cpp - CollisionShapes/btConeShape.cpp - CollisionShapes/btConvexHullShape.cpp - CollisionShapes/btConvexShape.cpp - CollisionShapes/btConvexInternalShape.cpp - CollisionShapes/btConvexTriangleMeshShape.cpp - CollisionShapes/btCylinderShape.cpp - CollisionShapes/btEmptyShape.cpp - CollisionShapes/btHeightfieldTerrainShape.cpp - CollisionShapes/btMinkowskiSumShape.cpp - CollisionShapes/btMultiSphereShape.cpp - CollisionShapes/btOptimizedBvh.cpp - CollisionShapes/btPolyhedralConvexShape.cpp - CollisionShapes/btTetrahedronShape.cpp - CollisionShapes/btSphereShape.cpp - CollisionShapes/btStaticPlaneShape.cpp - CollisionShapes/btStridingMeshInterface.cpp - CollisionShapes/btTriangleCallback.cpp - CollisionShapes/btTriangleBuffer.cpp - CollisionShapes/btTriangleIndexVertexArray.cpp - CollisionShapes/btTriangleMesh.cpp - CollisionShapes/btTriangleMeshShape.cpp - CollisionShapes/btUniformScalingShape.cpp - NarrowPhaseCollision/btContinuousConvexCollision.cpp - NarrowPhaseCollision/btGjkEpa.cpp - NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp - NarrowPhaseCollision/btConvexCast.cpp - NarrowPhaseCollision/btGjkConvexCast.cpp - NarrowPhaseCollision/btGjkPairDetector.cpp - NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp - NarrowPhaseCollision/btPersistentManifold.cpp - NarrowPhaseCollision/btRaycastCallback.cpp - NarrowPhaseCollision/btSubSimplexConvexCast.cpp - NarrowPhaseCollision/btVoronoiSimplexSolver.cpp -) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp deleted file mode 100644 index 81133670f0c..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* -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. -*/ - -#include "LinearMath/btScalar.h" -#include "SphereTriangleDetector.h" -#include "BulletCollision/CollisionShapes/btTriangleShape.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" - - -SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle) -:m_sphere(sphere), -m_triangle(triangle) -{ - -} - -void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) -{ - - (void)debugDraw; - const btTransform& transformA = input.m_transformA; - const btTransform& transformB = input.m_transformB; - - btVector3 point,normal; - btScalar timeOfImpact = btScalar(1.); - btScalar depth = btScalar(0.); -// output.m_distance = btScalar(1e30); - //move sphere into triangle space - btTransform sphereInTr = transformB.inverseTimes(transformA); - - if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact)) - { - output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth); - } - -} - -#define MAX_OVERLAP btScalar(0.) - - - -// See also geometrictools.com -// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv -btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) { - btVector3 diff = p - from; - btVector3 v = to - from; - btScalar t = v.dot(diff); - - if (t > 0) { - btScalar dotVV = v.dot(v); - if (t < dotVV) { - t /= dotVV; - diff -= t*v; - } else { - t = 1; - diff -= v; - } - } else - t = 0; - - nearest = from + t*v; - return diff.dot(diff); -} - -bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal) { - btVector3 lp(p); - btVector3 lnormal(normal); - - return pointInTriangle(vertices, lnormal, &lp); -} - -///combined discrete/continuous sphere-triangle -bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact) -{ - - const btVector3* vertices = &m_triangle->getVertexPtr(0); - const btVector3& c = sphereCenter; - btScalar r = m_sphere->getRadius(); - - btVector3 delta (0,0,0); - - btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]); - normal.normalize(); - btVector3 p1ToCentre = c - vertices[0]; - btScalar distanceFromPlane = p1ToCentre.dot(normal); - - if (distanceFromPlane < btScalar(0.)) - { - //triangle facing the other way - - distanceFromPlane *= btScalar(-1.); - normal *= btScalar(-1.); - } - - ///todo: move this gContactBreakingThreshold into a proper structure - extern btScalar gContactBreakingThreshold; - - btScalar contactMargin = gContactBreakingThreshold; - bool isInsideContactPlane = distanceFromPlane < r + contactMargin; - bool isInsideShellPlane = distanceFromPlane < r; - - btScalar deltaDotNormal = delta.dot(normal); - if (!isInsideShellPlane && deltaDotNormal >= btScalar(0.0)) - return false; - - // Check for contact / intersection - bool hasContact = false; - btVector3 contactPoint; - if (isInsideContactPlane) { - if (facecontains(c,vertices,normal)) { - // Inside the contact wedge - touches a point on the shell plane - hasContact = true; - contactPoint = c - normal*distanceFromPlane; - } else { - // Could be inside one of the contact capsules - btScalar contactCapsuleRadiusSqr = (r + contactMargin) * (r + contactMargin); - btVector3 nearestOnEdge; - for (int i = 0; i < m_triangle->getNumEdges(); i++) { - - btPoint3 pa; - btPoint3 pb; - - m_triangle->getEdge(i,pa,pb); - - btScalar distanceSqr = SegmentSqrDistance(pa,pb,c, nearestOnEdge); - if (distanceSqr < contactCapsuleRadiusSqr) { - // Yep, we're inside a capsule - hasContact = true; - contactPoint = nearestOnEdge; - } - - } - } - } - - if (hasContact) { - btVector3 contactToCentre = c - contactPoint; - btScalar distanceSqr = contactToCentre.length2(); - if (distanceSqr < (r - MAX_OVERLAP)*(r - MAX_OVERLAP)) { - btScalar distance = btSqrt(distanceSqr); - resultNormal = contactToCentre; - resultNormal.normalize(); - point = contactPoint; - depth = -(r-distance); - return true; - } - - if (delta.dot(contactToCentre) >= btScalar(0.0)) - return false; - - // Moving towards the contact point -> collision - point = contactPoint; - timeOfImpact = btScalar(0.0); - return true; - } - - return false; -} - - -bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ) -{ - const btVector3* p1 = &vertices[0]; - const btVector3* p2 = &vertices[1]; - const btVector3* p3 = &vertices[2]; - - btVector3 edge1( *p2 - *p1 ); - btVector3 edge2( *p3 - *p2 ); - btVector3 edge3( *p1 - *p3 ); - - btVector3 p1_to_p( *p - *p1 ); - btVector3 p2_to_p( *p - *p2 ); - btVector3 p3_to_p( *p - *p3 ); - - btVector3 edge1_normal( edge1.cross(normal)); - btVector3 edge2_normal( edge2.cross(normal)); - btVector3 edge3_normal( edge3.cross(normal)); - - btScalar r1, r2, r3; - r1 = edge1_normal.dot( p1_to_p ); - r2 = edge2_normal.dot( p2_to_p ); - r3 = edge3_normal.dot( p3_to_p ); - if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) || - ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) ) - return true; - return false; - -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h deleted file mode 100644 index 0c817b221c8..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -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. -*/ - -#ifndef SPHERE_TRIANGLE_DETECTOR_H -#define SPHERE_TRIANGLE_DETECTOR_H - -#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" -#include "LinearMath/btPoint3.h" - - -class btSphereShape; -class btTriangleShape; - - - -/// sphere-triangle to match the btDiscreteCollisionDetectorInterface -struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface -{ - virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw); - - SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle); - - virtual ~SphereTriangleDetector() {}; - -private: - - bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact); - bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ); - bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal); - - btSphereShape* m_sphere; - btTriangleShape* m_triangle; - - -}; -#endif //SPHERE_TRIANGLE_DETECTOR_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h deleted file mode 100644 index fad770ac26d..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -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. -*/ - -#ifndef BT_COLLISION_CONFIGURATION -#define BT_COLLISION_CONFIGURATION -struct btCollisionAlgorithmCreateFunc; - -class btStackAlloc; -class btPoolAllocator; - -///btCollisionConfiguration allows to configure Bullet collision detection -///stack allocator size, default collision algorithms and persistent manifold pool size -///todo: describe the meaning -class btCollisionConfiguration -{ - -public: - - virtual ~btCollisionConfiguration() - { - } - - ///memory pools - virtual btPoolAllocator* getPersistentManifoldPool() = 0; - - virtual btPoolAllocator* getCollisionAlgorithmPool() = 0; - - virtual btStackAlloc* getStackAllocator() = 0; - - virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0; - -}; - -#endif //BT_COLLISION_CONFIGURATION - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h deleted file mode 100644 index c6728918d16..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -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. -*/ - -#ifndef COLLISION_CREATE_FUNC -#define COLLISION_CREATE_FUNC - -#include "LinearMath/btAlignedObjectArray.h" -typedef btAlignedObjectArray btCollisionObjectArray; -class btCollisionAlgorithm; -class btCollisionObject; - -struct btCollisionAlgorithmConstructionInfo; - -///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm -struct btCollisionAlgorithmCreateFunc -{ - bool m_swapped; - - btCollisionAlgorithmCreateFunc() - :m_swapped(false) - { - } - virtual ~btCollisionAlgorithmCreateFunc(){}; - - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , btCollisionObject* body0,btCollisionObject* body1) - { - - (void)body0; - (void)body1; - return 0; - } -}; -#endif //COLLISION_CREATE_FUNC - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp deleted file mode 100644 index 644caf2677b..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* -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. -*/ - - - -#include "btCollisionDispatcher.h" - - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" - -#include "BulletCollision/CollisionShapes/btCollisionShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" -#include "LinearMath/btPoolAllocator.h" -#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" - -int gNumManifold = 0; - -#include - - - -btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration): - m_count(0), - m_useIslands(true), - m_collisionConfiguration(collisionConfiguration) -{ - int i; - - setNearCallback(defaultNearCallback); - - m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool(); - - m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool(); - - for (i=0;igetCollisionAlgorithmCreateFunc(i,j); - assert(m_doubleDispatch[i][j]); - } - } - - -}; - - -void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc) -{ - m_doubleDispatch[proxyType0][proxyType1] = createFunc; -} - -btCollisionDispatcher::~btCollisionDispatcher() -{ -} - -btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) -{ - gNumManifold++; - - //btAssert(gNumManifold < 65535); - - - btCollisionObject* body0 = (btCollisionObject*)b0; - btCollisionObject* body1 = (btCollisionObject*)b1; - - void* mem = 0; - - if (m_persistentManifoldPoolAllocator->getFreeCount()) - { - mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold)); - } else - { - mem = btAlignedAlloc(sizeof(btPersistentManifold),16); - - } - btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0); - manifold->m_index1a = m_manifoldsPtr.size(); - m_manifoldsPtr.push_back(manifold); - - return manifold; -} - -void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold) -{ - manifold->clearManifold(); -} - - -void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) -{ - - gNumManifold--; - - //printf("releaseManifold: gNumManifold %d\n",gNumManifold); - clearManifold(manifold); - - int findIndex = manifold->m_index1a; - btAssert(findIndex < m_manifoldsPtr.size()); - m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); - m_manifoldsPtr[findIndex]->m_index1a = findIndex; - m_manifoldsPtr.pop_back(); - - manifold->~btPersistentManifold(); - if (m_persistentManifoldPoolAllocator->validPtr(manifold)) - { - m_persistentManifoldPoolAllocator->free(manifold); - } else - { - btAlignedFree(manifold); - } - -} - - - -btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) -{ - - btCollisionAlgorithmConstructionInfo ci; - - ci.m_dispatcher1 = this; - ci.m_manifold = sharedManifold; - btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1); - - return algo; -} - - - - - -bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1) -{ - //here you can do filtering - bool hasResponse = - (body0->hasContactResponse() && body1->hasContactResponse()); - //no response between two static/kinematic bodies: - hasResponse = hasResponse && - ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject())); - return hasResponse; -} - -bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1) -{ - assert(body0); - assert(body1); - - bool needsCollision = true; - - //broadphase filtering already deals with this - if ((body0->isStaticObject() || body0->isKinematicObject()) && - (body1->isStaticObject() || body1->isKinematicObject())) - { - printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); - } - - if ((!body0->isActive()) && (!body1->isActive())) - needsCollision = false; - else if (!body0->checkCollideWith(body1)) - needsCollision = false; - - return needsCollision ; - -} - - - -///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc) -///this is useful for the collision dispatcher. -class btCollisionPairCallback : public btOverlapCallback -{ - btDispatcherInfo& m_dispatchInfo; - btCollisionDispatcher* m_dispatcher; - -public: - - btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) - :m_dispatchInfo(dispatchInfo), - m_dispatcher(dispatcher) - { - } - - btCollisionPairCallback& operator=(btCollisionPairCallback& other) - { - m_dispatchInfo = other.m_dispatchInfo; - m_dispatcher = other.m_dispatcher; - return *this; - } - - virtual ~btCollisionPairCallback() {} - - - virtual bool processOverlap(btBroadphasePair& pair) - { - (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo); - - return false; - } -}; - - -void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) -{ - //m_blockedForChanges = true; - - btCollisionPairCallback collisionCallback(dispatchInfo,this); - - pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); - - //m_blockedForChanges = false; - -} - - - - -//by default, Bullet will use this near callback -void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) -{ - btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; - btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; - - if (dispatcher.needsCollision(colObj0,colObj1)) - { - //dispatcher will keep algorithms persistent in the collision pair - if (!collisionPair.m_algorithm) - { - collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1); - } - - if (collisionPair.m_algorithm) - { - btManifoldResult contactPointResult(colObj0,colObj1); - - if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) - { - //discrete collision detection query - collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult); - } else - { - //continuous collision detection query, time of impact (toi) - btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); - if (dispatchInfo.m_timeOfImpact > toi) - dispatchInfo.m_timeOfImpact = toi; - - } - } - } - -} - - -void* btCollisionDispatcher::allocateCollisionAlgorithm(int size) -{ - if (m_collisionAlgorithmPoolAllocator->getFreeCount()) - { - return m_collisionAlgorithmPoolAllocator->allocate(size); - } - - //warn user for overflow? - return btAlignedAlloc(size,16); -} - -void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr) -{ - if (m_collisionAlgorithmPoolAllocator->validPtr(ptr)) - { - m_collisionAlgorithmPoolAllocator->free(ptr); - } else - { - btAlignedFree(ptr); - } -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h deleted file mode 100644 index 45aaa1bd90d..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h +++ /dev/null @@ -1,145 +0,0 @@ -/* -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. -*/ - -#ifndef COLLISION__DISPATCHER_H -#define COLLISION__DISPATCHER_H - -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" - -#include "BulletCollision/CollisionDispatch/btManifoldResult.h" - -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "LinearMath/btAlignedObjectArray.h" - -class btIDebugDraw; -class btOverlappingPairCache; -class btPoolAllocator; -class btCollisionConfiguration; - -#include "btCollisionCreateFunc.h" - -#define USE_DISPATCH_REGISTRY_ARRAY 1 - -class btCollisionDispatcher; -///user can override this nearcallback for collision filtering and more finegrained control over collision detection -typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); - - -///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. -///Time of Impact, Closest Points and Penetration Depth. -class btCollisionDispatcher : public btDispatcher -{ - int m_count; - - btAlignedObjectArray m_manifoldsPtr; - - bool m_useIslands; - - btManifoldResult m_defaultManifoldResult; - - btNearCallback m_nearCallback; - - btPoolAllocator* m_collisionAlgorithmPoolAllocator; - - btPoolAllocator* m_persistentManifoldPoolAllocator; - - btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; - - - btCollisionConfiguration* m_collisionConfiguration; - - -public: - - ///registerCollisionCreateFunc allows registration of custom/alternative collision create functions - void registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc); - - int getNumManifolds() const - { - return int( m_manifoldsPtr.size()); - } - - btPersistentManifold** getInternalManifoldPointer() - { - return &m_manifoldsPtr[0]; - } - - btPersistentManifold* getManifoldByIndexInternal(int index) - { - return m_manifoldsPtr[index]; - } - - const btPersistentManifold* getManifoldByIndexInternal(int index) const - { - return m_manifoldsPtr[index]; - } - - btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration); - - virtual ~btCollisionDispatcher(); - - virtual btPersistentManifold* getNewManifold(void* b0,void* b1); - - virtual void releaseManifold(btPersistentManifold* manifold); - - - virtual void clearManifold(btPersistentManifold* manifold); - - - btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0); - - virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1); - - virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1); - - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher); - - void setNearCallback(btNearCallback nearCallback) - { - m_nearCallback = nearCallback; - } - - btNearCallback getNearCallback() const - { - return m_nearCallback; - } - - //by default, Bullet will use this near callback - static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); - - virtual void* allocateCollisionAlgorithm(int size); - - virtual void freeCollisionAlgorithm(void* ptr); - - btCollisionConfiguration* getCollisionConfiguration() - { - return m_collisionConfiguration; - } - - const btCollisionConfiguration* getCollisionConfiguration() const - { - return m_collisionConfiguration; - } - - void setCollisionConfiguration(btCollisionConfiguration* config) - { - m_collisionConfiguration = config; - } - -}; - -#endif //COLLISION__DISPATCHER_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp deleted file mode 100644 index 6b72a131c4f..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* -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. -*/ - - -#include "btCollisionObject.h" - -btCollisionObject::btCollisionObject() - : m_broadphaseHandle(0), - m_collisionShape(0), - m_collisionFlags(0), - m_islandTag1(-1), - m_companionId(-1), - m_activationState1(1), - m_deactivationTime(btScalar(0.)), - m_userObjectPointer(0), - m_internalOwner(0), - m_hitFraction(btScalar(1.)), - m_ccdSweptSphereRadius(btScalar(0.)), - m_ccdSquareMotionThreshold(btScalar(0.)), - m_checkCollideWith(false) -{ - -} - -btCollisionObject::~btCollisionObject() -{ -} - -void btCollisionObject::setActivationState(int newState) -{ - if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION)) - m_activationState1 = newState; -} - -void btCollisionObject::forceActivationState(int newState) -{ - m_activationState1 = newState; -} - -void btCollisionObject::activate(bool forceActivation) -{ - if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT))) - { - setActivationState(ACTIVE_TAG); - m_deactivationTime = btScalar(0.); - } -} - - - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h deleted file mode 100644 index 7c1ddbf1e2d..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h +++ /dev/null @@ -1,349 +0,0 @@ -/* -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. -*/ - -#ifndef COLLISION_OBJECT_H -#define COLLISION_OBJECT_H - -#include "LinearMath/btTransform.h" - -//island management, m_activationState1 -#define ACTIVE_TAG 1 -#define ISLAND_SLEEPING 2 -#define WANTS_DEACTIVATION 3 -#define DISABLE_DEACTIVATION 4 -#define DISABLE_SIMULATION 5 - -struct btBroadphaseProxy; -class btCollisionShape; -#include "LinearMath/btMotionState.h" -#include "LinearMath/btAlignedAllocator.h" - - - -/// btCollisionObject can be used to manage collision detection objects. -/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy. -/// They can be added to the btCollisionWorld. -ATTRIBUTE_ALIGNED16(class) btCollisionObject -{ - -protected: - - btTransform m_worldTransform; - - ///m_interpolationWorldTransform is used for CCD and interpolation - ///it can be either previous or future (predicted) transform - btTransform m_interpolationWorldTransform; - //those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities) - //without destroying the continuous interpolated motion (which uses this interpolation velocities) - btVector3 m_interpolationLinearVelocity; - btVector3 m_interpolationAngularVelocity; - btBroadphaseProxy* m_broadphaseHandle; - btCollisionShape* m_collisionShape; - - int m_collisionFlags; - - int m_islandTag1; - int m_companionId; - - int m_activationState1; - btScalar m_deactivationTime; - - btScalar m_friction; - btScalar m_restitution; - - ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer - void* m_userObjectPointer; - - ///m_internalOwner is reserved to point to Bullet's btRigidBody. Don't use this, use m_userObjectPointer instead. - void* m_internalOwner; - - ///time of impact calculation - btScalar m_hitFraction; - - ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: - btScalar m_ccdSweptSphereRadius; - - /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold - btScalar m_ccdSquareMotionThreshold; - - /// If some object should have elaborate collision filtering by sub-classes - bool m_checkCollideWith; - - char m_pad[7]; - - virtual bool checkCollideWithOverride(btCollisionObject* co) - { - return true; - } - -public: - - BT_DECLARE_ALIGNED_ALLOCATOR(); - - enum CollisionFlags - { - CF_STATIC_OBJECT= 1, - CF_KINEMATIC_OBJECT= 2, - CF_NO_CONTACT_RESPONSE = 4, - CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution) - }; - - - SIMD_FORCE_INLINE bool mergesSimulationIslands() const - { - ///static objects, kinematic and object without contact response don't merge islands - return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0); - } - - - SIMD_FORCE_INLINE bool isStaticObject() const { - return (m_collisionFlags & CF_STATIC_OBJECT) != 0; - } - - SIMD_FORCE_INLINE bool isKinematicObject() const - { - return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0; - } - - SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const - { - return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ; - } - - SIMD_FORCE_INLINE bool hasContactResponse() const { - return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0; - } - - - btCollisionObject(); - - virtual ~btCollisionObject(); - - void setCollisionShape(btCollisionShape* collisionShape) - { - m_collisionShape = collisionShape; - } - - SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const - { - return m_collisionShape; - } - - SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() - { - return m_collisionShape; - } - - - - - int getActivationState() const { return m_activationState1;} - - void setActivationState(int newState); - - void setDeactivationTime(btScalar time) - { - m_deactivationTime = time; - } - btScalar getDeactivationTime() const - { - return m_deactivationTime; - } - - void forceActivationState(int newState); - - void activate(bool forceActivation = false); - - inline bool isActive() const - { - return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION)); - } - - void setRestitution(btScalar rest) - { - m_restitution = rest; - } - btScalar getRestitution() const - { - return m_restitution; - } - void setFriction(btScalar frict) - { - m_friction = frict; - } - btScalar getFriction() const - { - return m_friction; - } - - ///reserved for Bullet internal usage - void* getInternalOwner() - { - return m_internalOwner; - } - - const void* getInternalOwner() const - { - return m_internalOwner; - } - - btTransform& getWorldTransform() - { - return m_worldTransform; - } - - const btTransform& getWorldTransform() const - { - return m_worldTransform; - } - - void setWorldTransform(const btTransform& worldTrans) - { - m_worldTransform = worldTrans; - } - - - btBroadphaseProxy* getBroadphaseHandle() - { - return m_broadphaseHandle; - } - - const btBroadphaseProxy* getBroadphaseHandle() const - { - return m_broadphaseHandle; - } - - void setBroadphaseHandle(btBroadphaseProxy* handle) - { - m_broadphaseHandle = handle; - } - - - const btTransform& getInterpolationWorldTransform() const - { - return m_interpolationWorldTransform; - } - - btTransform& getInterpolationWorldTransform() - { - return m_interpolationWorldTransform; - } - - void setInterpolationWorldTransform(const btTransform& trans) - { - m_interpolationWorldTransform = trans; - } - - - const btVector3& getInterpolationLinearVelocity() const - { - return m_interpolationLinearVelocity; - } - - const btVector3& getInterpolationAngularVelocity() const - { - return m_interpolationAngularVelocity; - } - - const int getIslandTag() const - { - return m_islandTag1; - } - - void setIslandTag(int tag) - { - m_islandTag1 = tag; - } - - const int getCompanionId() const - { - return m_companionId; - } - - void setCompanionId(int id) - { - m_companionId = id; - } - - const btScalar getHitFraction() const - { - return m_hitFraction; - } - - void setHitFraction(btScalar hitFraction) - { - m_hitFraction = hitFraction; - } - - - const int getCollisionFlags() const - { - return m_collisionFlags; - } - - void setCollisionFlags(int flags) - { - m_collisionFlags = flags; - } - - ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: - btScalar getCcdSweptSphereRadius() const - { - return m_ccdSweptSphereRadius; - } - - ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: - void setCcdSweptSphereRadius(btScalar radius) - { - m_ccdSweptSphereRadius = radius; - } - - btScalar getCcdSquareMotionThreshold() const - { - return m_ccdSquareMotionThreshold; - } - - - /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold - void setCcdSquareMotionThreshold(btScalar ccdSquareMotionThreshold) - { - m_ccdSquareMotionThreshold = ccdSquareMotionThreshold; - } - - ///users can point to their objects, userPointer is not used by Bullet - void* getUserPointer() const - { - return m_userObjectPointer; - } - - ///users can point to their objects, userPointer is not used by Bullet - void setUserPointer(void* userPointer) - { - m_userObjectPointer = userPointer; - } - - inline bool checkCollideWith(btCollisionObject* co) - { - if (m_checkCollideWith) - return checkCollideWithOverride(co); - - return true; - } - - -} -; - -#endif //COLLISION_OBJECT_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp deleted file mode 100644 index b4828508bcb..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* -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. -*/ - -#include "btCollisionWorld.h" -#include "btCollisionDispatcher.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" -#include "BulletCollision/CollisionShapes/btConvexShape.h" - -#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting -#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" //for raycasting -#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" -#include "BulletCollision/CollisionShapes/btCompoundShape.h" -#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" -#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" - -#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" -#include "LinearMath/btAabbUtil2.h" -#include "LinearMath/btQuickprof.h" -#include "LinearMath/btStackAlloc.h" - -//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" -#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" - - -btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration) -:m_dispatcher1(dispatcher), -m_broadphasePairCache(pairCache) -{ - m_stackAlloc = collisionConfiguration->getStackAllocator(); - m_dispatchInfo.m_stackAllocator = m_stackAlloc; -} - - -btCollisionWorld::~btCollisionWorld() -{ - - //clean up remaining objects - int i; - for (i=0;igetBroadphaseHandle(); - if (bp) - { - // - // only clear the cached algorithms - // - getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); - getBroadphase()->destroyProxy(bp,m_dispatcher1); - } - } - - -} - - - - - - - - - - -void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask) -{ - - //check that the object isn't already added - btAssert( m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size()); - - m_collisionObjects.push_back(collisionObject); - - //calculate new AABB - btTransform trans = collisionObject->getWorldTransform(); - - btVector3 minAabb; - btVector3 maxAabb; - collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb); - - int type = collisionObject->getCollisionShape()->getShapeType(); - collisionObject->setBroadphaseHandle( getBroadphase()->createProxy( - minAabb, - maxAabb, - type, - collisionObject, - collisionFilterGroup, - collisionFilterMask, - m_dispatcher1 - )) ; - - - - - -} - - - - -void btCollisionWorld::performDiscreteCollisionDetection() -{ - btDispatcherInfo& dispatchInfo = getDispatchInfo(); - - BEGIN_PROFILE("perform Broadphase Collision Detection"); - - - //update aabb (of all moved objects) - - btVector3 aabbMin,aabbMax; - for (int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax); - m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax,m_dispatcher1); - } - - m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); - - END_PROFILE("perform Broadphase Collision Detection"); - - BEGIN_PROFILE("performDiscreteCollisionDetection"); - - btDispatcher* dispatcher = getDispatcher(); - if (dispatcher) - dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); - - END_PROFILE("performDiscreteCollisionDetection"); - -} - - - -void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) -{ - - - //bool removeFromBroadphase = false; - - { - - btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); - if (bp) - { - // - // only clear the cached algorithms - // - getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); - getBroadphase()->destroyProxy(bp,m_dispatcher1); - collisionObject->setBroadphaseHandle(0); - } - } - - - //swapremove - m_collisionObjects.remove(collisionObject); - -} - - - -void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, - btCollisionObject* collisionObject, - const btCollisionShape* collisionShape, - const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback,short int collisionFilterMask) -{ - - btSphereShape pointShape(btScalar(0.0)); - pointShape.setMargin(0.f); - - objectQuerySingle(&pointShape,rayFromTrans,rayToTrans, - collisionObject, - collisionShape, - colObjWorldTransform, - resultCallback,collisionFilterMask); -} - -void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans, - btCollisionObject* collisionObject, - const btCollisionShape* collisionShape, - const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback,short int collisionFilterMask) -{ - - - if (collisionShape->isConvex()) - { - btConvexCast::CastResult castResult; - castResult.m_fraction = btScalar(1.);//?? - - btConvexShape* convexShape = (btConvexShape*) collisionShape; - btVoronoiSimplexSolver simplexSolver; -#define USE_SUBSIMPLEX_CONVEX_CAST 1 -#ifdef USE_SUBSIMPLEX_CONVEX_CAST - btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); -#else - //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); - //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); -#endif //#USE_SUBSIMPLEX_CONVEX_CAST - - if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) - { - //add hit - if (castResult.m_normal.length2() > btScalar(0.0001)) - { - - if (castResult.m_fraction < resultCallback.m_closestHitFraction) - { -#ifdef USE_SUBSIMPLEX_CONVEX_CAST - //rotate normal into worldspace - castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal; -#endif //USE_SUBSIMPLEX_CONVEX_CAST - - castResult.m_normal.normalize(); - btCollisionWorld::LocalRayResult localRayResult - ( - collisionObject, - 0, - castResult.m_normal, - castResult.m_fraction - ); - - bool normalInWorldSpace = true; - resultCallback.AddSingleResult(localRayResult, normalInWorldSpace); - - } - } - } - } - else - { - - if (collisionShape->isConcave()) - { - - btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; - - btTransform worldTocollisionObject = colObjWorldTransform.inverse(); - - btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); - btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); - - //ConvexCast::CastResult - - struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback - { - btCollisionWorld::RayResultCallback* m_resultCallback; - btCollisionObject* m_collisionObject; - btTriangleMeshShape* m_triangleMesh; - - BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, - btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): - btTriangleRaycastCallback(from,to), - m_resultCallback(resultCallback), - m_collisionObject(collisionObject), - m_triangleMesh(triangleMesh) - { - } - - - virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) - { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = partId; - shapeInfo.m_triangleIndex = triangleIndex; - - btCollisionWorld::LocalRayResult rayResult - (m_collisionObject, - &shapeInfo, - hitNormalLocal, - hitFraction); - - bool normalInWorldSpace = false; - return m_resultCallback->AddSingleResult(rayResult,normalInWorldSpace); - - - } - - }; - - - BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); - rcb.m_hitFraction = resultCallback.m_closestHitFraction; - - btVector3 rayAabbMinLocal = rayFromLocal; - rayAabbMinLocal.setMin(rayToLocal); - btVector3 rayAabbMaxLocal = rayFromLocal; - rayAabbMaxLocal.setMax(rayToLocal); - - triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); - - } else - { - //todo: use AABB tree or other BVH acceleration structure! - if (collisionShape->isCompound()) - { - const btCompoundShape* compoundShape = static_cast(collisionShape); - int i=0; - for (i=0;igetNumChildShapes();i++) - { - btTransform childTrans = compoundShape->getChildTransform(i); - const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); - btTransform childWorldTrans = colObjWorldTransform * childTrans; - objectQuerySingle(castShape, rayFromTrans,rayToTrans, - collisionObject, - childCollisionShape, - childWorldTrans, - resultCallback, collisionFilterMask); - - } - - - } - } - } -} - -void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask) -{ - - - btTransform rayFromTrans,rayToTrans; - rayFromTrans.setIdentity(); - rayFromTrans.setOrigin(rayFromWorld); - rayToTrans.setIdentity(); - - rayToTrans.setOrigin(rayToWorld); - - /// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD) - - int i; - for (i=0;igetBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { - //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); - btVector3 collisionObjectAabbMin,collisionObjectAabbMax; - collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); - - btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing - btVector3 hitNormal; - if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) - { - rayTestSingle(rayFromTrans,rayToTrans, - collisionObject, - collisionObject->getCollisionShape(), - collisionObject->getWorldTransform(), - resultCallback); - } - } - } - -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h deleted file mode 100644 index bda03ccedeb..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ /dev/null @@ -1,259 +0,0 @@ -/* -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. -*/ - - -/** - * @mainpage Bullet Documentation - * - * @section intro_sec Introduction - * Bullet Collision Detection & Physics SDK - * - * Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ). - * - * There is the Physics Forum for Feedback and bteral Collision Detection and Physics discussions. - * Please visit http://www.continuousphysics.com/Bullet/phpBB2/index.php - * - * @section install_sec Installation - * - * @subsection step1 Step 1: Download - * You can download the Bullet Physics Library from our website: http://www.continuousphysics.com/Bullet/ - * @subsection step2 Step 2: Building - * Bullet comes with autogenerated Project Files for Microsoft Visual Studio 6, 7, 7.1 and 8. - * The main Workspace/Solution is located in Bullet/msvc/8/wksbullet.sln (replace 8 with your version). - * - * Under other platforms, like Linux or Mac OS-X, Bullet can be build using either using cmake, http://www.cmake.org, or jam, http://www.perforce.com/jam/jam.html . cmake can autogenerate Xcode, KDevelop, MSVC and other build systems. just run cmake . in the root of Bullet. - * Jam is a build system that can build the library, demos and also autogenerate the MSVC Project Files. - * So if you are not using MSVC, you can run configure and jam . - * If you don't have jam installed, you can make jam from the included jam-2.5 sources, or download jam from ftp://ftp.perforce.com/pub/jam/ - * - * @subsection step3 Step 3: Testing demos - * Try to run and experiment with CcdPhysicsDemo executable as a starting point. - * Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation. - * The Dependencies can be seen in this documentation under Directories - * - * @subsection step4 Step 4: Integrating in your application, Full Rigid Body Simulation - * Check out CcdPhysicsDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform. - * PLEASE NOTE THE CcdPhysicsEnvironment and CcdPhysicsController is obsolete and will be removed. It has been replaced by classes derived frmo btDynamicsWorld and btRididBody - * @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras) - * Bullet Collision Detection can also be used without the Dynamics/Extras. - * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo. Also in Extras/test_BulletOde.cpp there is a sample Collision Detection integration with Open Dynamics Engine, ODE, http://www.ode.org - * @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation. - * Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector. - * - * @section copyright Copyright - * Copyright (C) 2005-2007 Erwin Coumans, some contributions Copyright Gino van den Bergen, Christer Ericson, Simon Hobbs, Ricardo Padrela, F Richter(res), Stephane Redon - * Special thanks to all visitors of the Bullet Physics forum, and in particular above contributors, Dave Eberle, Dirk Gregorius, Erin Catto, Dave Eberle, Adam Moravanszky, - * Pierre Terdiman, Kenny Erleben, Russell Smith, Oliver Strunk, Jan Paul van Waveren, Marten Svanfeldt. - * - */ - - - -#ifndef COLLISION_WORLD_H -#define COLLISION_WORLD_H - -class btStackAlloc; -class btCollisionShape; -class btConvexShape; -class btBroadphaseInterface; -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransform.h" -#include "btCollisionObject.h" -#include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray -#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" -#include "LinearMath/btAlignedObjectArray.h" - -///CollisionWorld is interface and container for the collision detection -class btCollisionWorld -{ - - -protected: - - btAlignedObjectArray m_collisionObjects; - - btDispatcher* m_dispatcher1; - - btDispatcherInfo m_dispatchInfo; - - btStackAlloc* m_stackAlloc; - - btBroadphaseInterface* m_broadphasePairCache; - -public: - - //this constructor doesn't own the dispatcher and paircache/broadphase - btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration); - - virtual ~btCollisionWorld(); - - - btBroadphaseInterface* getBroadphase() - { - return m_broadphasePairCache; - } - - btOverlappingPairCache* getPairCache() - { - return m_broadphasePairCache->getOverlappingPairCache(); - } - - - btDispatcher* getDispatcher() - { - return m_dispatcher1; - } - - ///LocalShapeInfo gives extra information for complex shapes - ///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart - struct LocalShapeInfo - { - int m_shapePart; - int m_triangleIndex; - - //const btCollisionShape* m_shapeTemp; - //const btTransform* m_shapeLocalTransform; - }; - - struct LocalRayResult - { - LocalRayResult(btCollisionObject* collisionObject, - LocalShapeInfo* localShapeInfo, - const btVector3& hitNormalLocal, - btScalar hitFraction) - :m_collisionObject(collisionObject), - m_localShapeInfo(localShapeInfo), - m_hitNormalLocal(hitNormalLocal), - m_hitFraction(hitFraction) - { - } - - btCollisionObject* m_collisionObject; - LocalShapeInfo* m_localShapeInfo; - btVector3 m_hitNormalLocal; - btScalar m_hitFraction; - - }; - - ///RayResultCallback is used to report new raycast results - struct RayResultCallback - { - virtual ~RayResultCallback() - { - } - btScalar m_closestHitFraction; - bool HasHit() - { - return (m_closestHitFraction < btScalar(1.)); - } - - RayResultCallback() - :m_closestHitFraction(btScalar(1.)) - { - } - virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0; - }; - - struct ClosestRayResultCallback : public RayResultCallback - { - ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) - :m_rayFromWorld(rayFromWorld), - m_rayToWorld(rayToWorld), - m_collisionObject(0) - { - } - - btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction - btVector3 m_rayToWorld; - - btVector3 m_hitNormalWorld; - btVector3 m_hitPointWorld; - btCollisionObject* m_collisionObject; - - virtual btScalar AddSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) - { - -//caller already does the filter on the m_closestHitFraction - assert(rayResult.m_hitFraction <= m_closestHitFraction); - - m_closestHitFraction = rayResult.m_hitFraction; - m_collisionObject = rayResult.m_collisionObject; - if (normalInWorldSpace) - { - m_hitNormalWorld = rayResult.m_hitNormalLocal; - } else - { - ///need to transform normal into worldspace - m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; - } - m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); - return rayResult.m_hitFraction; - } - }; - - - - - int getNumCollisionObjects() const - { - return int(m_collisionObjects.size()); - } - - /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback - /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. - void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1); - - /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. - /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. - /// This allows more customization. - static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, - btCollisionObject* collisionObject, - const btCollisionShape* collisionShape, - const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback, short int collisionFilterMask=-1); - - /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest. - static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans, - btCollisionObject* collisionObject, - const btCollisionShape* collisionShape, - const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback, short int collisionFilterMask=-1); - - void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1); - - btCollisionObjectArray& getCollisionObjectArray() - { - return m_collisionObjects; - } - - const btCollisionObjectArray& getCollisionObjectArray() const - { - return m_collisionObjects; - } - - - void removeCollisionObject(btCollisionObject* collisionObject); - - virtual void performDiscreteCollisionDetection(); - - btDispatcherInfo& getDispatchInfo() - { - return m_dispatchInfo; - } - -}; - - -#endif //COLLISION_WORLD_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp deleted file mode 100644 index 7c0c7a3b0a9..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* -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. -*/ - -#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btCompoundShape.h" - - -btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) -:btCollisionAlgorithm(ci), -m_isSwapped(isSwapped) -{ - btCollisionObject* colObj = m_isSwapped? body1 : body0; - btCollisionObject* otherObj = m_isSwapped? body0 : body1; - assert (colObj->getCollisionShape()->isCompound()); - - btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); - int numChildren = compoundShape->getNumChildShapes(); - int i; - - m_childCollisionAlgorithms.resize(numChildren); - for (i=0;igetChildShape(i); - btCollisionShape* orgShape = colObj->getCollisionShape(); - colObj->setCollisionShape( childShape ); - m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj); - colObj->setCollisionShape( orgShape ); - } -} - - -btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() -{ - int numChildren = m_childCollisionAlgorithms.size(); - int i; - for (i=0;i~btCollisionAlgorithm(); - m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); - } -} - -void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - btCollisionObject* colObj = m_isSwapped? body1 : body0; - btCollisionObject* otherObj = m_isSwapped? body0 : body1; - - assert (colObj->getCollisionShape()->isCompound()); - btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); - - //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps - //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals - //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: - //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1 - //then use each overlapping node AABB against Tree0 - //and vise versa. - - int numChildren = m_childCollisionAlgorithms.size(); - int i; - for (i=0;igetChildShape(i); - - //backup - btTransform orgTrans = colObj->getWorldTransform(); - btCollisionShape* orgShape = colObj->getCollisionShape(); - - const btTransform& childTrans = compoundShape->getChildTransform(i); - //btTransform newChildWorldTrans = orgTrans*childTrans ; - colObj->setWorldTransform( orgTrans*childTrans ); - //the contactpoint is still projected back using the original inverted worldtrans - colObj->setCollisionShape( childShape ); - m_childCollisionAlgorithms[i]->processCollision(colObj,otherObj,dispatchInfo,resultOut); - //revert back - colObj->setCollisionShape( orgShape); - colObj->setWorldTransform( orgTrans ); - } -} - -btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - - btCollisionObject* colObj = m_isSwapped? body1 : body0; - btCollisionObject* otherObj = m_isSwapped? body0 : body1; - - assert (colObj->getCollisionShape()->isCompound()); - - btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); - - //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps - //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals - //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: - //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1 - //then use each overlapping node AABB against Tree0 - //and vise versa. - - btScalar hitFraction = btScalar(1.); - - int numChildren = m_childCollisionAlgorithms.size(); - int i; - for (i=0;igetChildShape(i); - - //backup - btTransform orgTrans = colObj->getWorldTransform(); - btCollisionShape* orgShape = colObj->getCollisionShape(); - - const btTransform& childTrans = compoundShape->getChildTransform(i); - //btTransform newChildWorldTrans = orgTrans*childTrans ; - colObj->setWorldTransform( orgTrans*childTrans ); - - colObj->setCollisionShape( childShape ); - btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut); - if (fracsetCollisionShape( orgShape); - colObj->setWorldTransform( orgTrans); - } - return hitFraction; - -} - - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h deleted file mode 100644 index a381d8b3c3f..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -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. -*/ - -#ifndef COMPOUND_COLLISION_ALGORITHM_H -#define COMPOUND_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" - -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -class btDispatcher; -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "btCollisionCreateFunc.h" -#include "LinearMath/btAlignedObjectArray.h" -class btDispatcher; - -/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes -/// Place holder, not fully implemented yet -class btCompoundCollisionAlgorithm : public btCollisionAlgorithm -{ - btAlignedObjectArray m_childCollisionAlgorithms; - bool m_isSwapped; - -public: - - btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); - - virtual ~btCompoundCollisionAlgorithm(); - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); - return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false); - } - }; - - struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); - return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true); - } - }; - -}; - -#endif //COMPOUND_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp deleted file mode 100644 index 559b633feb9..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp +++ /dev/null @@ -1,314 +0,0 @@ -/* -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. -*/ - - -#include "btConvexConcaveCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionShapes/btConcaveShape.h" -#include "BulletCollision/CollisionDispatch/btManifoldResult.h" -#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" -#include "BulletCollision/CollisionShapes/btTriangleShape.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "LinearMath/btIDebugDraw.h" -#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" - -btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) -: btCollisionAlgorithm(ci), -m_isSwapped(isSwapped), -m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) -{ -} - -btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm() -{ -} - - - -btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): - m_dispatcher(dispatcher), - m_dispatchInfoPtr(0) -{ - m_convexBody = isSwapped? body1:body0; - m_triBody = isSwapped? body0:body1; - - // - // create the manifold from the dispatcher 'manifold pool' - // - m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); - - clearCache(); -} - -btConvexTriangleCallback::~btConvexTriangleCallback() -{ - clearCache(); - m_dispatcher->releaseManifold( m_manifoldPtr ); - -} - - -void btConvexTriangleCallback::clearCache() -{ - m_dispatcher->clearManifold(m_manifoldPtr); -}; - - - -void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) -{ - - //just for debugging purposes - //printf("triangle %d",m_triangleCount++); - - - //aabb filter is already applied! - - btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher1 = m_dispatcher; - - btCollisionObject* ob = static_cast(m_triBody); - - - - ///debug drawing of the overlapping triangles - if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() > 0) - { - btVector3 color(255,255,0); - btTransform& tr = ob->getWorldTransform(); - m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); - m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); - m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); - - //btVector3 center = triangle[0] + triangle[1]+triangle[2]; - //center *= btScalar(0.333333); - //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(center),color); - //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(center),color); - //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(center),color); - - } - - - //btCollisionObject* colObj = static_cast(m_convexProxy->m_clientObject); - - if (m_convexBody->getCollisionShape()->isConvex()) - { - btTriangleShape tm(triangle[0],triangle[1],triangle[2]); - tm.setMargin(m_collisionMarginTriangle); - - - btCollisionShape* tmpShape = ob->getCollisionShape(); - ob->setCollisionShape( &tm ); - - - btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); - ///this should use the btDispatcher, so the actual registered algorithm is used - // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); - - m_resultOut->setShapeIdentifiers(-1,-1,partId,triangleIndex); - // cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex); -// cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); - colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); - colAlgo->~btCollisionAlgorithm(); - ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); - ob->setCollisionShape( tmpShape ); - - } - - - -} - - - -void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - m_dispatchInfoPtr = &dispatchInfo; - m_collisionMarginTriangle = collisionMarginTriangle; - m_resultOut = resultOut; - - //recalc aabbs - btTransform convexInTriangleSpace; - convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_convexBody->getWorldTransform(); - btCollisionShape* convexShape = static_cast(m_convexBody->getCollisionShape()); - //CollisionShape* triangleShape = static_cast(triBody->m_collisionShape); - convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax); - btScalar extraMargin = collisionMarginTriangle; - btVector3 extra(extraMargin,extraMargin,extraMargin); - - m_aabbMax += extra; - m_aabbMin -= extra; - -} - -void btConvexConcaveCollisionAlgorithm::clearCache() -{ - m_btConvexTriangleCallback.clearCache(); - -} - -void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - - - btCollisionObject* convexBody = m_isSwapped ? body1 : body0; - btCollisionObject* triBody = m_isSwapped ? body0 : body1; - - if (triBody->getCollisionShape()->isConcave()) - { - - - btCollisionObject* triOb = triBody; - btConcaveShape* concaveShape = static_cast( triOb->getCollisionShape()); - - if (convexBody->getCollisionShape()->isConvex()) - { - btScalar collisionMarginTriangle = concaveShape->getMargin(); - - resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr); - m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut); - - //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here. - //m_dispatcher->clearManifold(m_btConvexTriangleCallback.m_manifoldPtr); - - m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody); - - concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax()); - - resultOut->refreshContactPoints(); - - } - - } - -} - - -btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)resultOut; - (void)dispatchInfo; - btCollisionObject* convexbody = m_isSwapped ? body1 : body0; - btCollisionObject* triBody = m_isSwapped ? body0 : body1; - - - //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) - - //only perform CCD above a certain threshold, this prevents blocking on the long run - //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... - btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); - if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) - { - return btScalar(1.); - } - - //const btVector3& from = convexbody->m_worldTransform.getOrigin(); - //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); - //todo: only do if the motion exceeds the 'radius' - - btTransform triInv = triBody->getWorldTransform().inverse(); - btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); - btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); - - struct LocalTriangleSphereCastCallback : public btTriangleCallback - { - btTransform m_ccdSphereFromTrans; - btTransform m_ccdSphereToTrans; - btTransform m_meshTransform; - - btScalar m_ccdSphereRadius; - btScalar m_hitFraction; - - - LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) - :m_ccdSphereFromTrans(from), - m_ccdSphereToTrans(to), - m_ccdSphereRadius(ccdSphereRadius), - m_hitFraction(hitFraction) - { - } - - - virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) - { - (void)partId; - (void)triangleIndex; - //do a swept sphere for now - btTransform ident; - ident.setIdentity(); - btConvexCast::CastResult castResult; - castResult.m_fraction = m_hitFraction; - btSphereShape pointShape(m_ccdSphereRadius); - btTriangleShape triShape(triangle[0],triangle[1],triangle[2]); - btVoronoiSimplexSolver simplexSolver; - btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); - //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); - //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); - //local space? - - if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, - ident,ident,castResult)) - { - if (m_hitFraction > castResult.m_fraction) - m_hitFraction = castResult.m_fraction; - } - - } - - }; - - - - - - if (triBody->getCollisionShape()->isConcave()) - { - btVector3 rayAabbMin = convexFromLocal.getOrigin(); - rayAabbMin.setMin(convexToLocal.getOrigin()); - btVector3 rayAabbMax = convexFromLocal.getOrigin(); - rayAabbMax.setMax(convexToLocal.getOrigin()); - btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); - rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); - rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); - - btScalar curHitFraction = btScalar(1.); //is this available? - LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, - convexbody->getCcdSweptSphereRadius(),curHitFraction); - - raycastCallback.m_hitFraction = convexbody->getHitFraction(); - - btCollisionObject* concavebody = triBody; - - btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); - - if (triangleMesh) - { - triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); - } - - - - if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) - { - convexbody->setHitFraction( raycastCallback.m_hitFraction); - return raycastCallback.m_hitFraction; - } - } - - return btScalar(1.); - -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h deleted file mode 100644 index da33e988991..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h +++ /dev/null @@ -1,113 +0,0 @@ -/* -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. -*/ - -#ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H -#define CONVEX_CONCAVE_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" -#include "BulletCollision/CollisionShapes/btTriangleCallback.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -class btDispatcher; -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "btCollisionCreateFunc.h" - -///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called. -class btConvexTriangleCallback : public btTriangleCallback -{ - btCollisionObject* m_convexBody; - btCollisionObject* m_triBody; - - btVector3 m_aabbMin; - btVector3 m_aabbMax ; - - btManifoldResult* m_resultOut; - - btDispatcher* m_dispatcher; - const btDispatcherInfo* m_dispatchInfoPtr; - btScalar m_collisionMarginTriangle; - -public: -int m_triangleCount; - - btPersistentManifold* m_manifoldPtr; - - btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); - - void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual ~btConvexTriangleCallback(); - - virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); - - void clearCache(); - - SIMD_FORCE_INLINE const btVector3& getAabbMin() const - { - return m_aabbMin; - } - SIMD_FORCE_INLINE const btVector3& getAabbMax() const - { - return m_aabbMax; - } - -}; - - - - -/// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes. -class btConvexConcaveCollisionAlgorithm : public btCollisionAlgorithm -{ - - bool m_isSwapped; - - btConvexTriangleCallback m_btConvexTriangleCallback; - - -public: - - btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); - - virtual ~btConvexConcaveCollisionAlgorithm(); - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - void clearCache(); - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); - return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); - } - }; - - struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); - return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); - } - }; - -}; - -#endif //CONVEX_CONCAVE_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp deleted file mode 100644 index d1692cdac69..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* -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. -*/ - -#include "btConvexConvexAlgorithm.h" - -#include -#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionShapes/btBoxShape.h" -#include "BulletCollision/CollisionDispatch/btManifoldResult.h" - -#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" -#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" - - - -#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" -#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" - -#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" - -#include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" - - - - - - - - - -btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) -{ - m_simplexSolver = simplexSolver; - m_pdSolver = pdSolver; -} - -btConvexConvexAlgorithm::CreateFunc::~CreateFunc() -{ -} - -btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) -: btCollisionAlgorithm(ci), -m_gjkPairDetector(0,0,simplexSolver,pdSolver), -m_ownManifold (false), -m_manifoldPtr(mf), -m_lowLevelOfDetail(false) -{ - (void)body0; - (void)body1; - - -} - - - - -btConvexConvexAlgorithm::~btConvexConvexAlgorithm() -{ - if (m_ownManifold) - { - if (m_manifoldPtr) - m_dispatcher->releaseManifold(m_manifoldPtr); - } -} - -void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel) -{ - m_lowLevelOfDetail = useLowLevel; -} - - - - - -// -// Convex-Convex collision algorithm -// -void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - - if (!m_manifoldPtr) - { - //swapped? - m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); - m_ownManifold = true; - } - resultOut->setPersistentManifold(m_manifoldPtr); - -#ifdef USE_BT_GJKEPA - btConvexShape* shape0(static_cast(body0->getCollisionShape())); - btConvexShape* shape1(static_cast(body1->getCollisionShape())); - const btScalar radialmargin(0/*shape0->getMargin()+shape1->getMargin()*/); - btGjkEpaSolver::sResults results; - if(btGjkEpaSolver::Collide( shape0,body0->getWorldTransform(), - shape1,body1->getWorldTransform(), - radialmargin,results)) - { - dispatchInfo.m_debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); - resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); - } -#else - - btConvexShape* min0 = static_cast(body0->getCollisionShape()); - btConvexShape* min1 = static_cast(body1->getCollisionShape()); - - btGjkPairDetector::ClosestPointInput input; - - //TODO: if (dispatchInfo.m_useContinuous) - m_gjkPairDetector.setMinkowskiA(min0); - m_gjkPairDetector.setMinkowskiB(min1); - input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); - input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; - input.m_stackAlloc = dispatchInfo.m_stackAllocator; - -// input.m_maximumDistanceSquared = btScalar(1e30); - - input.m_transformA = body0->getWorldTransform(); - input.m_transformB = body1->getWorldTransform(); - - m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); -#endif - - if (m_ownManifold) - { - resultOut->refreshContactPoints(); - } - -} - - - -bool disableCcd = false; -btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)resultOut; - (void)dispatchInfo; - ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold - - ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold - ///col0->m_worldTransform, - btScalar resultFraction = btScalar(1.); - - - btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2(); - btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2(); - - if (squareMot0 < col0->getCcdSquareMotionThreshold() && - squareMot1 < col1->getCcdSquareMotionThreshold()) - return resultFraction; - - if (disableCcd) - return btScalar(1.); - - - //An adhoc way of testing the Continuous Collision Detection algorithms - //One object is approximated as a sphere, to simplify things - //Starting in penetration should report no time of impact - //For proper CCD, better accuracy and handling of 'allowed' penetration should be added - //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies) - - - /// Convex0 against sphere for Convex1 - { - btConvexShape* convex0 = static_cast(col0->getCollisionShape()); - - btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation - btConvexCast::CastResult result; - btVoronoiSimplexSolver voronoiSimplex; - //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); - ///Simplification, one object is simplified as a sphere - btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex); - //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); - if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), - col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) - { - - //store result.m_fraction in both bodies - - if (col0->getHitFraction()> result.m_fraction) - col0->setHitFraction( result.m_fraction ); - - if (col1->getHitFraction() > result.m_fraction) - col1->setHitFraction( result.m_fraction); - - if (resultFraction > result.m_fraction) - resultFraction = result.m_fraction; - - } - - - - - } - - /// Sphere (for convex0) against Convex1 - { - btConvexShape* convex1 = static_cast(col1->getCollisionShape()); - - btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation - btConvexCast::CastResult result; - btVoronoiSimplexSolver voronoiSimplex; - //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); - ///Simplification, one object is simplified as a sphere - btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex); - //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); - if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), - col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) - { - - //store result.m_fraction in both bodies - - if (col0->getHitFraction() > result.m_fraction) - col0->setHitFraction( result.m_fraction); - - if (col1->getHitFraction() > result.m_fraction) - col1->setHitFraction( result.m_fraction); - - if (resultFraction > result.m_fraction) - resultFraction = result.m_fraction; - - } - } - - return resultFraction; - -} - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h deleted file mode 100644 index ca58bce25f1..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -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. -*/ - -#ifndef CONVEX_CONVEX_ALGORITHM_H -#define CONVEX_CONVEX_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" -#include "btCollisionCreateFunc.h" -#include "btCollisionDispatcher.h" - -class btConvexPenetrationDepthSolver; - -///ConvexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations. -class btConvexConvexAlgorithm : public btCollisionAlgorithm -{ - btGjkPairDetector m_gjkPairDetector; -public: - - bool m_ownManifold; - btPersistentManifold* m_manifoldPtr; - bool m_lowLevelOfDetail; - - -public: - - btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); - - virtual ~btConvexConvexAlgorithm(); - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - void setLowLevelOfDetail(bool useLowLevel); - - - const btPersistentManifold* getManifold() - { - return m_manifoldPtr; - } - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - btConvexPenetrationDepthSolver* m_pdSolver; - btSimplexSolverInterface* m_simplexSolver; - - CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); - - virtual ~CreateFunc(); - - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm)); - return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver); - } - }; - - -}; - -#endif //CONVEX_CONVEX_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp deleted file mode 100644 index 661270b9bcb..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp +++ /dev/null @@ -1,237 +0,0 @@ - -/* -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. -*/ - -#include "btDefaultCollisionConfiguration.h" - -#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" - - - -#include "LinearMath/btStackAlloc.h" -#include "LinearMath/btPoolAllocator.h" - - - -#define DEFAULT_MAX_OVERLAPPING_PAIRS 65535 -#define DEFAULT_STACK_ALLOCATOR_SIZE (5*1024*1024) - - -btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool) -{ - - void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16); - m_simplexSolver = new (mem)btVoronoiSimplexSolver(); - mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16); - m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver; - - //default CreationFunctions, filling the m_doubleDispatch table - mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16); - m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); - mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); - m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc; - mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); - m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc; - mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16); - m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc; - mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16); - m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc; - mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16); - m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc; - - mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16); - m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc; - mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); - m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc; - mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); - m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc; - m_boxSphereCF->m_swapped = true; - mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); - m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; - mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); - m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; - m_triangleSphereCF->m_swapped = true; - - - ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool - int maxSize = sizeof(btConvexConvexAlgorithm); - int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm); - int maxSize3 = sizeof(btCompoundCollisionAlgorithm); - int maxSize4 = sizeof(btEmptyAlgorithm); - - int collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2); - collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3); - collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4); - - if (stackAlloc) - { - m_ownsStackAllocator = false; - this->m_stackAlloc = stackAlloc; - } else - { - m_ownsStackAllocator = true; - void* mem = btAlignedAlloc(sizeof(btStackAlloc),16); - m_stackAlloc = new(mem)btStackAlloc(DEFAULT_STACK_ALLOCATOR_SIZE); - } - - if (persistentManifoldPool) - { - m_ownsPersistentManifoldPool = false; - m_persistentManifoldPool = persistentManifoldPool; - } else - { - m_ownsPersistentManifoldPool = true; - void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); - m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),DEFAULT_MAX_OVERLAPPING_PAIRS); - } - - if (collisionAlgorithmPool) - { - m_ownsCollisionAlgorithmPool = false; - m_collisionAlgorithmPool = collisionAlgorithmPool; - } else - { - m_ownsCollisionAlgorithmPool = true; - void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); - m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,DEFAULT_MAX_OVERLAPPING_PAIRS); - } - - -} - -btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration() -{ - if (m_ownsStackAllocator) - { - m_stackAlloc->destroy(); - m_stackAlloc->~btStackAlloc(); - btAlignedFree(m_stackAlloc); - } - if (m_ownsCollisionAlgorithmPool) - { - m_collisionAlgorithmPool->~btPoolAllocator(); - btAlignedFree(m_collisionAlgorithmPool); - } - if (m_ownsPersistentManifoldPool) - { - m_persistentManifoldPool->~btPoolAllocator(); - btAlignedFree(m_persistentManifoldPool); - } - - m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_convexConvexCreateFunc); - - m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_convexConcaveCreateFunc); - m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_swappedConvexConcaveCreateFunc); - - m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_compoundCreateFunc); - - m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_swappedCompoundCreateFunc); - - m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_emptyCreateFunc); - - m_sphereSphereCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_sphereSphereCF); - - m_sphereBoxCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_sphereBoxCF); - m_boxSphereCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_boxSphereCF); - m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_sphereTriangleCF); - m_triangleSphereCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_triangleSphereCF); - - m_simplexSolver->~btVoronoiSimplexSolver(); - btAlignedFree(m_simplexSolver); - m_pdSolver->~btGjkEpaPenetrationDepthSolver(); - btAlignedFree(m_pdSolver); - - -} - - -btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) -{ - - - if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) - { - return m_sphereSphereCF; - } - - if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE)) - { - return m_sphereBoxCF; - } - - if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) - { - return m_boxSphereCF; - } - - if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE)) - { - return m_sphereTriangleCF; - } - - if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) - { - return m_triangleSphereCF; - } - - - if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) - { - return m_convexConvexCreateFunc; - } - - if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) - { - return m_convexConcaveCreateFunc; - } - - if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) - { - return m_swappedConvexConcaveCreateFunc; - } - - if (btBroadphaseProxy::isCompound(proxyType0)) - { - return m_compoundCreateFunc; - } else - { - if (btBroadphaseProxy::isCompound(proxyType1)) - { - return m_swappedCompoundCreateFunc; - } - } - - //failed to find an algorithm - return m_emptyCreateFunc; -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h deleted file mode 100644 index 2e99f1db18f..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -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. -*/ - -#ifndef BT_DEFAULT_COLLISION_CONFIGURATION -#define BT_DEFAULT_COLLISION_CONFIGURATION - -#include "btCollisionConfiguration.h" -class btVoronoiSimplexSolver; -class btGjkEpaPenetrationDepthSolver; - - -///btCollisionConfiguration allows to configure Bullet collision detection -///stack allocator, pool memory allocators -///todo: describe the meaning -class btDefaultCollisionConfiguration : public btCollisionConfiguration -{ - - int m_persistentManifoldPoolSize; - - btStackAlloc* m_stackAlloc; - bool m_ownsStackAllocator; - - btPoolAllocator* m_persistentManifoldPool; - bool m_ownsPersistentManifoldPool; - - btPoolAllocator* m_collisionAlgorithmPool; - bool m_ownsCollisionAlgorithmPool; - - //default simplex/penetration depth solvers - btVoronoiSimplexSolver* m_simplexSolver; - btGjkEpaPenetrationDepthSolver* m_pdSolver; - - //default CreationFunctions, filling the m_doubleDispatch table - btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; - btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; - btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; - btCollisionAlgorithmCreateFunc* m_sphereSphereCF; - btCollisionAlgorithmCreateFunc* m_sphereBoxCF; - btCollisionAlgorithmCreateFunc* m_boxSphereCF; - btCollisionAlgorithmCreateFunc* m_sphereTriangleCF; - btCollisionAlgorithmCreateFunc* m_triangleSphereCF; - -public: - - btDefaultCollisionConfiguration(btStackAlloc* stackAlloc=0,btPoolAllocator* persistentManifoldPool=0,btPoolAllocator* collisionAlgorithmPool=0); - - virtual ~btDefaultCollisionConfiguration(); - - ///memory pools - virtual btPoolAllocator* getPersistentManifoldPool() - { - return m_persistentManifoldPool; - } - - virtual btPoolAllocator* getCollisionAlgorithmPool() - { - return m_collisionAlgorithmPool; - } - - virtual btStackAlloc* getStackAllocator() - { - return m_stackAlloc; - } - - - btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); - - -}; - -#endif //BT_DEFAULT_COLLISION_CONFIGURATION - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp deleted file mode 100644 index 936054387c4..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -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. -*/ - -#include "btEmptyCollisionAlgorithm.h" - - - -btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) - : btCollisionAlgorithm(ci) -{ -} - -void btEmptyAlgorithm::processCollision (btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* ) -{ -} - -btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* ) -{ - return btScalar(1.); -} - - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h deleted file mode 100644 index 89e7080780c..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -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. -*/ - -#ifndef EMPTY_ALGORITH -#define EMPTY_ALGORITH -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "btCollisionCreateFunc.h" -#include "btCollisionDispatcher.h" - -#define ATTRIBUTE_ALIGNED(a) - -///EmptyAlgorithm is a stub for unsupported collision pairs. -///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame. -class btEmptyAlgorithm : public btCollisionAlgorithm -{ - -public: - - btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci); - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - (void)body0; - (void)body1; - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm)); - return new(mem) btEmptyAlgorithm(ci); - } - }; - -} ATTRIBUTE_ALIGNED(16); - -#endif //EMPTY_ALGORITH diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp deleted file mode 100644 index 61c4c231da4..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* -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. -*/ - - -#include "btManifoldResult.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" - - -///This is to allow MaterialCombiner/Custom Friction/Restitution values -ContactAddedCallback gContactAddedCallback=0; - -///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; -inline btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1) -{ - btScalar friction = body0->getFriction() * body1->getFriction(); - - const btScalar MAX_FRICTION = btScalar(10.); - if (friction < -MAX_FRICTION) - friction = -MAX_FRICTION; - if (friction > MAX_FRICTION) - friction = MAX_FRICTION; - return friction; - -} - -inline btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1) -{ - return body0->getRestitution() * body1->getRestitution(); -} - - - -btManifoldResult::btManifoldResult(btCollisionObject* body0,btCollisionObject* body1) - :m_manifoldPtr(0), - m_body0(body0), - m_body1(body1) -{ - m_rootTransA = body0->getWorldTransform(); - m_rootTransB = body1->getWorldTransform(); -} - - -void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) -{ - assert(m_manifoldPtr); - //order in manifold needs to match - - if (depth > m_manifoldPtr->getContactBreakingThreshold()) - return; - - bool isSwapped = m_manifoldPtr->getBody0() != m_body0; - - btVector3 pointA = pointInWorld + normalOnBInWorld * depth; - - btVector3 localA; - btVector3 localB; - - if (isSwapped) - { - localA = m_rootTransB.invXform(pointA ); - localB = m_rootTransA.invXform(pointInWorld); - } else - { - localA = m_rootTransA.invXform(pointA ); - localB = m_rootTransB.invXform(pointInWorld); - } - - btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); - newPt.m_positionWorldOnA = pointA; - newPt.m_positionWorldOnB = pointInWorld; - - int insertIndex = m_manifoldPtr->getCacheEntry(newPt); - - newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1); - newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1); - - - ///todo, check this for any side effects - if (insertIndex >= 0) - { - //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); - m_manifoldPtr->replaceContactPoint(newPt,insertIndex); - } else - { - m_manifoldPtr->AddManifoldPoint(newPt); - } - - //User can override friction and/or restitution - if (gContactAddedCallback && - //and if either of the two bodies requires custom material - ((m_body0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) || - (m_body1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK))) - { - //experimental feature info, for per-triangle material etc. - btCollisionObject* obj0 = isSwapped? m_body1 : m_body0; - btCollisionObject* obj1 = isSwapped? m_body0 : m_body1; - (*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1); - } - -} - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h deleted file mode 100644 index 5aac9a46f6a..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -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. -*/ - - -#ifndef MANIFOLD_RESULT_H -#define MANIFOLD_RESULT_H - -class btCollisionObject; -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -class btManifoldPoint; - -#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" - -#include "LinearMath/btTransform.h" - -typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1); -extern ContactAddedCallback gContactAddedCallback; - - - -///btManifoldResult is a helper class to manage contact results. -class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result -{ - btPersistentManifold* m_manifoldPtr; - - //we need this for compounds - btTransform m_rootTransA; - btTransform m_rootTransB; - - btCollisionObject* m_body0; - btCollisionObject* m_body1; - int m_partId0; - int m_partId1; - int m_index0; - int m_index1; -public: - - btManifoldResult() - { - } - - btManifoldResult(btCollisionObject* body0,btCollisionObject* body1); - - virtual ~btManifoldResult() {}; - - void setPersistentManifold(btPersistentManifold* manifoldPtr) - { - m_manifoldPtr = manifoldPtr; - } - - const btPersistentManifold* getPersistentManifold() const - { - return m_manifoldPtr; - } - btPersistentManifold* getPersistentManifold() - { - return m_manifoldPtr; - } - - virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1) - { - m_partId0=partId0; - m_partId1=partId1; - m_index0=index0; - m_index1=index1; - } - - virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); - - SIMD_FORCE_INLINE void refreshContactPoints() - { - btAssert(m_manifoldPtr); - if (!m_manifoldPtr->getNumContacts()) - return; - - bool isSwapped = m_manifoldPtr->getBody0() != m_body0; - - if (isSwapped) - { - m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA); - } else - { - m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB); - } - } - - -}; - -#endif //MANIFOLD_RESULT_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp deleted file mode 100644 index 6c42d1706ff..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp +++ /dev/null @@ -1,359 +0,0 @@ - - -#include "LinearMath/btScalar.h" -#include "btSimulationIslandManager.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" - -#include -#include "LinearMath/btQuickprof.h" - -btSimulationIslandManager::btSimulationIslandManager() -{ -} - -btSimulationIslandManager::~btSimulationIslandManager() -{ -} - - -void btSimulationIslandManager::initUnionFind(int n) -{ - m_unionFind.reset(n); -} - - -void btSimulationIslandManager::findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld) -{ - - { - btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr(); - - for (int i=0;igetPairCache()->getNumOverlappingPairs();i++) - { - const btBroadphasePair& collisionPair = pairPtr[i]; - btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; - btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; - - if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && - ((colObj1) && ((colObj1)->mergesSimulationIslands()))) - { - - m_unionFind.unite((colObj0)->getIslandTag(), - (colObj1)->getIslandTag()); - } - } - } -} - - -void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher) -{ - - initUnionFind( int (colWorld->getCollisionObjectArray().size())); - - // put the index into m_controllers into m_tag - { - - int index = 0; - int i; - for (i=0;igetCollisionObjectArray().size(); i++) - { - btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; - collisionObject->setIslandTag(index); - collisionObject->setCompanionId(-1); - collisionObject->setHitFraction(btScalar(1.)); - index++; - - } - } - // do the union find - - findUnions(dispatcher,colWorld); - - - -} - - - - -void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld) -{ - // put the islandId ('find' value) into m_tag - { - - - int index = 0; - int i; - for (i=0;igetCollisionObjectArray().size();i++) - { - btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; - if (collisionObject->mergesSimulationIslands()) - { - collisionObject->setIslandTag( m_unionFind.find(index) ); - collisionObject->setCompanionId(-1); - } else - { - collisionObject->setIslandTag(-1); - collisionObject->setCompanionId(-2); - } - index++; - } - } -} - -inline int getIslandId(const btPersistentManifold* lhs) -{ - int islandId; - const btCollisionObject* rcolObj0 = static_cast(lhs->getBody0()); - const btCollisionObject* rcolObj1 = static_cast(lhs->getBody1()); - islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag(); - return islandId; - -} - - - -/// function object that routes calls to operator< -class btPersistentManifoldSortPredicate -{ - public: - - SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) - { - return getIslandId(lhs) < getIslandId(rhs); - } -}; - - - - - -// -// todo: this is random access, it can be walked 'cache friendly'! -// -void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) -{ - - BEGIN_PROFILE("islandUnionFindAndHeapSort"); - - //we are going to sort the unionfind array, and store the element id in the size - //afterwards, we clean unionfind, to make sure no-one uses it anymore - - getUnionFind().sortIslands(); - int numElem = getUnionFind().getNumElements(); - - int endIslandIndex=1; - int startIslandIndex; - - - //update the sleeping state for bodies, if all are sleeping - for ( startIslandIndex=0;startIslandIndexgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) - { - printf("error in island management\n"); - } - - assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); - if (colObj0->getIslandTag() == islandId) - { - if (colObj0->getActivationState()== ACTIVE_TAG) - { - allSleeping = false; - } - if (colObj0->getActivationState()== DISABLE_DEACTIVATION) - { - allSleeping = false; - } - } - } - - - if (allSleeping) - { - int idx; - for (idx=startIslandIndex;idxgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) - { - printf("error in island management\n"); - } - - assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); - - if (colObj0->getIslandTag() == islandId) - { - colObj0->setActivationState( ISLAND_SLEEPING ); - } - } - } else - { - - int idx; - for (idx=startIslandIndex;idxgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) - { - printf("error in island management\n"); - } - - assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); - - if (colObj0->getIslandTag() == islandId) - { - if ( colObj0->getActivationState() == ISLAND_SLEEPING) - { - colObj0->setActivationState( WANTS_DEACTIVATION); - } - } - } - } - } - - - int i; - int maxNumManifolds = dispatcher->getNumManifolds(); - -#define SPLIT_ISLANDS 1 -#ifdef SPLIT_ISLANDS - - -#endif //SPLIT_ISLANDS - - - for (i=0;igetManifoldByIndexInternal(i); - - btCollisionObject* colObj0 = static_cast(manifold->getBody0()); - btCollisionObject* colObj1 = static_cast(manifold->getBody1()); - - //todo: check sleeping conditions! - if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) || - ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING)) - { - - //kinematic objects don't merge islands, but wake up all connected objects - if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) - { - colObj1->activate(); - } - if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) - { - colObj0->activate(); - } -#ifdef SPLIT_ISLANDS - // //filtering for response - if (dispatcher->needsResponse(colObj0,colObj1)) - m_islandmanifold.push_back(manifold); -#endif //SPLIT_ISLANDS - } - } - -#ifndef SPLIT_ISLANDS - btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); - - callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); -#else - // Sort manifolds, based on islands - // Sort the vector using predicate and std::sort - //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); - - int numManifolds = int (m_islandmanifold.size()); - - //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) - m_islandmanifold.heapSort(btPersistentManifoldSortPredicate()); - - //now process all active islands (sets of manifolds for now) - - int startManifoldIndex = 0; - int endManifoldIndex = 1; - - //int islandId; - - END_PROFILE("islandUnionFindAndHeapSort"); - - - -// printf("Start Islands\n"); - - //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated - for ( startIslandIndex=0;startIslandIndexisActive()) - islandSleeping = true; - } - - - //find the accompanying contact manifold for this islandId - int numIslandManifolds = 0; - btPersistentManifold** startManifold = 0; - - if (startManifoldIndexProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); -// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); - } - - if (numIslandManifolds) - { - startManifoldIndex = endManifoldIndex; - } - - m_islandBodies.resize(0); - } -#endif //SPLIT_ISLANDS - - m_islandmanifold.resize(0); -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h deleted file mode 100644 index 01a059b5fbe..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -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. -*/ - -#ifndef SIMULATION_ISLAND_MANAGER_H -#define SIMULATION_ISLAND_MANAGER_H - -#include "BulletCollision/CollisionDispatch/btUnionFind.h" -#include "btCollisionCreateFunc.h" -#include "LinearMath/btAlignedObjectArray.h" - - -class btCollisionObject; -class btCollisionWorld; -class btDispatcher; -class btPersistentManifold; - - -///SimulationIslandManager creates and handles simulation islands, using btUnionFind -class btSimulationIslandManager -{ - btUnionFind m_unionFind; - - btAlignedObjectArray m_islandmanifold; - btAlignedObjectArray m_islandBodies; - - -public: - btSimulationIslandManager(); - virtual ~btSimulationIslandManager(); - - - void initUnionFind(int n); - - - btUnionFind& getUnionFind() { return m_unionFind;} - - virtual void updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher); - virtual void storeIslandActivationState(btCollisionWorld* world); - - - void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld); - - - - struct IslandCallback - { - virtual ~IslandCallback() {}; - - virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0; - }; - - void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback); - -}; - -#endif //SIMULATION_ISLAND_MANAGER_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp deleted file mode 100644 index 1e4bbce451d..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* -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. -*/ - -#include "btSphereBoxCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionShapes/btBoxShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -//#include - -btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped) -: btCollisionAlgorithm(ci), -m_ownManifold(false), -m_manifoldPtr(mf), -m_isSwapped(isSwapped) -{ - btCollisionObject* sphereObj = m_isSwapped? col1 : col0; - btCollisionObject* boxObj = m_isSwapped? col0 : col1; - - if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObj,boxObj)) - { - m_manifoldPtr = m_dispatcher->getNewManifold(sphereObj,boxObj); - m_ownManifold = true; - } -} - - -btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm() -{ - if (m_ownManifold) - { - if (m_manifoldPtr) - m_dispatcher->releaseManifold(m_manifoldPtr); - } -} - - - -void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)dispatchInfo; - (void)resultOut; - if (!m_manifoldPtr) - return; - - btCollisionObject* sphereObj = m_isSwapped? body1 : body0; - btCollisionObject* boxObj = m_isSwapped? body0 : body1; - - - btSphereShape* sphere0 = (btSphereShape*)sphereObj->getCollisionShape(); - - btVector3 normalOnSurfaceB; - btVector3 pOnBox,pOnSphere; - btVector3 sphereCenter = sphereObj->getWorldTransform().getOrigin(); - btScalar radius = sphere0->getRadius(); - - btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius); - - resultOut->setPersistentManifold(m_manifoldPtr); - - if (dist < SIMD_EPSILON) - { - btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize(); - - /// report a contact. internally this will be kept persistent, and contact reduction is done - - resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist); - - } - - if (m_ownManifold) - { - if (m_manifoldPtr->getNumContacts()) - { - resultOut->refreshContactPoints(); - } - } - -} - -btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)resultOut; - (void)dispatchInfo; - (void)col0; - (void)col1; - - //not yet - return btScalar(1.); -} - - -btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* boxObj, btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius ) -{ - - btScalar margins; - btVector3 bounds[2]; - btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape(); - - bounds[0] = -boxShape->getHalfExtentsWithoutMargin(); - bounds[1] = boxShape->getHalfExtentsWithoutMargin(); - - margins = boxShape->getMargin();//also add sphereShape margin? - - const btTransform& m44T = boxObj->getWorldTransform(); - - btVector3 boundsVec[2]; - btScalar fPenetration; - - boundsVec[0] = bounds[0]; - boundsVec[1] = bounds[1]; - - btVector3 marginsVec( margins, margins, margins ); - - // add margins - bounds[0] += marginsVec; - bounds[1] -= marginsVec; - - ///////////////////////////////////////////////// - - btVector3 tmp, prel, n[6], normal, v3P; - btScalar fSep = btScalar(10000000.0), fSepThis; - - n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) ); - n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) ); - n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) ); - n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) ); - n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) ); - n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) ); - - // convert point in local space - prel = m44T.invXform( sphereCenter); - - bool bFound = false; - - v3P = prel; - - for (int i=0;i<6;i++) - { - int j = i<3? 0:1; - if ( (fSepThis = ((v3P-bounds[j]) .dot(n[i]))) > btScalar(0.0) ) - { - v3P = v3P - n[i]*fSepThis; - bFound = true; - } - } - - // - - if ( bFound ) - { - bounds[0] = boundsVec[0]; - bounds[1] = boundsVec[1]; - - normal = (prel - v3P).normalize(); - pointOnBox = v3P + normal*margins; - v3PointOnSphere = prel - normal*fRadius; - - if ( ((v3PointOnSphere - pointOnBox) .dot (normal)) > btScalar(0.0) ) - { - return btScalar(1.0); - } - - // transform back in world space - tmp = m44T( pointOnBox); - pointOnBox = tmp; - tmp = m44T( v3PointOnSphere); - v3PointOnSphere = tmp; - btScalar fSeps2 = (pointOnBox-v3PointOnSphere).length2(); - - //if this fails, fallback into deeper penetration case, below - if (fSeps2 > SIMD_EPSILON) - { - fSep = - btSqrt(fSeps2); - normal = (pointOnBox-v3PointOnSphere); - normal *= btScalar(1.)/fSep; - } - - return fSep; - } - - ////////////////////////////////////////////////// - // Deep penetration case - - fPenetration = getSpherePenetration( boxObj,pointOnBox, v3PointOnSphere, sphereCenter, fRadius,bounds[0],bounds[1] ); - - bounds[0] = boundsVec[0]; - bounds[1] = boundsVec[1]; - - if ( fPenetration <= btScalar(0.0) ) - return (fPenetration-margins); - else - return btScalar(1.0); -} - -btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* boxObj,btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax) -{ - - btVector3 bounds[2]; - - bounds[0] = aabbMin; - bounds[1] = aabbMax; - - btVector3 p0, tmp, prel, n[6], normal; - btScalar fSep = btScalar(-10000000.0), fSepThis; - - // set p0 and normal to a default value to shup up GCC - p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); - normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); - - n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) ); - n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) ); - n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) ); - n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) ); - n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) ); - n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) ); - - const btTransform& m44T = boxObj->getWorldTransform(); - - // convert point in local space - prel = m44T.invXform( sphereCenter); - - /////////// - - for (int i=0;i<6;i++) - { - int j = i<3 ? 0:1; - if ( (fSepThis = ((prel-bounds[j]) .dot( n[i]))-fRadius) > btScalar(0.0) ) return btScalar(1.0); - if ( fSepThis > fSep ) - { - p0 = bounds[j]; normal = (btVector3&)n[i]; - fSep = fSepThis; - } - } - - pointOnBox = prel - normal*(normal.dot((prel-p0))); - v3PointOnSphere = pointOnBox + normal*fSep; - - // transform back in world space - tmp = m44T( pointOnBox); - pointOnBox = tmp; - tmp = m44T( v3PointOnSphere); v3PointOnSphere = tmp; - normal = (pointOnBox-v3PointOnSphere).normalize(); - - return fSep; - -} - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h deleted file mode 100644 index b839dc4adb1..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -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. -*/ - -#ifndef SPHERE_BOX_COLLISION_ALGORITHM_H -#define SPHERE_BOX_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -class btPersistentManifold; -#include "btCollisionDispatcher.h" - -#include "LinearMath/btVector3.h" - -/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. -/// Other features are frame-coherency (persistent data) and collision response. -class btSphereBoxCollisionAlgorithm : public btCollisionAlgorithm -{ - bool m_ownManifold; - btPersistentManifold* m_manifoldPtr; - bool m_isSwapped; - -public: - - btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); - - virtual ~btSphereBoxCollisionAlgorithm(); - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius ); - - btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax); - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm)); - if (!m_swapped) - { - return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); - } else - { - return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); - } - } - }; - -}; - -#endif //SPHERE_BOX_COLLISION_ALGORITHM_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp deleted file mode 100644 index e7f42647e61..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* -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. -*/ - -#include "btSphereSphereCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" - -btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1) -: btCollisionAlgorithm(ci), -m_ownManifold(false), -m_manifoldPtr(mf) -{ - if (!m_manifoldPtr) - { - m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1); - m_ownManifold = true; - } -} - -btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm() -{ - if (m_ownManifold) - { - if (m_manifoldPtr) - m_dispatcher->releaseManifold(m_manifoldPtr); - } -} - -void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)dispatchInfo; - - if (!m_manifoldPtr) - return; - - resultOut->setPersistentManifold(m_manifoldPtr); - - btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape(); - btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape(); - - btVector3 diff = col0->getWorldTransform().getOrigin()- col1->getWorldTransform().getOrigin(); - btScalar len = diff.length(); - btScalar radius0 = sphere0->getRadius(); - btScalar radius1 = sphere1->getRadius(); - - m_manifoldPtr->clearManifold(); - - ///iff distance positive, don't generate a new contact - if ( len > (radius0+radius1)) - { - return; - } - ///distance (negative means penetration) - btScalar dist = len - (radius0+radius1); - - btVector3 normalOnSurfaceB = diff / len; - ///point on A (worldspace) - btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; - ///point on B (worldspace) - btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; - - /// report a contact. internally this will be kept persistent, and contact reduction is done - - - resultOut->addContactPoint(normalOnSurfaceB,pos1,dist); - - //no resultOut->refreshContactPoints(); needed, because of clearManifold (all points are new) - -} - -btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)col0; - (void)col1; - (void)dispatchInfo; - (void)resultOut; - - //not yet - return btScalar(1.); -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h deleted file mode 100644 index bcaa0d303a9..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -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. -*/ - -#ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H -#define SPHERE_SPHERE_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -#include "btCollisionDispatcher.h" - -class btPersistentManifold; - -/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. -/// Other features are frame-coherency (persistent data) and collision response. -/// Also provides the most basic sample for custom/user btCollisionAlgorithm -class btSphereSphereCollisionAlgorithm : public btCollisionAlgorithm -{ - bool m_ownManifold; - btPersistentManifold* m_manifoldPtr; - -public: - btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); - - btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) - : btCollisionAlgorithm(ci) {} - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - - virtual ~btSphereSphereCollisionAlgorithm(); - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm)); - return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1); - } - }; - -}; - -#endif //SPHERE_SPHERE_COLLISION_ALGORITHM_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp deleted file mode 100644 index 5d50bfed7a1..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* -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. -*/ - - -#include "btSphereTriangleCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "SphereTriangleDetector.h" - - -btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,bool swapped) -: btCollisionAlgorithm(ci), -m_ownManifold(false), -m_manifoldPtr(mf), -m_swapped(swapped) -{ - if (!m_manifoldPtr) - { - m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1); - m_ownManifold = true; - } -} - -btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm() -{ - if (m_ownManifold) - { - if (m_manifoldPtr) - m_dispatcher->releaseManifold(m_manifoldPtr); - } -} - -void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - if (!m_manifoldPtr) - return; - - btCollisionObject* sphereObj = m_swapped? col1 : col0; - btCollisionObject* triObj = m_swapped? col0 : col1; - - btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape(); - btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape(); - - /// report a contact. internally this will be kept persistent, and contact reduction is done - resultOut->setPersistentManifold(m_manifoldPtr); - SphereTriangleDetector detector(sphere,triangle); - - btDiscreteCollisionDetectorInterface::ClosestPointInput input; - input.m_maximumDistanceSquared = btScalar(1e30);//todo: tighter bounds - input.m_transformA = col0->getWorldTransform(); - input.m_transformB = col1->getWorldTransform(); - - detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); - - if (m_ownManifold) - resultOut->refreshContactPoints(); - -} - -btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)resultOut; - (void)dispatchInfo; - (void)col0; - (void)col1; - - //not yet - return btScalar(1.); -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h deleted file mode 100644 index 4aefc0c43a5..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -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. -*/ - -#ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H -#define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -class btPersistentManifold; -#include "btCollisionDispatcher.h" - -/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. -/// Other features are frame-coherency (persistent data) and collision response. -/// Also provides the most basic sample for custom/user btCollisionAlgorithm -class btSphereTriangleCollisionAlgorithm : public btCollisionAlgorithm -{ - bool m_ownManifold; - btPersistentManifold* m_manifoldPtr; - bool m_swapped; - -public: - btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool swapped); - - btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) - : btCollisionAlgorithm(ci) {} - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - - virtual ~btSphereTriangleCollisionAlgorithm(); - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm)); - - return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); - } - }; - -}; - -#endif //SPHERE_TRIANGLE_COLLISION_ALGORITHM_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp deleted file mode 100644 index c81be8aa75c..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -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. -*/ - -#include "btUnionFind.h" -#include - - - - -btUnionFind::~btUnionFind() -{ - Free(); - -} - -btUnionFind::btUnionFind() -{ - -} - -void btUnionFind::allocate(int N) -{ - m_elements.resize(N); -} -void btUnionFind::Free() -{ - m_elements.clear(); -} - - -void btUnionFind::reset(int N) -{ - allocate(N); - - for (int i = 0; i < N; i++) - { - m_elements[i].m_id = i; m_elements[i].m_sz = 1; - } -} - - -class btUnionFindElementSortPredicate -{ - public: - - bool operator() ( const btElement& lhs, const btElement& rhs ) - { - return lhs.m_id < rhs.m_id; - } -}; - -///this is a special operation, destroying the content of btUnionFind. -///it sorts the elements, based on island id, in order to make it easy to iterate over islands -void btUnionFind::sortIslands() -{ - - //first store the original body index, and islandId - int numElements = m_elements.size(); - - for (int i=0;i m_elements; - - public: - - btUnionFind(); - ~btUnionFind(); - - - //this is a special operation, destroying the content of btUnionFind. - //it sorts the elements, based on island id, in order to make it easy to iterate over islands - void sortIslands(); - - void reset(int N); - - SIMD_FORCE_INLINE int getNumElements() const - { - return int(m_elements.size()); - } - SIMD_FORCE_INLINE bool isRoot(int x) const - { - return (x == m_elements[x].m_id); - } - - btElement& getElement(int index) - { - return m_elements[index]; - } - const btElement& getElement(int index) const - { - return m_elements[index]; - } - - void allocate(int N); - void Free(); - - - - - int find(int p, int q) - { - return (find(p) == find(q)); - } - - void unite(int p, int q) - { - int i = find(p), j = find(q); - if (i == j) - return; - -#ifndef USE_PATH_COMPRESSION - //weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) ) - if (m_elements[i].m_sz < m_elements[j].m_sz) - { - m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; - } - else - { - m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz; - } -#else - m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; -#endif //USE_PATH_COMPRESSION - } - - int find(int x) - { - //assert(x < m_N); - //assert(x >= 0); - - while (x != m_elements[x].m_id) - { - //not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically - - #ifdef USE_PATH_COMPRESSION - // - m_elements[x].m_id = m_elements[m_elements[x].m_id].m_id; - #endif // - x = m_elements[x].m_id; - //assert(x < m_N); - //assert(x >= 0); - - } - return x; - } - - - }; - - -#endif //UNION_FIND_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp deleted file mode 100644 index adac455bbcb..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* -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. -*/ - -#include "btBoxShape.h" - - -//{ - - -void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const -{ - const btVector3& halfExtents = getHalfExtentsWithoutMargin(); - - btMatrix3x3 abs_b = t.getBasis().absolute(); - btPoint3 center = t.getOrigin(); - btVector3 extent = btVector3(abs_b[0].dot(halfExtents), - abs_b[1].dot(halfExtents), - abs_b[2].dot(halfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); - - aabbMin = center - extent; - aabbMax = center + extent; - - -} - - -void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const -{ - //btScalar margin = btScalar(0.); - btVector3 halfExtents = getHalfExtentsWithMargin(); - - btScalar lx=btScalar(2.)*(halfExtents.x()); - btScalar ly=btScalar(2.)*(halfExtents.y()); - btScalar lz=btScalar(2.)*(halfExtents.z()); - - inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), - mass/(btScalar(12.0)) * (lx*lx + lz*lz), - mass/(btScalar(12.0)) * (lx*lx + ly*ly)); - -} - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h deleted file mode 100644 index 98f1bd34b09..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h +++ /dev/null @@ -1,323 +0,0 @@ -/* -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. -*/ - -#ifndef OBB_BOX_MINKOWSKI_H -#define OBB_BOX_MINKOWSKI_H - -#include "btPolyhedralConvexShape.h" -#include "btCollisionMargin.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "LinearMath/btPoint3.h" -#include "LinearMath/btMinMax.h" - -///btBoxShape implements both a feature based (vertex/edge/plane) and implicit (getSupportingVertex) Box -class btBoxShape: public btPolyhedralConvexShape -{ - - //btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead - - -public: - - btVector3 getHalfExtentsWithMargin() const - { - btVector3 halfExtents = getHalfExtentsWithoutMargin(); - btVector3 margin(getMargin(),getMargin(),getMargin()); - halfExtents += margin; - return halfExtents; - } - - const btVector3& getHalfExtentsWithoutMargin() const - { - return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included - } - - - virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;} - - virtual btVector3 localGetSupportingVertex(const btVector3& vec) const - { - btVector3 halfExtents = getHalfExtentsWithoutMargin(); - btVector3 margin(getMargin(),getMargin(),getMargin()); - halfExtents += margin; - - return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), - btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), - btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); - } - - SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const - { - const btVector3& halfExtents = getHalfExtentsWithoutMargin(); - - return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), - btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), - btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); - } - - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const - { - const btVector3& halfExtents = getHalfExtentsWithoutMargin(); - - for (int i=0;i>1)) - halfExtents.y() * ((i&2)>>1), - halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2)); - } - - - virtual void getPlaneEquation(btVector4& plane,int i) const - { - btVector3 halfExtents = getHalfExtentsWithoutMargin(); - - switch (i) - { - case 0: - plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); - plane[3] = -halfExtents.x(); - break; - case 1: - plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); - plane[3] = -halfExtents.x(); - break; - case 2: - plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); - plane[3] = -halfExtents.y(); - break; - case 3: - plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); - plane[3] = -halfExtents.y(); - break; - case 4: - plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); - plane[3] = -halfExtents.z(); - break; - case 5: - plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); - plane[3] = -halfExtents.z(); - break; - default: - assert(0); - } - } - - - virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const - //virtual void getEdge(int i,Edge& edge) const - { - int edgeVert0 = 0; - int edgeVert1 = 0; - - switch (i) - { - case 0: - edgeVert0 = 0; - edgeVert1 = 1; - break; - case 1: - edgeVert0 = 0; - edgeVert1 = 2; - break; - case 2: - edgeVert0 = 1; - edgeVert1 = 3; - - break; - case 3: - edgeVert0 = 2; - edgeVert1 = 3; - break; - case 4: - edgeVert0 = 0; - edgeVert1 = 4; - break; - case 5: - edgeVert0 = 1; - edgeVert1 = 5; - - break; - case 6: - edgeVert0 = 2; - edgeVert1 = 6; - break; - case 7: - edgeVert0 = 3; - edgeVert1 = 7; - break; - case 8: - edgeVert0 = 4; - edgeVert1 = 5; - break; - case 9: - edgeVert0 = 4; - edgeVert1 = 6; - break; - case 10: - edgeVert0 = 5; - edgeVert1 = 7; - break; - case 11: - edgeVert0 = 6; - edgeVert1 = 7; - break; - default: - btAssert(0); - - } - - getVertex(edgeVert0,pa ); - getVertex(edgeVert1,pb ); - } - - - - - - virtual bool isInside(const btPoint3& pt,btScalar tolerance) const - { - btVector3 halfExtents = getHalfExtentsWithoutMargin(); - - //btScalar minDist = 2*tolerance; - - bool result = (pt.x() <= (halfExtents.x()+tolerance)) && - (pt.x() >= (-halfExtents.x()-tolerance)) && - (pt.y() <= (halfExtents.y()+tolerance)) && - (pt.y() >= (-halfExtents.y()-tolerance)) && - (pt.z() <= (halfExtents.z()+tolerance)) && - (pt.z() >= (-halfExtents.z()-tolerance)); - - return result; - } - - - //debugging - virtual const char* getName()const - { - return "Box"; - } - - virtual int getNumPreferredPenetrationDirections() const - { - return 6; - } - - virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const - { - switch (index) - { - case 0: - penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); - break; - case 1: - penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); - break; - case 2: - penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); - break; - case 3: - penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); - break; - case 4: - penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); - break; - case 5: - penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); - break; - default: - assert(0); - } - } - -}; - -#endif //OBB_BOX_MINKOWSKI_H - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp deleted file mode 100644 index eea263fe5b4..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* -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. -*/ - -//#define DISABLE_BVH - -#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" - - -///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. -///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. -btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh) -:btTriangleMeshShape(meshInterface), -m_bvh(0), -m_useQuantizedAabbCompression(useQuantizedAabbCompression), -m_ownsBvh(false) -{ - //construct bvh from meshInterface -#ifndef DISABLE_BVH - - btVector3 bvhAabbMin,bvhAabbMax; - meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax); - - if (buildBvh) - { - void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); - m_bvh = new (mem) btOptimizedBvh(); - m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); - m_ownsBvh = true; - } - -#endif //DISABLE_BVH - -} - -btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh) -:btTriangleMeshShape(meshInterface), -m_bvh(0), -m_useQuantizedAabbCompression(useQuantizedAabbCompression), -m_ownsBvh(false) -{ - //construct bvh from meshInterface -#ifndef DISABLE_BVH - - if (buildBvh) - { - void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); - m_bvh = new (mem) btOptimizedBvh(); - - m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); - m_ownsBvh = true; - } - -#endif //DISABLE_BVH - -} - -void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax) -{ - m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax ); - - m_localAabbMin.setMin(aabbMin); - m_localAabbMax.setMax(aabbMax); -} - - -void btBvhTriangleMeshShape::refitTree() -{ - m_bvh->refit( m_meshInterface ); - - recalcLocalAabb(); -} - -btBvhTriangleMeshShape::~btBvhTriangleMeshShape() -{ - if (m_ownsBvh) - { - m_bvh->~btOptimizedBvh(); - btAlignedFree(m_bvh); - } -} - -//perform bvh tree traversal and report overlapping triangles to 'callback' -void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const -{ - -#ifdef DISABLE_BVH - //brute force traverse all triangles - btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax); -#else - - //first get all the nodes - - - struct MyNodeOverlapCallback : public btNodeOverlapCallback - { - btStridingMeshInterface* m_meshInterface; - btTriangleCallback* m_callback; - btVector3 m_triangle[3]; - - - MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) - :m_meshInterface(meshInterface), - m_callback(callback) - { - } - - virtual void processNode(int nodeSubPart, int nodeTriangleIndex) - { - const unsigned char *vertexbase; - int numverts; - PHY_ScalarType type; - int stride; - const unsigned char *indexbase; - int indexstride; - int numfaces; - PHY_ScalarType indicestype; - - - m_meshInterface->getLockedReadOnlyVertexIndexBase( - &vertexbase, - numverts, - type, - stride, - &indexbase, - indexstride, - numfaces, - indicestype, - nodeSubPart); - - int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); - - const btVector3& meshScaling = m_meshInterface->getScaling(); - for (int j=2;j>=0;j--) - { - - int graphicsindex = gfxbase[j]; - - -#ifdef DEBUG_TRIANGLE_MESH - printf("%d ,",graphicsindex); -#endif //DEBUG_TRIANGLE_MESH - btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); - - m_triangle[j] = btVector3( - graphicsbase[0]*meshScaling.getX(), - graphicsbase[1]*meshScaling.getY(), - graphicsbase[2]*meshScaling.getZ()); -#ifdef DEBUG_TRIANGLE_MESH - printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z()); -#endif //DEBUG_TRIANGLE_MESH - } - - m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); - m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); - } - - }; - - MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); - - m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); - - -#endif//DISABLE_BVH - - -} - - -void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) -{ - if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) - { - btTriangleMeshShape::setLocalScaling(scaling); - if (m_ownsBvh) - { - m_bvh->~btOptimizedBvh(); - btAlignedFree(m_bvh); - } - ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work - void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); - m_bvh = new(mem) btOptimizedBvh(); - //rebuild the bvh... - m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); - - } -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h deleted file mode 100644 index 95c73b2441f..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -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. -*/ - -#ifndef BVH_TRIANGLE_MESH_SHAPE_H -#define BVH_TRIANGLE_MESH_SHAPE_H - -#include "btTriangleMeshShape.h" -#include "btOptimizedBvh.h" -#include "LinearMath/btAlignedAllocator.h" - -///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. -///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. -ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape -{ - - btOptimizedBvh* m_bvh; - bool m_useQuantizedAabbCompression; - bool m_ownsBvh; - bool m_pad[11];////need padding due to alignment - -public: - - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btBvhTriangleMeshShape() :btTriangleMeshShape(0),m_bvh(0),m_ownsBvh(false) {}; - btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true); - - ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb - btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true); - - virtual ~btBvhTriangleMeshShape(); - - - /* - virtual int getShapeType() const - { - return TRIANGLE_MESH_SHAPE_PROXYTYPE; - } - */ - - - - virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - void refitTree(); - - ///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks - void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax); - - //debugging - virtual const char* getName()const {return "BVHTRIANGLEMESH";} - - - virtual void setLocalScaling(const btVector3& scaling); - - btOptimizedBvh* getOptimizedBvh() - { - return m_bvh; - } - - - void setOptimizedBvh(btOptimizedBvh* bvh) - { - btAssert(!m_bvh); - btAssert(!m_ownsBvh); - - m_bvh = bvh; - m_ownsBvh = false; - } - - bool usesQuantizedAabbCompression() const - { - return m_useQuantizedAabbCompression; - } -} -; - -#endif //BVH_TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp deleted file mode 100644 index b4f21f38b3d..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* -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. -*/ - - -#include "btCapsuleShape.h" - -#include "BulletCollision/CollisionShapes/btCollisionMargin.h" -#include "LinearMath/btQuaternion.h" - -btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) -{ - m_implicitShapeDimensions.setValue(radius,0.5f*height,radius); -} - - - btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const -{ - - btVector3 supVec(0,0,0); - - btScalar maxDot(btScalar(-1e30)); - - btVector3 vec = vec0; - btScalar lenSqr = vec.length2(); - if (lenSqr < btScalar(0.0001)) - { - vec.setValue(1,0,0); - } else - { - btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); - vec *= rlen; - } - - btVector3 vtx; - btScalar newDot; - - btScalar radius = getRadius(); - - - { - btVector3 pos(0,getHalfHeight(),0); - vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); - newDot = vec.dot(vtx); - if (newDot > maxDot) - { - maxDot = newDot; - supVec = vtx; - } - } - { - btVector3 pos(0,-getHalfHeight(),0); - vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); - newDot = vec.dot(vtx); - if (newDot > maxDot) - { - maxDot = newDot; - supVec = vtx; - } - } - - return supVec; - -} - - void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const -{ - - - btScalar radius = getRadius(); - - for (int j=0;j maxDot) - { - maxDot = newDot; - supportVerticesOut[j] = vtx; - } - } - { - btVector3 pos(0,-getHalfHeight(),0); - vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); - newDot = vec.dot(vtx); - if (newDot > maxDot) - { - maxDot = newDot; - supportVerticesOut[j] = vtx; - } - } - - } -} - - -void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const -{ - //as an approximation, take the inertia of the box that bounds the spheres - - btTransform ident; - ident.setIdentity(); - - - btScalar radius = getRadius(); - - btVector3 halfExtents(radius,radius+getHalfHeight(),radius); - - btScalar margin = CONVEX_DISTANCE_MARGIN; - - btScalar lx=btScalar(2.)*(halfExtents[0]+margin); - btScalar ly=btScalar(2.)*(halfExtents[1]+margin); - btScalar lz=btScalar(2.)*(halfExtents[2]+margin); - const btScalar x2 = lx*lx; - const btScalar y2 = ly*ly; - const btScalar z2 = lz*lz; - const btScalar scaledmass = mass * btScalar(.08333333); - - inertia[0] = scaledmass * (y2+z2); - inertia[1] = scaledmass * (x2+z2); - inertia[2] = scaledmass * (x2+y2); - -} - - - - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h deleted file mode 100644 index 0b566450fef..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -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. -*/ - -#ifndef BT_CAPSULE_SHAPE_H -#define BT_CAPSULE_SHAPE_H - -#include "btConvexInternalShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types - - -///btCapsuleShape represents a capsule around the Y axis -///A more general solution that can represent capsules is the btMultiSphereShape -class btCapsuleShape : public btConvexInternalShape -{ - -public: - btCapsuleShape(btScalar radius,btScalar height); - - ///CollisionShape Interface - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - - /// btConvexShape Interface - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; - - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - - virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; } - - virtual const char* getName()const - { - return "CapsuleShape"; - } - - btScalar getRadius() const - { - return m_implicitShapeDimensions.getX(); - } - - btScalar getHalfHeight() const - { - return m_implicitShapeDimensions.getY(); - } - -}; - - - -#endif //BT_CAPSULE_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h deleted file mode 100644 index 4730264d3df..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -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. -*/ - -#ifndef COLLISION_MARGIN_H -#define COLLISION_MARGIN_H - -//used by Gjk and some other algorithms - -#define CONVEX_DISTANCE_MARGIN btScalar(0.04)// btScalar(0.1)//;//btScalar(0.01) - - - -#endif //COLLISION_MARGIN_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp deleted file mode 100644 index 81d82428f4c..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -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. -*/ - -#include "BulletCollision/CollisionShapes/btCollisionShape.h" - - -/* - Make sure this dummy function never changes so that it - can be used by probes that are checking whether the - library is actually installed. -*/ -extern "C" void btBulletCollisionProbe () {} - - - -void btCollisionShape::getBoundingSphere(btVector3& center,btScalar& radius) const -{ - btTransform tr; - tr.setIdentity(); - btVector3 aabbMin,aabbMax; - - getAabb(tr,aabbMin,aabbMax); - - radius = (aabbMax-aabbMin).length()*btScalar(0.5); - center = (aabbMin+aabbMax)*btScalar(0.5); -} - -btScalar btCollisionShape::getAngularMotionDisc() const -{ - btVector3 center; - btScalar disc; - getBoundingSphere(center,disc); - disc += (center).length(); - return disc; -} - -void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) -{ - //start with static aabb - getAabb(curTrans,temporalAabbMin,temporalAabbMax); - - btScalar temporalAabbMaxx = temporalAabbMax.getX(); - btScalar temporalAabbMaxy = temporalAabbMax.getY(); - btScalar temporalAabbMaxz = temporalAabbMax.getZ(); - btScalar temporalAabbMinx = temporalAabbMin.getX(); - btScalar temporalAabbMiny = temporalAabbMin.getY(); - btScalar temporalAabbMinz = temporalAabbMin.getZ(); - - // add linear motion - btVector3 linMotion = linvel*timeStep; - //todo: simd would have a vector max/min operation, instead of per-element access - if (linMotion.x() > btScalar(0.)) - temporalAabbMaxx += linMotion.x(); - else - temporalAabbMinx += linMotion.x(); - if (linMotion.y() > btScalar(0.)) - temporalAabbMaxy += linMotion.y(); - else - temporalAabbMiny += linMotion.y(); - if (linMotion.z() > btScalar(0.)) - temporalAabbMaxz += linMotion.z(); - else - temporalAabbMinz += linMotion.z(); - - //add conservative angular motion - btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep; - btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion); - temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz); - temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz); - - temporalAabbMin -= angularMotion3d; - temporalAabbMax += angularMotion3d; -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h deleted file mode 100644 index 53fb12e33a1..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -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. -*/ - -#ifndef COLLISION_SHAPE_H -#define COLLISION_SHAPE_H - -#include "LinearMath/btTransform.h" -#include "LinearMath/btVector3.h" -#include "LinearMath/btMatrix3x3.h" -#include "LinearMath/btPoint3.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types - -///btCollisionShape provides interface for collision shapes that can be shared among btCollisionObjects. -class btCollisionShape -{ -public: - - btCollisionShape() - { - } - virtual ~btCollisionShape() - { - } - - ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; - - virtual void getBoundingSphere(btVector3& center,btScalar& radius) const; - - ///getAngularMotionDisc returns the maximus radius needed for Conservative Advancement to handle time-of-impact with rotations. - virtual btScalar getAngularMotionDisc() const; - - - ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep) - ///result is conservative - void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax); - -#ifndef __SPU__ - - SIMD_FORCE_INLINE bool isPolyhedral() const - { - return btBroadphaseProxy::isPolyhedral(getShapeType()); - } - - SIMD_FORCE_INLINE bool isConvex() const - { - return btBroadphaseProxy::isConvex(getShapeType()); - } - SIMD_FORCE_INLINE bool isConcave() const - { - return btBroadphaseProxy::isConcave(getShapeType()); - } - SIMD_FORCE_INLINE bool isCompound() const - { - return btBroadphaseProxy::isCompound(getShapeType()); - } - - ///isInfinite is used to catch simulation error (aabb check) - SIMD_FORCE_INLINE bool isInfinite() const - { - return btBroadphaseProxy::isInfinite(getShapeType()); - } - - virtual int getShapeType() const=0; - virtual void setLocalScaling(const btVector3& scaling) =0; - virtual const btVector3& getLocalScaling() const =0; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0; - - -//debugging support - virtual const char* getName()const =0 ; -#endif //__SPU__ - - - - virtual void setMargin(btScalar margin) = 0; - virtual btScalar getMargin() const = 0; - -}; - -#endif //COLLISION_SHAPE_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp deleted file mode 100644 index 114a1f4c1fc..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* -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. -*/ - -#include "btCompoundShape.h" - - -#include "btCollisionShape.h" - - -btCompoundShape::btCompoundShape() -:m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)), -m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)), -m_aabbTree(0), -m_collisionMargin(btScalar(0.)), -m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)) -{ -} - - -btCompoundShape::~btCompoundShape() -{ -} - -void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) -{ - //m_childTransforms.push_back(localTransform); - //m_childShapes.push_back(shape); - btCompoundShapeChild child; - child.m_transform = localTransform; - child.m_childShape = shape; - child.m_childShapeType = shape->getShapeType(); - child.m_childMargin = shape->getMargin(); - - m_children.push_back(child); - - //extend the local aabbMin/aabbMax - btVector3 localAabbMin,localAabbMax; - shape->getAabb(localTransform,localAabbMin,localAabbMax); - for (int i=0;i<3;i++) - { - if (m_localAabbMin[i] > localAabbMin[i]) - { - m_localAabbMin[i] = localAabbMin[i]; - } - if (m_localAabbMax[i] < localAabbMax[i]) - { - m_localAabbMax[i] = localAabbMax[i]; - } - - } -} - - - - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version -void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const -{ - btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); - btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); - - btMatrix3x3 abs_b = trans.getBasis().absolute(); - - btPoint3 center = trans(localCenter); - - btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); - - aabbMin = center - extent; - aabbMax = center + extent; -} - -void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const -{ - //approximation: take the inertia from the aabb for now - btTransform ident; - ident.setIdentity(); - btVector3 aabbMin,aabbMax; - getAabb(ident,aabbMin,aabbMax); - - btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); - - btScalar lx=btScalar(2.)*(halfExtents.x()); - btScalar ly=btScalar(2.)*(halfExtents.y()); - btScalar lz=btScalar(2.)*(halfExtents.z()); - - inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz); - inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz); - inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly); - -} - - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h deleted file mode 100644 index d23bd65b5e8..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -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. -*/ - -#ifndef COMPOUND_SHAPE_H -#define COMPOUND_SHAPE_H - -#include "btCollisionShape.h" - -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransform.h" -#include "LinearMath/btMatrix3x3.h" -#include "btCollisionMargin.h" -#include "LinearMath/btAlignedObjectArray.h" - -class btOptimizedBvh; - -ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btTransform m_transform; - btCollisionShape* m_childShape; - int m_childShapeType; - btScalar m_childMargin; -}; - -/// btCompoundShape allows to store multiple other btCollisionShapes -/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape. -ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape -{ - //btAlignedObjectArray m_childTransforms; - //btAlignedObjectArray m_childShapes; - btAlignedObjectArray m_children; - btVector3 m_localAabbMin; - btVector3 m_localAabbMax; - - btOptimizedBvh* m_aabbTree; - -public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btCompoundShape(); - - virtual ~btCompoundShape(); - - void addChildShape(const btTransform& localTransform,btCollisionShape* shape); - - int getNumChildShapes() const - { - return int (m_children.size()); - } - - btCollisionShape* getChildShape(int index) - { - return m_children[index].m_childShape; - } - const btCollisionShape* getChildShape(int index) const - { - return m_children[index].m_childShape; - } - - btTransform getChildTransform(int index) - { - return m_children[index].m_transform; - } - const btTransform getChildTransform(int index) const - { - return m_children[index].m_transform; - } - - - btCompoundShapeChild* getChildList() - { - return &m_children[0]; - } - - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - - virtual void setLocalScaling(const btVector3& scaling) - { - m_localScaling = scaling; - } - virtual const btVector3& getLocalScaling() const - { - return m_localScaling; - } - - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - - virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;} - - virtual void setMargin(btScalar margin) - { - m_collisionMargin = margin; - } - virtual btScalar getMargin() const - { - return m_collisionMargin; - } - virtual const char* getName()const - { - return "Compound"; - } - - //this is optional, but should make collision queries faster, by culling non-overlapping nodes - void createAabbTreeFromChildren(); - - const btOptimizedBvh* getAabbTree() const - { - return m_aabbTree; - } - -private: - btScalar m_collisionMargin; -protected: - btVector3 m_localScaling; - -}; - - - -#endif //COMPOUND_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.cpp deleted file mode 100644 index 5103500a012..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.cpp +++ /dev/null @@ -1,28 +0,0 @@ - -/* -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. -*/ - - -#include "btConcaveShape.h" - -btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.)) -{ - -} - -btConcaveShape::~btConcaveShape() -{ - -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h deleted file mode 100644 index 4db4e6513dd..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -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. -*/ - -#ifndef CONCAVE_SHAPE_H -#define CONCAVE_SHAPE_H - -#include "btCollisionShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -#include "btTriangleCallback.h" - - -///Concave shape proves an interface concave shapes that can produce triangles that overlapping a given AABB. -///Static triangle mesh, infinite plane, height field/landscapes are example that implement this interface. -class btConcaveShape : public btCollisionShape -{ -protected: - btScalar m_collisionMargin; - -public: - btConcaveShape(); - - virtual ~btConcaveShape(); - - virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const = 0; - - virtual btScalar getMargin() const { - return m_collisionMargin; - } - virtual void setMargin(btScalar collisionMargin) - { - m_collisionMargin = collisionMargin; - } - - - -}; - -#endif //CONCAVE_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp deleted file mode 100644 index 207b3024bc3..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* -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. -*/ - -#include "btConeShape.h" -#include "LinearMath/btPoint3.h" - - - -btConeShape::btConeShape (btScalar radius,btScalar height): -m_radius (radius), -m_height(height) -{ - setConeUpIndex(1); - btVector3 halfExtents; - m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height)); -} - -btConeShapeZ::btConeShapeZ (btScalar radius,btScalar height): -btConeShape(radius,height) -{ - setConeUpIndex(2); -} - -btConeShapeX::btConeShapeX (btScalar radius,btScalar height): -btConeShape(radius,height) -{ - setConeUpIndex(0); -} - -///choose upAxis index -void btConeShape::setConeUpIndex(int upIndex) -{ - switch (upIndex) - { - case 0: - m_coneIndices[0] = 1; - m_coneIndices[1] = 0; - m_coneIndices[2] = 2; - break; - case 1: - m_coneIndices[0] = 0; - m_coneIndices[1] = 1; - m_coneIndices[2] = 2; - break; - case 2: - m_coneIndices[0] = 0; - m_coneIndices[1] = 2; - m_coneIndices[2] = 1; - break; - default: - assert(0); - }; -} - -btVector3 btConeShape::coneLocalSupport(const btVector3& v) const -{ - - btScalar halfHeight = m_height * btScalar(0.5); - - if (v[m_coneIndices[1]] > v.length() * m_sinAngle) - { - btVector3 tmp; - - tmp[m_coneIndices[0]] = btScalar(0.); - tmp[m_coneIndices[1]] = halfHeight; - tmp[m_coneIndices[2]] = btScalar(0.); - return tmp; - } - else { - btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]); - if (s > SIMD_EPSILON) { - btScalar d = m_radius / s; - btVector3 tmp; - tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d; - tmp[m_coneIndices[1]] = -halfHeight; - tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d; - return tmp; - } - else { - btVector3 tmp; - tmp[m_coneIndices[0]] = btScalar(0.); - tmp[m_coneIndices[1]] = -halfHeight; - tmp[m_coneIndices[2]] = btScalar(0.); - return tmp; - } - } - -} - -btVector3 btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const -{ - return coneLocalSupport(vec); -} - -void btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const -{ - for (int i=0;i maxDot) - { - maxDot = newDot; - supVec = vtx; - } - } - return supVec; -} - -void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const -{ - btScalar newDot; - //use 'w' component of supportVerticesOut? - { - for (int i=0;i supportVerticesOut[j][3]) - { - //WARNING: don't swap next lines, the w component would get overwritten! - supportVerticesOut[j] = vtx; - supportVerticesOut[j][3] = newDot; - } - } - } - - - -} - - - -btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const -{ - btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); - - if ( getMargin()!=btScalar(0.) ) - { - btVector3 vecnorm = vec; - if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) - { - vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); - } - vecnorm.normalize(); - supVertex+= getMargin() * vecnorm; - } - return supVertex; -} - - - - - - - - - -//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection -//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo -int btConvexHullShape::getNumVertices() const -{ - return m_points.size(); -} - -int btConvexHullShape::getNumEdges() const -{ - return m_points.size(); -} - -void btConvexHullShape::getEdge(int i,btPoint3& pa,btPoint3& pb) const -{ - - int index0 = i%m_points.size(); - int index1 = (i+1)%m_points.size(); - pa = m_points[index0]*m_localScaling; - pb = m_points[index1]*m_localScaling; -} - -void btConvexHullShape::getVertex(int i,btPoint3& vtx) const -{ - vtx = m_points[i]*m_localScaling; -} - -int btConvexHullShape::getNumPlanes() const -{ - return 0; -} - -void btConvexHullShape::getPlane(btVector3& ,btPoint3& ,int ) const -{ - - btAssert(0); -} - -//not yet -bool btConvexHullShape::isInside(const btPoint3& ,btScalar ) const -{ - assert(0); - return false; -} - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h deleted file mode 100644 index 0928d68b8fc..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -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. -*/ - -#ifndef CONVEX_HULL_SHAPE_H -#define CONVEX_HULL_SHAPE_H - -#include "btPolyhedralConvexShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -#include "LinearMath/btAlignedObjectArray.h" - -///ConvexHullShape implements an implicit (getSupportingVertex) Convex Hull of a Point Cloud (vertices) -///No connectivity is needed. localGetSupportingVertex iterates linearly though all vertices. -///on modern hardware, due to cache coherency this isn't that bad. Complex algorithms tend to trash the cash. -///(memory is much slower then the cpu) -ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexShape -{ - btAlignedObjectArray m_points; - -public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - - ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory. - ///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint. - ///btConvexHullShape make an internal copy of the points. - btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btPoint3)); - - void addPoint(const btPoint3& point); - - btPoint3* getPoints() - { - return &m_points[0]; - } - - int getNumPoints() - { - return m_points.size(); - } - - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - - - virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; } - - //debugging - virtual const char* getName()const {return "Convex";} - - - virtual int getNumVertices() const; - virtual int getNumEdges() const; - virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const; - virtual void getVertex(int i,btPoint3& vtx) const; - virtual int getNumPlanes() const; - virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const; - virtual bool isInside(const btPoint3& pt,btScalar tolerance) const; - - - -}; - - -#endif //CONVEX_HULL_SHAPE_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp deleted file mode 100644 index f828d28e18c..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* -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. -*/ - - -#include "btConvexInternalShape.h" - - -btConvexInternalShape::btConvexInternalShape() -: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), -m_collisionMargin(CONVEX_DISTANCE_MARGIN) -{ -} - - -void btConvexInternalShape::setLocalScaling(const btVector3& scaling) -{ - m_localScaling = scaling; -} - - - -void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const -{ - - btScalar margin = getMargin(); - for (int i=0;i<3;i++) - { - btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); - vec[i] = btScalar(1.); - - btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); - - btVector3 tmp = trans(sv); - maxAabb[i] = tmp[i]+margin; - vec[i] = btScalar(-1.); - tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); - minAabb[i] = tmp[i]-margin; - } -}; - - -btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const -{ -#ifndef __SPU__ - - btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); - - if ( getMargin()!=btScalar(0.) ) - { - btVector3 vecnorm = vec; - if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) - { - vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); - } - vecnorm.normalize(); - supVertex+= getMargin() * vecnorm; - } - return supVertex; - -#else - return btVector3(0,0,0); -#endif //__SPU__ - - } - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h deleted file mode 100644 index a03af873bd3..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h +++ /dev/null @@ -1,99 +0,0 @@ - -#ifndef BT_CONVEX_INTERNAL_SHAPE_H -#define BT_CONVEX_INTERNAL_SHAPE_H - -#include "btConvexShape.h" - -///btConvexInternalShape carries some additional data, shared by most implementations -class btConvexInternalShape : public btConvexShape -{ - - protected: - - //local scaling. collisionMargin is not scaled ! - btVector3 m_localScaling; - - btVector3 m_implicitShapeDimensions; - - btScalar m_collisionMargin; - - btScalar m_padding[2]; - - - - -public: - - btConvexInternalShape(); - - virtual ~btConvexInternalShape() - { - - } - - - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; -#ifndef __SPU__ - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; - - //notice that the vectors should be unit length - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; -#endif //#ifndef __SPU__ - - const btVector3& getImplicitShapeDimensions() const - { - return m_implicitShapeDimensions; - } - - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const - { - getAabbSlow(t,aabbMin,aabbMax); - } - - - - virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - - virtual void setLocalScaling(const btVector3& scaling); - virtual const btVector3& getLocalScaling() const - { - return m_localScaling; - } - - const btVector3& getLocalScalingNV() const - { - return m_localScaling; - } - - virtual void setMargin(btScalar margin) - { - m_collisionMargin = margin; - } - virtual btScalar getMargin() const - { - return m_collisionMargin; - } - - btScalar getMarginNV() const - { - return m_collisionMargin; - } - - virtual int getNumPreferredPenetrationDirections() const - { - return 0; - } - - virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const - { - (void)penetrationVector; - (void)index; - btAssert(0); - } - -}; - - -#endif //BT_CONVEX_INTERNAL_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp deleted file mode 100644 index 7afcccf8b03..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* -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. -*/ - -#include "btConvexShape.h" - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h deleted file mode 100644 index 6dfd288e05b..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -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. -*/ - -#ifndef CONVEX_SHAPE_INTERFACE1 -#define CONVEX_SHAPE_INTERFACE1 - -#include "btCollisionShape.h" - -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransform.h" -#include "LinearMath/btMatrix3x3.h" -#include "btCollisionMargin.h" -#include "LinearMath/btAlignedAllocator.h" - -//todo: get rid of this btConvexCastResult thing! -struct btConvexCastResult; -#define MAX_PREFERRED_PENETRATION_DIRECTIONS 10 - -/// btConvexShape is an abstract shape interface. -/// It describes general convex shapes using the localGetSupportingVertex interface -/// used in combination with GJK or btConvexCast -ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape -{ - - -public: - - BT_DECLARE_ALIGNED_ALLOCATOR(); - - virtual ~btConvexShape() - { - - } - - - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const =0; -#ifndef __SPU__ - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; - - //notice that the vectors should be unit length - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; -#endif //#ifndef __SPU__ - - - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; - - virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; - - virtual void setLocalScaling(const btVector3& scaling) =0; - virtual const btVector3& getLocalScaling() const =0; - - virtual void setMargin(btScalar margin)=0; - - virtual btScalar getMargin() const=0; - - virtual int getNumPreferredPenetrationDirections() const=0; - - virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0; - -}; - - - -#endif //CONVEX_SHAPE_INTERFACE1 diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp deleted file mode 100644 index 6941030b15f..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* -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. -*/ -#include "btConvexTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btCollisionMargin.h" - -#include "LinearMath/btQuaternion.h" -#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" - - -btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface) -:m_stridingMesh(meshInterface) -{ - recalcLocalAabb(); -} - - - - -///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once -///but then we are duplicating -class LocalSupportVertexCallback: public btInternalTriangleIndexCallback -{ - - btVector3 m_supportVertexLocal; -public: - - btScalar m_maxDot; - btVector3 m_supportVecLocal; - - LocalSupportVertexCallback(const btVector3& supportVecLocal) - : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), - m_maxDot(btScalar(-1e30)), - m_supportVecLocal(supportVecLocal) - { - } - - virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) - { - (void)triangleIndex; - (void)partId; - - for (int i=0;i<3;i++) - { - btScalar dot = m_supportVecLocal.dot(triangle[i]); - if (dot > m_maxDot) - { - m_maxDot = dot; - m_supportVertexLocal = triangle[i]; - } - } - } - - btVector3 GetSupportVertexLocal() - { - return m_supportVertexLocal; - } - -}; - - - - - -btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const -{ - btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); - - btVector3 vec = vec0; - btScalar lenSqr = vec.length2(); - if (lenSqr < btScalar(0.0001)) - { - vec.setValue(1,0,0); - } else - { - btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); - vec *= rlen; - } - - LocalSupportVertexCallback supportCallback(vec); - btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); - supVec = supportCallback.GetSupportVertexLocal(); - - return supVec; -} - -void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const -{ - //use 'w' component of supportVerticesOut? - { - for (int i=0;iInternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); - supportVerticesOut[j] = supportCallback.GetSupportVertexLocal(); - } - -} - - - -btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const -{ - btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); - - if ( getMargin()!=btScalar(0.) ) - { - btVector3 vecnorm = vec; - if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) - { - vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); - } - vecnorm.normalize(); - supVertex+= getMargin() * vecnorm; - } - return supVertex; -} - - - - - - - - - -//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection -//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo -int btConvexTriangleMeshShape::getNumVertices() const -{ - //cache this? - return 0; - -} - -int btConvexTriangleMeshShape::getNumEdges() const -{ - return 0; -} - -void btConvexTriangleMeshShape::getEdge(int ,btPoint3& ,btPoint3& ) const -{ - btAssert(0); -} - -void btConvexTriangleMeshShape::getVertex(int ,btPoint3& ) const -{ - btAssert(0); -} - -int btConvexTriangleMeshShape::getNumPlanes() const -{ - return 0; -} - -void btConvexTriangleMeshShape::getPlane(btVector3& ,btPoint3& ,int ) const -{ - btAssert(0); -} - -//not yet -bool btConvexTriangleMeshShape::isInside(const btPoint3& ,btScalar ) const -{ - btAssert(0); - return false; -} - - - -void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling) -{ - m_stridingMesh->setScaling(scaling); - - recalcLocalAabb(); - -} - - -const btVector3& btConvexTriangleMeshShape::getLocalScaling() const -{ - return m_stridingMesh->getScaling(); -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h deleted file mode 100644 index f3daa58368f..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef CONVEX_TRIANGLEMESH_SHAPE_H -#define CONVEX_TRIANGLEMESH_SHAPE_H - - -#include "btPolyhedralConvexShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types - - -/// btConvexTriangleMeshShape is a convex hull of a triangle mesh. If you just have a point cloud, you can use btConvexHullShape instead. -/// It uses the btStridingMeshInterface instead of a point cloud. This can avoid the duplication of the triangle mesh data. -class btConvexTriangleMeshShape : public btPolyhedralConvexShape -{ - - class btStridingMeshInterface* m_stridingMesh; - -public: - btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface); - - class btStridingMeshInterface* getMeshInterface() - { - return m_stridingMesh; - } - const class btStridingMeshInterface* getMeshInterface() const - { - return m_stridingMesh; - } - - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - - virtual int getShapeType()const { return CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; } - - //debugging - virtual const char* getName()const {return "ConvexTrimesh";} - - virtual int getNumVertices() const; - virtual int getNumEdges() const; - virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const; - virtual void getVertex(int i,btPoint3& vtx) const; - virtual int getNumPlanes() const; - virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const; - virtual bool isInside(const btPoint3& pt,btScalar tolerance) const; - - - virtual void setLocalScaling(const btVector3& scaling); - virtual const btVector3& getLocalScaling() const; - -}; - - - -#endif //CONVEX_TRIANGLEMESH_SHAPE_H - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp deleted file mode 100644 index 3afef1c7550..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* -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. -*/ -#include "btCylinderShape.h" -#include "LinearMath/btPoint3.h" - -btCylinderShape::btCylinderShape (const btVector3& halfExtents) -:btBoxShape(halfExtents), -m_upAxis(1) -{ - recalcLocalAabb(); -} - - -btCylinderShapeX::btCylinderShapeX (const btVector3& halfExtents) -:btCylinderShape(halfExtents) -{ - m_upAxis = 0; - recalcLocalAabb(); -} - - -btCylinderShapeZ::btCylinderShapeZ (const btVector3& halfExtents) -:btCylinderShape(halfExtents) -{ - m_upAxis = 2; - recalcLocalAabb(); -} - -void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const -{ - //skip the box 'getAabb' - btPolyhedralConvexShape::getAabb(t,aabbMin,aabbMax); -} - - -SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) -{ -const int cylinderUpAxis = 0; -const int XX = 1; -const int YY = 0; -const int ZZ = 2; - - //mapping depends on how cylinder local orientation is - // extents of the cylinder is: X,Y is for radius, and Z for height - - - btScalar radius = halfExtents[XX]; - btScalar halfHeight = halfExtents[cylinderUpAxis]; - - - btVector3 tmp; - btScalar d ; - - btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); - if (s != btScalar(0.0)) - { - d = radius / s; - tmp[XX] = v[XX] * d; - tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; - tmp[ZZ] = v[ZZ] * d; - return tmp; - } - else - { - tmp[XX] = radius; - tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; - tmp[ZZ] = btScalar(0.0); - return tmp; - } - - -} - - - - - - -inline btVector3 CylinderLocalSupportY(const btVector3& halfExtents,const btVector3& v) -{ - -const int cylinderUpAxis = 1; -const int XX = 0; -const int YY = 1; -const int ZZ = 2; - - - btScalar radius = halfExtents[XX]; - btScalar halfHeight = halfExtents[cylinderUpAxis]; - - - btVector3 tmp; - btScalar d ; - - btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); - if (s != btScalar(0.0)) - { - d = radius / s; - tmp[XX] = v[XX] * d; - tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; - tmp[ZZ] = v[ZZ] * d; - return tmp; - } - else - { - tmp[XX] = radius; - tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; - tmp[ZZ] = btScalar(0.0); - return tmp; - } - -} - -inline btVector3 CylinderLocalSupportZ(const btVector3& halfExtents,const btVector3& v) -{ -const int cylinderUpAxis = 2; -const int XX = 0; -const int YY = 2; -const int ZZ = 1; - - //mapping depends on how cylinder local orientation is - // extents of the cylinder is: X,Y is for radius, and Z for height - - - btScalar radius = halfExtents[XX]; - btScalar halfHeight = halfExtents[cylinderUpAxis]; - - - btVector3 tmp; - btScalar d ; - - btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); - if (s != btScalar(0.0)) - { - d = radius / s; - tmp[XX] = v[XX] * d; - tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; - tmp[ZZ] = v[ZZ] * d; - return tmp; - } - else - { - tmp[XX] = radius; - tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; - tmp[ZZ] = btScalar(0.0); - return tmp; - } - - -} - -btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const -{ - return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec); -} - - -btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const -{ - return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec); -} -btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const -{ - return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec); -} - -void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const -{ - for (int i=0;i=0); - btAssert(y>=0); - btAssert(xstartX) - startX = quantizedAabbMin[1]; - if (quantizedAabbMax[1]startJ) - startJ = quantizedAabbMin[2]; - if (quantizedAabbMax[2]startX) - startX = quantizedAabbMin[0]; - if (quantizedAabbMax[0]startJ) - startJ = quantizedAabbMin[2]; - if (quantizedAabbMax[2]startX) - startX = quantizedAabbMin[0]; - if (quantizedAabbMax[0]startJ) - startJ = quantizedAabbMin[1]; - if (quantizedAabbMax[1]processTriangle(vertices,x,j); - //second triangle - getVertex(x,j,vertices[0]); - getVertex(x+1,j+1,vertices[1]); - getVertex(x,j+1,vertices[2]); - callback->processTriangle(vertices,x,j); - } else - { - //first triangle - getVertex(x,j,vertices[0]); - getVertex(x,j+1,vertices[1]); - getVertex(x+1,j,vertices[2]); - callback->processTriangle(vertices,x,j); - //second triangle - getVertex(x+1,j,vertices[0]); - getVertex(x,j+1,vertices[1]); - getVertex(x+1,j+1,vertices[2]); - callback->processTriangle(vertices,x,j); - } - } - } - - - -} - -void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const -{ - //moving concave objects not supported - - inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); -} - -void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling) -{ - m_localScaling = scaling; -} -const btVector3& btHeightfieldTerrainShape::getLocalScaling() const -{ - return m_localScaling; -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h deleted file mode 100644 index 8dba7b3d5fe..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -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. -*/ - -#ifndef HEIGHTFIELD_TERRAIN_SHAPE_H -#define HEIGHTFIELD_TERRAIN_SHAPE_H - -#include "btConcaveShape.h" - -///btHeightfieldTerrainShape simulates a 2D heightfield terrain -class btHeightfieldTerrainShape : public btConcaveShape -{ -protected: - btVector3 m_localAabbMin; - btVector3 m_localAabbMax; - - ///terrain data - int m_width; - int m_length; - btScalar m_maxHeight; - union - { - unsigned char* m_heightfieldDataUnsignedChar; - btScalar* m_heightfieldDataFloat; - void* m_heightfieldDataUnknown; - }; - - bool m_useFloatData; - bool m_flipQuadEdges; - bool m_useDiamondSubdivision; - - int m_upAxis; - - btVector3 m_localScaling; - - virtual btScalar getHeightFieldValue(int x,int y) const; - void quantizeWithClamp(int* out, const btVector3& point) const; - void getVertex(int x,int y,btVector3& vertex) const; - - inline bool testQuantizedAabbAgainstQuantizedAabb(int* aabbMin1, int* aabbMax1,const int* aabbMin2,const int* aabbMax2) const - { - bool overlap = true; - overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; - overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; - overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; - return overlap; - } - -public: - btHeightfieldTerrainShape(int width,int height,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges); - - virtual ~btHeightfieldTerrainShape(); - - - void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;} - - virtual int getShapeType() const - { - return TERRAIN_SHAPE_PROXYTYPE; - } - - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - - virtual void setLocalScaling(const btVector3& scaling); - - virtual const btVector3& getLocalScaling() const; - - //debugging - virtual const char* getName()const {return "HEIGHTFIELD";} - -}; - -#endif //HEIGHTFIELD_TERRAIN_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp deleted file mode 100644 index 7f7f2822189..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -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. -*/ - -#include "btMinkowskiSumShape.h" - - -btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB) -:m_shapeA(shapeA), -m_shapeB(shapeB) -{ - m_transA.setIdentity(); - m_transB.setIdentity(); -} - -btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const -{ - btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis())); - btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(vec*m_transB.getBasis())); - return supVertexA + supVertexB; -} - -void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const -{ - //todo: could make recursive use of batching. probably this shape is not used frequently. - for (int i=0;igetMargin() + m_shapeB->getMargin(); -} - - -void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const -{ - (void)mass; - btAssert(0); - inertia.setValue(0,0,0); -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h deleted file mode 100644 index 484e317e6fc..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -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. -*/ - -#ifndef MINKOWSKI_SUM_SHAPE_H -#define MINKOWSKI_SUM_SHAPE_H - -#include "btConvexInternalShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types - -/// btMinkowskiSumShape represents implicit (getSupportingVertex) based minkowski sum of two convex implicit shapes. -class btMinkowskiSumShape : public btConvexInternalShape -{ - - btTransform m_transA; - btTransform m_transB; - const btConvexShape* m_shapeA; - const btConvexShape* m_shapeB; - -public: - - btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB); - - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; - - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - - - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - - void setTransformA(const btTransform& transA) { m_transA = transA;} - void setTransformB(const btTransform& transB) { m_transB = transB;} - - const btTransform& getTransformA()const { return m_transA;} - const btTransform& GetTransformB()const { return m_transB;} - - - virtual int getShapeType() const { return MINKOWSKI_SUM_SHAPE_PROXYTYPE; } - - virtual btScalar getMargin() const; - - const btConvexShape* getShapeA() const { return m_shapeA;} - const btConvexShape* getShapeB() const { return m_shapeB;} - - virtual const char* getName()const - { - return "MinkowskiSum"; - } -}; - -#endif //MINKOWSKI_SUM_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp deleted file mode 100644 index a8ce8622f9f..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* -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. -*/ - -#include "btMultiSphereShape.h" -#include "BulletCollision/CollisionShapes/btCollisionMargin.h" -#include "LinearMath/btQuaternion.h" - -btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,const btVector3* positions,const btScalar* radi,int numSpheres) -:m_inertiaHalfExtents(inertiaHalfExtents) -{ - btScalar startMargin = btScalar(1e30); - - m_numSpheres = numSpheres; - for (int i=0;i maxDot) - { - maxDot = newDot; - supVec = vtx; - } - } - - return supVec; - -} - - void btMultiSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const -{ - - for (int j=0;j maxDot) - { - maxDot = newDot; - supportVerticesOut[j] = vtx; - } - } - } -} - - - - - - - - -void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const -{ - //as an approximation, take the inertia of the box that bounds the spheres - - btTransform ident; - ident.setIdentity(); -// btVector3 aabbMin,aabbMax; - -// getAabb(ident,aabbMin,aabbMax); - - btVector3 halfExtents = m_inertiaHalfExtents;//(aabbMax - aabbMin)* btScalar(0.5); - - btScalar margin = CONVEX_DISTANCE_MARGIN; - - btScalar lx=btScalar(2.)*(halfExtents[0]+margin); - btScalar ly=btScalar(2.)*(halfExtents[1]+margin); - btScalar lz=btScalar(2.)*(halfExtents[2]+margin); - const btScalar x2 = lx*lx; - const btScalar y2 = ly*ly; - const btScalar z2 = lz*lz; - const btScalar scaledmass = mass * btScalar(.08333333); - - inertia[0] = scaledmass * (y2+z2); - inertia[1] = scaledmass * (x2+z2); - inertia[2] = scaledmass * (x2+y2); - -} - - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h deleted file mode 100644 index 7db54e7a23c..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -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. -*/ - -#ifndef MULTI_SPHERE_MINKOWSKI_H -#define MULTI_SPHERE_MINKOWSKI_H - -#include "btConvexInternalShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types - -#define MAX_NUM_SPHERES 5 - -///btMultiSphereShape represents implicit convex hull of a collection of spheres (using getSupportingVertex) -class btMultiSphereShape : public btConvexInternalShape - -{ - - btVector3 m_localPositions[MAX_NUM_SPHERES]; - btScalar m_radi[MAX_NUM_SPHERES]; - btVector3 m_inertiaHalfExtents; - - int m_numSpheres; - - - - -public: - btMultiSphereShape (const btVector3& inertiaHalfExtents,const btVector3* positions,const btScalar* radi,int numSpheres); - - ///CollisionShape Interface - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - - /// btConvexShape Interface - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; - - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - - int getSphereCount() const - { - return m_numSpheres; - } - - const btVector3& getSpherePosition(int index) const - { - return m_localPositions[index]; - } - - btScalar getSphereRadius(int index) const - { - return m_radi[index]; - } - - virtual int getShapeType() const { return MULTI_SPHERE_SHAPE_PROXYTYPE; } - - virtual const char* getName()const - { - return "MultiSphere"; - } - -}; - - -#endif //MULTI_SPHERE_MINKOWSKI_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp deleted file mode 100644 index e80469f45cf..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp +++ /dev/null @@ -1,1181 +0,0 @@ -/* -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. -*/ -#include "btOptimizedBvh.h" -#include "btStridingMeshInterface.h" -#include "LinearMath/btAabbUtil2.h" -#include "LinearMath/btIDebugDraw.h" - - -btOptimizedBvh::btOptimizedBvh() : m_useQuantization(false), - //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY) - m_traversalMode(TRAVERSAL_STACKLESS) - //m_traversalMode(TRAVERSAL_RECURSIVE) - ,m_subtreeHeaderCount(0) //PCK: add this line -{ - -} - - -void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax) -{ - m_useQuantization = useQuantizedAabbCompression; - - - // NodeArray triangleNodes; - - struct NodeTriangleCallback : public btInternalTriangleIndexCallback - { - - NodeArray& m_triangleNodes; - - NodeTriangleCallback& operator=(NodeTriangleCallback& other) - { - m_triangleNodes = other.m_triangleNodes; - return *this; - } - - NodeTriangleCallback(NodeArray& triangleNodes) - :m_triangleNodes(triangleNodes) - { - } - - virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) - { - btOptimizedBvhNode node; - btVector3 aabbMin,aabbMax; - aabbMin.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - aabbMax.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); - aabbMin.setMin(triangle[0]); - aabbMax.setMax(triangle[0]); - aabbMin.setMin(triangle[1]); - aabbMax.setMax(triangle[1]); - aabbMin.setMin(triangle[2]); - aabbMax.setMax(triangle[2]); - - //with quantization? - node.m_aabbMinOrg = aabbMin; - node.m_aabbMaxOrg = aabbMax; - - node.m_escapeIndex = -1; - - //for child nodes - node.m_subPart = partId; - node.m_triangleIndex = triangleIndex; - m_triangleNodes.push_back(node); - } - }; - struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback - { - QuantizedNodeArray& m_triangleNodes; - const btOptimizedBvh* m_optimizedTree; // for quantization - - QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other) - { - m_triangleNodes = other.m_triangleNodes; - m_optimizedTree = other.m_optimizedTree; - return *this; - } - - QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btOptimizedBvh* tree) - :m_triangleNodes(triangleNodes),m_optimizedTree(tree) - { - } - - virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) - { - btAssert(partId==0); - //negative indices are reserved for escapeIndex - btAssert(triangleIndex>=0); - - btQuantizedBvhNode node; - btVector3 aabbMin,aabbMax; - aabbMin.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - aabbMax.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); - aabbMin.setMin(triangle[0]); - aabbMax.setMax(triangle[0]); - aabbMin.setMin(triangle[1]); - aabbMax.setMax(triangle[1]); - aabbMin.setMin(triangle[2]); - aabbMax.setMax(triangle[2]); - - //PCK: add these checks for zero dimensions of aabb - const btScalar MIN_AABB_DIMENSION = btScalar(0.002); - const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001); - if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION) - { - aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION); - aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION); - } - if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION) - { - aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION); - aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION); - } - if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION) - { - aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION); - aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION); - } - - m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMin[0],aabbMin); - m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMax[0],aabbMax); - - node.m_escapeIndexOrTriangleIndex = triangleIndex; - - m_triangleNodes.push_back(node); - } - }; - - - - int numLeafNodes = 0; - - - if (m_useQuantization) - { - - //initialize quantization values - setQuantizationValues(bvhAabbMin,bvhAabbMax); - - QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this); - - - triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax); - - //now we have an array of leafnodes in m_leafNodes - numLeafNodes = m_quantizedLeafNodes.size(); - - - m_quantizedContiguousNodes.resize(2*numLeafNodes); - - - } else - { - NodeTriangleCallback callback(m_leafNodes); - - btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); - btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - - triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax); - - //now we have an array of leafnodes in m_leafNodes - numLeafNodes = m_leafNodes.size(); - - m_contiguousNodes.resize(2*numLeafNodes); - } - - m_curNodeIndex = 0; - - buildTree(0,numLeafNodes); - - ///if the entire tree is small then subtree size, we need to create a header info for the tree - if(m_useQuantization && !m_SubtreeHeaders.size()) - { - btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); - subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]); - subtree.m_rootNodeIndex = 0; - subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); - } - - //PCK: update the copy of the size - m_subtreeHeaderCount = m_SubtreeHeaders.size(); - - //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary - m_quantizedLeafNodes.clear(); - m_leafNodes.clear(); -} - - - -void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax) -{ - //incrementally initialize quantization values - btAssert(m_useQuantization); - - btAssert(aabbMin.getX() > m_bvhAabbMin.getX()); - btAssert(aabbMin.getY() > m_bvhAabbMin.getY()); - btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ()); - - btAssert(aabbMax.getX() < m_bvhAabbMax.getX()); - btAssert(aabbMax.getY() < m_bvhAabbMax.getY()); - btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ()); - - ///we should update all quantization values, using updateBvhNodes(meshInterface); - ///but we only update chunks that overlap the given aabb - - unsigned short quantizedQueryAabbMin[3]; - unsigned short quantizedQueryAabbMax[3]; - - quantizeWithClamp(&quantizedQueryAabbMin[0],aabbMin); - quantizeWithClamp(&quantizedQueryAabbMax[0],aabbMax); - - int i; - for (i=0;im_SubtreeHeaders.size();i++) - { - btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; - - //PCK: unsigned instead of bool - unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); - if (overlap != 0) - { - updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i); - - subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]); - } - } - -} - -///just for debugging, to visualize the individual patches/subtrees -#ifdef DEBUG_PATCH_COLORS -btVector3 color[4]= -{ - btVector3(255,0,0), - btVector3(0,255,0), - btVector3(0,0,255), - btVector3(0,255,255) -}; -#endif //DEBUG_PATCH_COLORS - - -void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index) -{ - (void)index; - - btAssert(m_useQuantization); - - int nodeSubPart=0; - - //get access info to trianglemesh data - const unsigned char *vertexbase; - int numverts; - PHY_ScalarType type; - int stride; - const unsigned char *indexbase; - int indexstride; - int numfaces; - PHY_ScalarType indicestype; - meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); - - btVector3 triangleVerts[3]; - btVector3 aabbMin,aabbMax; - const btVector3& meshScaling = meshInterface->getScaling(); - - int i; - for (i=endNode-1;i>=firstNode;i--) - { - - - btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i]; - if (curNode.isLeafNode()) - { - //recalc aabb from triangle data - int nodeTriangleIndex = curNode.getTriangleIndex(); - //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts, - - int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); - - - for (int j=2;j>=0;j--) - { - - int graphicsindex = gfxbase[j]; - btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); -#ifdef DEBUG_PATCH_COLORS - btVector3 mycolor = color[index&3]; - graphicsbase[8] = mycolor.getX(); - graphicsbase[9] = mycolor.getY(); - graphicsbase[10] = mycolor.getZ(); -#endif //DEBUG_PATCH_COLORS - - - triangleVerts[j] = btVector3( - graphicsbase[0]*meshScaling.getX(), - graphicsbase[1]*meshScaling.getY(), - graphicsbase[2]*meshScaling.getZ()); - } - - - - aabbMin.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - aabbMax.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); - aabbMin.setMin(triangleVerts[0]); - aabbMax.setMax(triangleVerts[0]); - aabbMin.setMin(triangleVerts[1]); - aabbMax.setMax(triangleVerts[1]); - aabbMin.setMin(triangleVerts[2]); - aabbMax.setMax(triangleVerts[2]); - - quantizeWithClamp(&curNode.m_quantizedAabbMin[0],aabbMin); - quantizeWithClamp(&curNode.m_quantizedAabbMax[0],aabbMax); - - } else - { - //combine aabb from both children - - btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1]; - - btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] : - &m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()]; - - - { - for (int i=0;i<3;i++) - { - curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i]; - if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i]) - curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i]; - - curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i]; - if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i]) - curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i]; - } - } - } - - } - - meshInterface->unLockReadOnlyVertexBase(nodeSubPart); - - -} - -void btOptimizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin) -{ - //enlarge the AABB to avoid division by zero when initializing the quantization values - btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin); - m_bvhAabbMin = bvhAabbMin - clampValue; - m_bvhAabbMax = bvhAabbMax + clampValue; - btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin; - m_bvhQuantization = btVector3(btScalar(65535.0),btScalar(65535.0),btScalar(65535.0)) / aabbSize; -} - - -void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface) -{ - if (m_useQuantization) - { - //calculate new aabb - btVector3 aabbMin,aabbMax; - meshInterface->calculateAabbBruteForce(aabbMin,aabbMax); - - setQuantizationValues(aabbMin,aabbMax); - - updateBvhNodes(meshInterface,0,m_curNodeIndex,0); - - ///now update all subtree headers - - int i; - for (i=0;i gMaxStackDepth) - gMaxStackDepth = gStackDepth; -#endif //DEBUG_TREE_BUILDING - - - int splitAxis, splitIndex, i; - int numIndices =endIndex-startIndex; - int curIndex = m_curNodeIndex; - - assert(numIndices>0); - - if (numIndices==1) - { -#ifdef DEBUG_TREE_BUILDING - gStackDepth--; -#endif //DEBUG_TREE_BUILDING - - assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex); - - m_curNodeIndex++; - return; - } - //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. - - splitAxis = calcSplittingAxis(startIndex,endIndex); - - splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis); - - int internalNodeIndex = m_curNodeIndex; - - setInternalNodeAabbMax(m_curNodeIndex,btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30))); - setInternalNodeAabbMin(m_curNodeIndex,btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30))); - - for (i=startIndex;im_escapeIndex; - - int leftChildNodexIndex = m_curNodeIndex; - - //build left child tree - buildTree(startIndex,splitIndex); - - int rightChildNodexIndex = m_curNodeIndex; - //build right child tree - buildTree(splitIndex,endIndex); - -#ifdef DEBUG_TREE_BUILDING - gStackDepth--; -#endif //DEBUG_TREE_BUILDING - - int escapeIndex = m_curNodeIndex - curIndex; - - if (m_useQuantization) - { - //escapeIndex is the number of nodes of this subtree - const int sizeQuantizedNode =sizeof(btQuantizedBvhNode); - const int treeSizeInBytes = escapeIndex * sizeQuantizedNode; - if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES) - { - updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex); - } - } - - setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex); - -} - -void btOptimizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex) -{ - btAssert(m_useQuantization); - - btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex]; - int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex(); - int leftSubTreeSizeInBytes = leftSubTreeSize * sizeof(btQuantizedBvhNode); - - btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex]; - int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex(); - int rightSubTreeSizeInBytes = rightSubTreeSize * sizeof(btQuantizedBvhNode); - - if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) - { - btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); - subtree.setAabbFromQuantizeNode(leftChildNode); - subtree.m_rootNodeIndex = leftChildNodexIndex; - subtree.m_subtreeSize = leftSubTreeSize; - } - - if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) - { - btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); - subtree.setAabbFromQuantizeNode(rightChildNode); - subtree.m_rootNodeIndex = rightChildNodexIndex; - subtree.m_subtreeSize = rightSubTreeSize; - } - - //PCK: update the copy of the size - m_subtreeHeaderCount = m_SubtreeHeaders.size(); -} - - -int btOptimizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis) -{ - int i; - int splitIndex =startIndex; - int numIndices = endIndex - startIndex; - btScalar splitValue; - - btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); - for (i=startIndex;i splitValue) - { - //swap - swapLeafNodes(i,splitIndex); - splitIndex++; - } - } - - //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex - //otherwise the tree-building might fail due to stack-overflows in certain cases. - //unbalanced1 is unsafe: it can cause stack overflows - //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); - - //unbalanced2 should work too: always use center (perfect balanced trees) - //bool unbalanced2 = true; - - //this should be safe too: - int rangeBalancedIndices = numIndices/3; - bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); - - if (unbalanced) - { - splitIndex = startIndex+ (numIndices>>1); - } - - bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); - btAssert(!unbal); - - return splitIndex; -} - - -int btOptimizedBvh::calcSplittingAxis(int startIndex,int endIndex) -{ - int i; - - btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); - btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); - int numIndices = endIndex-startIndex; - - for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg); - isLeafNode = rootNode->m_escapeIndex == -1; - - //PCK: unsigned instead of bool - if (isLeafNode && (aabbOverlap != 0)) - { - nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); - } - - //PCK: unsigned instead of bool - if ((aabbOverlap != 0) || isLeafNode) - { - rootNode++; - curIndex++; - } else - { - escapeIndex = rootNode->m_escapeIndex; - rootNode += escapeIndex; - curIndex += escapeIndex; - } - } - if (maxIterations < walkIterations) - maxIterations = walkIterations; - -} - -/* -///this was the original recursive traversal, before we optimized towards stackless traversal -void btOptimizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const -{ - bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax); - if (aabbOverlap) - { - isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild); - if (isLeafNode) - { - nodeCallback->processNode(rootNode); - } else - { - walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax); - walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax); - } - } - -} -*/ - -void btOptimizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const -{ - btAssert(m_useQuantization); - - bool isLeafNode; - //PCK: unsigned instead of bool - unsigned aabbOverlap; - - //PCK: unsigned instead of bool - aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax); - isLeafNode = currentNode->isLeafNode(); - - //PCK: unsigned instead of bool - if (aabbOverlap != 0) - { - if (isLeafNode) - { - nodeCallback->processNode(0,currentNode->getTriangleIndex()); - } else - { - //process left and right children - const btQuantizedBvhNode* leftChildNode = currentNode+1; - walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); - - const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex(); - walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); - } - } -} - - - - - - - -void btOptimizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const -{ - btAssert(m_useQuantization); - - int curIndex = startNodeIndex; - int walkIterations = 0; - int subTreeSize = endNodeIndex - startNodeIndex; - - const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; - int escapeIndex; - - bool isLeafNode; - //PCK: unsigned instead of bool - unsigned aabbOverlap; - - while (curIndex < endNodeIndex) - { - -//#define VISUALLY_ANALYZE_BVH 1 -#ifdef VISUALLY_ANALYZE_BVH - //some code snippet to debugDraw aabb, to visually analyze bvh structure - static int drawPatch = 0; - //need some global access to a debugDrawer - extern btIDebugDraw* debugDrawerPtr; - if (curIndex==drawPatch) - { - btVector3 aabbMin,aabbMax; - aabbMin = unQuantize(rootNode->m_quantizedAabbMin); - aabbMax = unQuantize(rootNode->m_quantizedAabbMax); - btVector3 color(1,0,0); - debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); - } -#endif//VISUALLY_ANALYZE_BVH - - //catch bugs in tree data - assert (walkIterations < subTreeSize); - - walkIterations++; - //PCK: unsigned instead of bool - aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); - isLeafNode = rootNode->isLeafNode(); - - if (isLeafNode && aabbOverlap) - { - nodeCallback->processNode(0,rootNode->getTriangleIndex()); - } - - //PCK: unsigned instead of bool - if ((aabbOverlap != 0) || isLeafNode) - { - rootNode++; - curIndex++; - } else - { - escapeIndex = rootNode->getEscapeIndex(); - rootNode += escapeIndex; - curIndex += escapeIndex; - } - } - if (maxIterations < walkIterations) - maxIterations = walkIterations; - -} - -//This traversal can be called from Playstation 3 SPU -void btOptimizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const -{ - btAssert(m_useQuantization); - - int i; - - - for (i=0;im_SubtreeHeaders.size();i++) - { - const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; - - //PCK: unsigned instead of bool - unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); - if (overlap != 0) - { - walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, - subtree.m_rootNodeIndex, - subtree.m_rootNodeIndex+subtree.m_subtreeSize); - } - } -} - - - - -void btOptimizedBvh::reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const -{ - (void)nodeCallback; - (void)aabbMin; - (void)aabbMax; - //not yet, please use aabb - btAssert(0); -} - - - - -btVector3 btOptimizedBvh::unQuantize(const unsigned short* vecIn) const -{ - btVector3 vecOut; - vecOut.setValue( - (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()), - (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()), - (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ())); - vecOut += m_bvhAabbMin; - return vecOut; -} - - -void btOptimizedBvh::swapLeafNodes(int i,int splitIndex) -{ - if (m_useQuantization) - { - btQuantizedBvhNode tmp = m_quantizedLeafNodes[i]; - m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex]; - m_quantizedLeafNodes[splitIndex] = tmp; - } else - { - btOptimizedBvhNode tmp = m_leafNodes[i]; - m_leafNodes[i] = m_leafNodes[splitIndex]; - m_leafNodes[splitIndex] = tmp; - } -} - -void btOptimizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex) -{ - if (m_useQuantization) - { - m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex]; - } else - { - m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex]; - } -} - -//PCK: include -#include - -//PCK: consts -static const unsigned BVH_ALIGNMENT = 16; -static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1; - -static const unsigned BVH_ALIGNMENT_BLOCKS = 2; - - - -unsigned int btOptimizedBvh::getAlignmentSerializationPadding() -{ - return BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT; -} - -unsigned btOptimizedBvh::calculateSerializeBufferSize() -{ - unsigned baseSize = sizeof(btOptimizedBvh) + getAlignmentSerializationPadding(); - baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; - if (m_useQuantization) - { - return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode); - } - return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode); -} - -bool btOptimizedBvh::serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) -{ - assert(m_subtreeHeaderCount == m_SubtreeHeaders.size()); - m_subtreeHeaderCount = m_SubtreeHeaders.size(); - -/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) - { - ///check alignedment for buffer? - btAssert(0); - return false; - } -*/ - - btOptimizedBvh *targetBvh = (btOptimizedBvh *)o_alignedDataBuffer; - - // construct the class so the virtual function table, etc will be set up - // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor - new (targetBvh) btOptimizedBvh; - - if (i_swapEndian) - { - targetBvh->m_curNodeIndex = btSwapEndian(m_curNodeIndex); - - - btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin); - btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax); - btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization); - - targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode); - targetBvh->m_subtreeHeaderCount = btSwapEndian(m_subtreeHeaderCount); - } - else - { - targetBvh->m_curNodeIndex = m_curNodeIndex; - targetBvh->m_bvhAabbMin = m_bvhAabbMin; - targetBvh->m_bvhAabbMax = m_bvhAabbMax; - targetBvh->m_bvhQuantization = m_bvhQuantization; - targetBvh->m_traversalMode = m_traversalMode; - targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount; - } - - targetBvh->m_useQuantization = m_useQuantization; - - unsigned char *nodeData = (unsigned char *)targetBvh; - nodeData += sizeof(btOptimizedBvh); - - unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; - nodeData += sizeToAdd; - - int nodeCount = m_curNodeIndex; - - if (m_useQuantization) - { - targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); - - if (i_swapEndian) - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); - - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); - - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex); - } - } - else - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]; - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]; - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]; - - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]; - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]; - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]; - - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex; - - - } - } - nodeData += sizeof(btQuantizedBvhNode) * nodeCount; - } - else - { - targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); - - if (i_swapEndian) - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); - btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); - - targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex); - targetBvh->m_contiguousNodes[nodeIndex].m_subPart = btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart); - targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex); - } - } - else - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg; - targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg; - - targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex; - targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart; - targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex; - } - } - nodeData += sizeof(btOptimizedBvhNode) * nodeCount; - } - - sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; - nodeData += sizeToAdd; - - // Now serialize the subtree headers - targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount); - if (i_swapEndian) - { - for (int i = 0; i < m_subtreeHeaderCount; i++) - { - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]); - - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]); - - targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex); - targetBvh->m_SubtreeHeaders[i].m_subtreeSize = btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize); - } - } - else - { - for (int i = 0; i < m_subtreeHeaderCount; i++) - { - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]); - - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]); - - targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex); - targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize); - targetBvh->m_SubtreeHeaders[i] = m_SubtreeHeaders[i]; - } - } - - nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; - - return true; -} - -btOptimizedBvh *btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) -{ - - if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) - { - return NULL; - } - btOptimizedBvh *bvh = (btOptimizedBvh *)i_alignedDataBuffer; - - if (i_swapEndian) - { - bvh->m_curNodeIndex = btSwapEndian(bvh->m_curNodeIndex); - - btUnSwapVector3Endian(bvh->m_bvhAabbMin); - btUnSwapVector3Endian(bvh->m_bvhAabbMax); - btUnSwapVector3Endian(bvh->m_bvhQuantization); - - bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode); - bvh->m_subtreeHeaderCount = btSwapEndian(bvh->m_subtreeHeaderCount); - } - - int calculatedBufSize = bvh->calculateSerializeBufferSize(); - btAssert(calculatedBufSize <= i_dataBufferSize); - - if (calculatedBufSize > i_dataBufferSize) - { - return NULL; - } - - unsigned char *nodeData = (unsigned char *)bvh; - nodeData += sizeof(btOptimizedBvh); - - unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; - nodeData += sizeToAdd; - - int nodeCount = bvh->m_curNodeIndex; - - // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor - // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor - new (bvh) btOptimizedBvh(*bvh, false); - - if (bvh->m_useQuantization) - { - bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); - - if (i_swapEndian) - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); - - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); - - bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex); - } - } - nodeData += sizeof(btQuantizedBvhNode) * nodeCount; - } - else - { - bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); - - if (i_swapEndian) - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); - btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); - - bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex); - bvh->m_contiguousNodes[nodeIndex].m_subPart = btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart); - bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex); - } - } - nodeData += sizeof(btOptimizedBvhNode) * nodeCount; - } - - sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; - nodeData += sizeToAdd; - - // Now serialize the subtree headers - bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount); - if (i_swapEndian) - { - for (int i = 0; i < bvh->m_subtreeHeaderCount; i++) - { - bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]); - bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]); - bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]); - - bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]); - bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]); - bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]); - - bvh->m_SubtreeHeaders[i].m_rootNodeIndex = btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex); - bvh->m_SubtreeHeaders[i].m_subtreeSize = btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize); - } - } - - return bvh; -} - -// Constructor that prevents btVector3's default constructor from being called -btOptimizedBvh::btOptimizedBvh(btOptimizedBvh &self, bool ownsMemory) : -m_bvhAabbMin(self.m_bvhAabbMin), -m_bvhAabbMax(self.m_bvhAabbMax), -m_bvhQuantization(self.m_bvhQuantization) -{ - -} - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h deleted file mode 100644 index bcacdbe582b..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h +++ /dev/null @@ -1,393 +0,0 @@ -/* -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. -*/ - -#ifndef OPTIMIZED_BVH_H -#define OPTIMIZED_BVH_H - - - -#include "LinearMath/btVector3.h" -#include "LinearMath/btAlignedAllocator.h" - - -//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp - - - -class btStridingMeshInterface; - -//Note: currently we have 16 bytes per quantized node -#define MAX_SUBTREE_SIZE_IN_BYTES 2048 - - -///btQuantizedBvhNode is a compressed aabb node, 16 bytes. -///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). -ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); - - //12 bytes - unsigned short int m_quantizedAabbMin[3]; - unsigned short int m_quantizedAabbMax[3]; - //4 bytes - int m_escapeIndexOrTriangleIndex; - - bool isLeafNode() const - { - //skipindex is negative (internal node), triangleindex >=0 (leafnode) - return (m_escapeIndexOrTriangleIndex >= 0); - } - int getEscapeIndex() const - { - btAssert(!isLeafNode()); - return -m_escapeIndexOrTriangleIndex; - } - int getTriangleIndex() const - { - btAssert(isLeafNode()); - return m_escapeIndexOrTriangleIndex; - } -} -; - -/// btOptimizedBvhNode contains both internal and leaf node information. -/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. -ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); - - //32 bytes - btVector3 m_aabbMinOrg; - btVector3 m_aabbMaxOrg; - - //4 - int m_escapeIndex; - - //8 - //for child nodes - int m_subPart; - int m_triangleIndex; - int m_padding[5];//bad, due to alignment - - -}; - - -///btBvhSubtreeInfo provides info to gather a subtree of limited size -ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo -{ -public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - //12 bytes - unsigned short int m_quantizedAabbMin[3]; - unsigned short int m_quantizedAabbMax[3]; - //4 bytes, points to the root of the subtree - int m_rootNodeIndex; - //4 bytes - int m_subtreeSize; - int m_padding[3]; - - btBvhSubtreeInfo() - { - //memset(&m_padding[0], 0, sizeof(m_padding)); - } - - - void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) - { - m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0]; - m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1]; - m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2]; - m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0]; - m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1]; - m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2]; - } -} -; - - -class btNodeOverlapCallback -{ -public: - virtual ~btNodeOverlapCallback() {}; - - virtual void processNode(int subPart, int triangleIndex) = 0; -}; - -#include "LinearMath/btAlignedAllocator.h" -#include "LinearMath/btAlignedObjectArray.h" - - - -///for code readability: -typedef btAlignedObjectArray NodeArray; -typedef btAlignedObjectArray QuantizedNodeArray; -typedef btAlignedObjectArray BvhSubtreeInfoArray; - - -///OptimizedBvh store an AABB tree that can be quickly traversed on CPU (and SPU,GPU in future) -ATTRIBUTE_ALIGNED16(class) btOptimizedBvh -{ - NodeArray m_leafNodes; - NodeArray m_contiguousNodes; - - QuantizedNodeArray m_quantizedLeafNodes; - - QuantizedNodeArray m_quantizedContiguousNodes; - - int m_curNodeIndex; - - - //quantization data - bool m_useQuantization; - btVector3 m_bvhAabbMin; - btVector3 m_bvhAabbMax; - btVector3 m_bvhQuantization; -public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - enum btTraversalMode - { - TRAVERSAL_STACKLESS = 0, - TRAVERSAL_STACKLESS_CACHE_FRIENDLY, - TRAVERSAL_RECURSIVE - }; -protected: - - btTraversalMode m_traversalMode; - - BvhSubtreeInfoArray m_SubtreeHeaders; - - //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray - int m_subtreeHeaderCount; - - - ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) - ///this might be refactored into a virtual, it is usually not calculated at run-time - void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin) - { - if (m_useQuantization) - { - quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin); - } else - { - m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin; - - } - } - void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax) - { - if (m_useQuantization) - { - quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax); - } else - { - m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax; - } - } - - btVector3 getAabbMin(int nodeIndex) const - { - if (m_useQuantization) - { - return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]); - } - //non-quantized - return m_leafNodes[nodeIndex].m_aabbMinOrg; - - } - btVector3 getAabbMax(int nodeIndex) const - { - if (m_useQuantization) - { - return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]); - } - //non-quantized - return m_leafNodes[nodeIndex].m_aabbMaxOrg; - - } - - void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); - - void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex) - { - if (m_useQuantization) - { - m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex; - } - else - { - m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex; - } - - } - - void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) - { - if (m_useQuantization) - { - unsigned short int quantizedAabbMin[3]; - unsigned short int quantizedAabbMax[3]; - quantizeWithClamp(quantizedAabbMin,newAabbMin); - quantizeWithClamp(quantizedAabbMax,newAabbMax); - for (int i=0;i<3;i++) - { - if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i]) - m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i]; - - if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i]) - m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i]; - - } - } else - { - //non-quantized - m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin); - m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax); - } - } - - void swapLeafNodes(int firstIndex,int secondIndex); - - void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex); - -protected: - - - - void buildTree (int startIndex,int endIndex); - - int calcSplittingAxis(int startIndex,int endIndex); - - int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis); - - void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const; - - ///tree traversal designed for small-memory processors like PS3 SPU - void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; - - ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal - void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; - - ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal - void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; - - -#define USE_BANCHLESS 1 -#ifdef USE_BANCHLESS - //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360) - SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const - { - return btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) - & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) - & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])), - 1, 0); - } -#else - SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const - { - bool overlap = true; - overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; - overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; - overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; - return overlap; - } -#endif //USE_BANCHLESS - - void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); - -public: - btOptimizedBvh(); - - virtual ~btOptimizedBvh(); - - void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax); - - void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - void reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point) const - { - - btAssert(m_useQuantization); - - btVector3 clampedPoint(point); - clampedPoint.setMax(m_bvhAabbMin); - clampedPoint.setMin(m_bvhAabbMax); - - btVector3 v = (clampedPoint - m_bvhAabbMin) * m_bvhQuantization; - out[0] = (unsigned short)(v.getX()+0.5f); - out[1] = (unsigned short)(v.getY()+0.5f); - out[2] = (unsigned short)(v.getZ()+0.5f); - } - - - btVector3 unQuantize(const unsigned short* vecIn) const; - - ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees. - void setTraversalMode(btTraversalMode traversalMode) - { - m_traversalMode = traversalMode; - } - - void refit(btStridingMeshInterface* triangles); - - void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax); - - void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index); - - - SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray() - { - return m_quantizedContiguousNodes; - } - - SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray() - { - return m_SubtreeHeaders; - } - - /////Calculate space needed to store BVH for serialization - unsigned calculateSerializeBufferSize(); - - /// Data buffer MUST be 16 byte aligned - bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian); - - ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' - static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian); - - static unsigned int getAlignmentSerializationPadding(); - - SIMD_FORCE_INLINE bool isQuantized() - { - return m_useQuantization; - } - -private: - // Special "copy" constructor that allows for in-place deserialization - // Prevents btVector3's default constructor from being called, but doesn't inialize much else - // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need) - btOptimizedBvh(btOptimizedBvh &other, bool ownsMemory); - -} -; - - -#endif //OPTIMIZED_BVH_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp deleted file mode 100644 index 30323deb3b5..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* -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. -*/ - -#include - -btPolyhedralConvexShape::btPolyhedralConvexShape() -:m_localAabbMin(1,1,1), -m_localAabbMax(-1,-1,-1), -m_isLocalAabbValid(false), -m_optionalHull(0) -{ - -} - - - -btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const -{ - int i; - btVector3 supVec(0,0,0); - - btScalar maxDot(btScalar(-1e30)); - - btVector3 vec = vec0; - btScalar lenSqr = vec.length2(); - if (lenSqr < btScalar(0.0001)) - { - vec.setValue(1,0,0); - } else - { - btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); - vec *= rlen; - } - - btVector3 vtx; - btScalar newDot; - - for (i=0;i maxDot) - { - maxDot = newDot; - supVec = vtx; - } - } - - return supVec; - -} - -void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const -{ - int i; - - btVector3 vtx; - btScalar newDot; - - for (i=0;i supportVerticesOut[j][3]) - { - //WARNING: don't swap next lines, the w component would get overwritten! - supportVerticesOut[j] = vtx; - supportVerticesOut[j][3] = newDot; - } - } - } -} - - - -void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const -{ - //not yet, return box inertia - - btScalar margin = getMargin(); - - btTransform ident; - ident.setIdentity(); - btVector3 aabbMin,aabbMax; - getAabb(ident,aabbMin,aabbMax); - btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); - - btScalar lx=btScalar(2.)*(halfExtents.x()+margin); - btScalar ly=btScalar(2.)*(halfExtents.y()+margin); - btScalar lz=btScalar(2.)*(halfExtents.z()+margin); - const btScalar x2 = lx*lx; - const btScalar y2 = ly*ly; - const btScalar z2 = lz*lz; - const btScalar scaledmass = mass * btScalar(0.08333333); - - inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); - -} - - - -void btPolyhedralConvexShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const -{ - getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin()); -} - - - - -void btPolyhedralConvexShape::recalcLocalAabb() -{ - m_isLocalAabbValid = true; - - for (int i=0;i<3;i++) - { - btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); - vec[i] = btScalar(1.); - btVector3 tmp = localGetSupportingVertex(vec); - m_localAabbMax[i] = tmp[i]+m_collisionMargin; - vec[i] = btScalar(-1.); - tmp = localGetSupportingVertex(vec); - m_localAabbMin[i] = tmp[i]-m_collisionMargin; - } -} - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h deleted file mode 100644 index 9d46b991e10..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h +++ /dev/null @@ -1,93 +0,0 @@ -/* -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. -*/ - -#ifndef BU_SHAPE -#define BU_SHAPE - -#include "LinearMath/btPoint3.h" -#include "LinearMath/btMatrix3x3.h" -#include "btConvexInternalShape.h" - - -///PolyhedralConvexShape is an interface class for feature based (vertex/edge/face) convex shapes. -class btPolyhedralConvexShape : public btConvexInternalShape -{ - -protected: - btVector3 m_localAabbMin; - btVector3 m_localAabbMax; - bool m_isLocalAabbValid; - -public: - - btPolyhedralConvexShape(); - - //brute force implementations - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - - - inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const - { - - //lazy evaluation of local aabb - btAssert(m_isLocalAabbValid); - - btAssert(m_localAabbMin.getX() <= m_localAabbMax.getX()); - btAssert(m_localAabbMin.getY() <= m_localAabbMax.getY()); - btAssert(m_localAabbMin.getZ() <= m_localAabbMax.getZ()); - - - btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); - btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); - - btMatrix3x3 abs_b = trans.getBasis().absolute(); - - btPoint3 center = trans(localCenter); - - btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - extent += btVector3(margin,margin,margin); - - aabbMin = center - extent; - aabbMax = center + extent; - - - } - - - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - void recalcLocalAabb(); - - virtual int getNumVertices() const = 0 ; - virtual int getNumEdges() const = 0; - virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const = 0; - virtual void getVertex(int i,btPoint3& vtx) const = 0; - virtual int getNumPlanes() const = 0; - virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const = 0; -// virtual int getIndex(int i) const = 0 ; - - virtual bool isInside(const btPoint3& pt,btScalar tolerance) const = 0; - - /// optional Hull is for optional Separating Axis Test Hull collision detection, see Hull.cpp - class Hull* m_optionalHull; - -}; - -#endif //BU_SHAPE diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp deleted file mode 100644 index 15cfe432e27..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* -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. -*/ - -#include "btSphereShape.h" -#include "BulletCollision/CollisionShapes/btCollisionMargin.h" - -#include "LinearMath/btQuaternion.h" - - -btSphereShape ::btSphereShape (btScalar radius) -{ - m_implicitShapeDimensions.setX(radius); -} - -btVector3 btSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const -{ - (void)vec; - return btVector3(btScalar(0.),btScalar(0.),btScalar(0.)); -} - -void btSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const -{ - (void)vectors; - - for (int i=0;iprocessTriangle(triangle,0,0); - - triangle[0] = projectedCenter - tangentDir0*radius - tangentDir1*radius; - triangle[1] = projectedCenter - tangentDir0*radius + tangentDir1*radius; - triangle[2] = projectedCenter + tangentDir0*radius + tangentDir1*radius; - - callback->processTriangle(triangle,0,1); - -} - -void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const -{ - (void)mass; - - //moving concave objects not supported - - inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); -} - -void btStaticPlaneShape::setLocalScaling(const btVector3& scaling) -{ - m_localScaling = scaling; -} -const btVector3& btStaticPlaneShape::getLocalScaling() const -{ - return m_localScaling; -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h deleted file mode 100644 index 0cbce3abd93..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -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. -*/ - -#ifndef STATIC_PLANE_SHAPE_H -#define STATIC_PLANE_SHAPE_H - -#include "btConcaveShape.h" - - -///StaticPlaneShape simulates an 'infinite' plane by dynamically reporting triangles approximated by intersection of the plane with the AABB. -///Assumed is that the other objects is not also infinite, so a reasonable sized AABB. -class btStaticPlaneShape : public btConcaveShape -{ -protected: - btVector3 m_localAabbMin; - btVector3 m_localAabbMax; - - btVector3 m_planeNormal; - btScalar m_planeConstant; - btVector3 m_localScaling; - -public: - btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant); - - virtual ~btStaticPlaneShape(); - - - virtual int getShapeType() const - { - return STATIC_PLANE_PROXYTYPE; - } - - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - - virtual void setLocalScaling(const btVector3& scaling); - virtual const btVector3& getLocalScaling() const; - - - //debugging - virtual const char* getName()const {return "STATICPLANE";} - - -}; - -#endif //STATIC_PLANE_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp deleted file mode 100644 index 3129b7c83ce..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* -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. -*/ - -#include "btStridingMeshInterface.h" - -btStridingMeshInterface::~btStridingMeshInterface() -{ - -} - - -void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const -{ - (void)aabbMin; - (void)aabbMax; - int numtotalphysicsverts = 0; - int part,graphicssubparts = getNumSubParts(); - const unsigned char * vertexbase; - const unsigned char * indexbase; - int indexstride; - PHY_ScalarType type; - PHY_ScalarType gfxindextype; - int stride,numverts,numtriangles; - int gfxindex; - btVector3 triangle[3]; - btScalar* graphicsbase; - - btVector3 meshScaling = getScaling(); - - ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype - for (part=0;partinternalProcessTriangleIndex(triangle,part,gfxindex); - } - break; - } - case PHY_SHORT: - { - for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); - } - break; - } - default: - btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT)); - } - - unLockReadOnlyVertexBase(part); - } -} - -void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax) -{ - - struct AabbCalculationCallback : public btInternalTriangleIndexCallback - { - btVector3 m_aabbMin; - btVector3 m_aabbMax; - - AabbCalculationCallback() - { - m_aabbMin.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - m_aabbMax.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); - } - - virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) - { - (void)partId; - (void)triangleIndex; - - m_aabbMin.setMin(triangle[0]); - m_aabbMax.setMax(triangle[0]); - m_aabbMin.setMin(triangle[1]); - m_aabbMax.setMax(triangle[1]); - m_aabbMin.setMin(triangle[2]); - m_aabbMax.setMax(triangle[2]); - } - }; - - //first calculate the total aabb for all triangles - AabbCalculationCallback aabbCallback; - aabbMin.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); - aabbMax.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax); - - aabbMin = aabbCallback.m_aabbMin; - aabbMax = aabbCallback.m_aabbMax; -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h deleted file mode 100644 index 4ce0bd2e2f9..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -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. -*/ - -#ifndef STRIDING_MESHINTERFACE_H -#define STRIDING_MESHINTERFACE_H - -#include "LinearMath/btVector3.h" -#include "btTriangleCallback.h" - -/// PHY_ScalarType enumerates possible scalar types. -/// See the btStridingMeshInterface for its use -typedef enum PHY_ScalarType { - PHY_FLOAT, - PHY_DOUBLE, - PHY_INTEGER, - PHY_SHORT, - PHY_FIXEDPOINT88 -} PHY_ScalarType; - -/// btStridingMeshInterface is the interface class for high performance access to triangle meshes -/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory. -class btStridingMeshInterface -{ - protected: - - btVector3 m_scaling; - - public: - btStridingMeshInterface() :m_scaling(btScalar(1.),btScalar(1.),btScalar(1.)) - { - - } - - virtual ~btStridingMeshInterface(); - - - - void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - ///brute force method to calculate aabb - void calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax); - - /// get read and write access to a subpart of a triangle mesh - /// this subpart has a continuous array of vertices and indices - /// in this way the mesh can be handled as chunks of memory with striding - /// very similar to OpenGL vertexarray support - /// make a call to unLockVertexBase when the read and write access is finished - virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0; - - virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const=0; - - /// unLockVertexBase finishes the access to a subpart of the triangle mesh - /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished - virtual void unLockVertexBase(int subpart)=0; - - virtual void unLockReadOnlyVertexBase(int subpart) const=0; - - - /// getNumSubParts returns the number of seperate subparts - /// each subpart has a continuous array of vertices and indices - virtual int getNumSubParts() const=0; - - virtual void preallocateVertices(int numverts)=0; - virtual void preallocateIndices(int numindices)=0; - - const btVector3& getScaling() const { - return m_scaling; - } - void setScaling(const btVector3& scaling) - { - m_scaling = scaling; - } - - -}; - -#endif //STRIDING_MESHINTERFACE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp deleted file mode 100644 index 3aa1eda9964..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp +++ /dev/null @@ -1,195 +0,0 @@ - -/* -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. -*/ -#include "btTetrahedronShape.h" -#include "LinearMath/btMatrix3x3.h" - -btBU_Simplex1to4::btBU_Simplex1to4() -:m_numVertices(0) -{ -} - -btBU_Simplex1to4::btBU_Simplex1to4(const btPoint3& pt0) -:m_numVertices(0) -{ - addVertex(pt0); -} - -btBU_Simplex1to4::btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1) -:m_numVertices(0) -{ - addVertex(pt0); - addVertex(pt1); -} - -btBU_Simplex1to4::btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1,const btPoint3& pt2) -:m_numVertices(0) -{ - addVertex(pt0); - addVertex(pt1); - addVertex(pt2); -} - -btBU_Simplex1to4::btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1,const btPoint3& pt2,const btPoint3& pt3) -:m_numVertices(0) -{ - addVertex(pt0); - addVertex(pt1); - addVertex(pt2); - addVertex(pt3); -} - - - - - -void btBU_Simplex1to4::addVertex(const btPoint3& pt) -{ - m_vertices[m_numVertices++] = pt; - - recalcLocalAabb(); -} - - -int btBU_Simplex1to4::getNumVertices() const -{ - return m_numVertices; -} - -int btBU_Simplex1to4::getNumEdges() const -{ - //euler formula, F-E+V = 2, so E = F+V-2 - - switch (m_numVertices) - { - case 0: - return 0; - case 1: return 0; - case 2: return 1; - case 3: return 3; - case 4: return 6; - - - } - - return 0; -} - -void btBU_Simplex1to4::getEdge(int i,btPoint3& pa,btPoint3& pb) const -{ - - switch (m_numVertices) - { - - case 2: - pa = m_vertices[0]; - pb = m_vertices[1]; - break; - case 3: - switch (i) - { - case 0: - pa = m_vertices[0]; - pb = m_vertices[1]; - break; - case 1: - pa = m_vertices[1]; - pb = m_vertices[2]; - break; - case 2: - pa = m_vertices[2]; - pb = m_vertices[0]; - break; - - } - break; - case 4: - switch (i) - { - case 0: - pa = m_vertices[0]; - pb = m_vertices[1]; - break; - case 1: - pa = m_vertices[1]; - pb = m_vertices[2]; - break; - case 2: - pa = m_vertices[2]; - pb = m_vertices[0]; - break; - case 3: - pa = m_vertices[0]; - pb = m_vertices[3]; - break; - case 4: - pa = m_vertices[1]; - pb = m_vertices[3]; - break; - case 5: - pa = m_vertices[2]; - pb = m_vertices[3]; - break; - } - - } - - - - -} - -void btBU_Simplex1to4::getVertex(int i,btPoint3& vtx) const -{ - vtx = m_vertices[i]; -} - -int btBU_Simplex1to4::getNumPlanes() const -{ - switch (m_numVertices) - { - case 0: - return 0; - case 1: - return 0; - case 2: - return 0; - case 3: - return 2; - case 4: - return 4; - default: - { - } - } - return 0; -} - - -void btBU_Simplex1to4::getPlane(btVector3&, btPoint3& ,int ) const -{ - -} - -int btBU_Simplex1to4::getIndex(int ) const -{ - return 0; -} - -bool btBU_Simplex1to4::isInside(const btPoint3& ,btScalar ) const -{ - return false; -} - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h deleted file mode 100644 index ca1b4b42a6f..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -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. -*/ - -#ifndef BU_SIMPLEX_1TO4_SHAPE -#define BU_SIMPLEX_1TO4_SHAPE - - -#include "btPolyhedralConvexShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" - - -///BU_Simplex1to4 implements feature based and implicit simplex of up to 4 vertices (tetrahedron, triangle, line, vertex). -class btBU_Simplex1to4 : public btPolyhedralConvexShape -{ -protected: - - int m_numVertices; - btPoint3 m_vertices[4]; - -public: - btBU_Simplex1to4(); - - btBU_Simplex1to4(const btPoint3& pt0); - btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1); - btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1,const btPoint3& pt2); - btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1,const btPoint3& pt2,const btPoint3& pt3); - - - void reset() - { - m_numVertices = 0; - } - - - virtual int getShapeType() const{ return TETRAHEDRAL_SHAPE_PROXYTYPE; } - - void addVertex(const btPoint3& pt); - - //PolyhedralConvexShape interface - - virtual int getNumVertices() const; - - virtual int getNumEdges() const; - - virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const; - - virtual void getVertex(int i,btPoint3& vtx) const; - - virtual int getNumPlanes() const; - - virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i) const; - - virtual int getIndex(int i) const; - - virtual bool isInside(const btPoint3& pt,btScalar tolerance) const; - - - ///getName is for debugging - virtual const char* getName()const { return "btBU_Simplex1to4";} - -}; - -#endif //BU_SIMPLEX_1TO4_SHAPE diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp deleted file mode 100644 index 54864c32f3a..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* -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. -*/ - -#include "btTriangleBuffer.h" - - -///example usage of this class: -// btTriangleBuffer triBuf; -// concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax); -// for (int i=0;i m_triangleBuffer; - -public: - - - virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); - - int getNumTriangles() const - { - return int(m_triangleBuffer.size()); - } - - const btTriangle& getTriangle(int index) const - { - return m_triangleBuffer[index]; - } - - void clearBuffer() - { - m_triangleBuffer.clear(); - } - -}; - - -#endif //BT_TRIANGLE_BUFFER_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp deleted file mode 100644 index a020746db5f..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* -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. -*/ - -#include "btTriangleCallback.h" - -btTriangleCallback::~btTriangleCallback() -{ - -} - - -btInternalTriangleIndexCallback::~btInternalTriangleIndexCallback() -{ - -} - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h deleted file mode 100644 index 7b2337498ec..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -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. -*/ - -#ifndef TRIANGLE_CALLBACK_H -#define TRIANGLE_CALLBACK_H - -#include "LinearMath/btVector3.h" - - -class btTriangleCallback -{ -public: - - virtual ~btTriangleCallback(); - virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) = 0; -}; - -class btInternalTriangleIndexCallback -{ -public: - - virtual ~btInternalTriangleIndexCallback(); - virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) = 0; -}; - - - -#endif //TRIANGLE_CALLBACK_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp deleted file mode 100644 index 554915a7058..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* -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. -*/ - -#include "btTriangleIndexVertexArray.h" - -btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride) -{ - btIndexedMesh mesh; - - mesh.m_numTriangles = numTriangles; - mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase; - mesh.m_triangleIndexStride = triangleIndexStride; - mesh.m_numVertices = numVertices; - mesh.m_vertexBase = (const unsigned char *)vertexBase; - mesh.m_vertexStride = vertexStride; - - addIndexedMesh(mesh); - -} - -btTriangleIndexVertexArray::~btTriangleIndexVertexArray() -{ - -} - -void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) -{ - btAssert(subpart< getNumSubParts() ); - - btIndexedMesh& mesh = m_indexedMeshes[subpart]; - - numverts = mesh.m_numVertices; - (*vertexbase) = (unsigned char *) mesh.m_vertexBase; - #ifdef BT_USE_DOUBLE_PRECISION - type = PHY_DOUBLE; - #else - type = PHY_FLOAT; - #endif - vertexStride = mesh.m_vertexStride; - - numfaces = mesh.m_numTriangles; - - (*indexbase) = (unsigned char *)mesh.m_triangleIndexBase; - indexstride = mesh.m_triangleIndexStride; - indicestype = PHY_INTEGER; -} - -void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const -{ - const btIndexedMesh& mesh = m_indexedMeshes[subpart]; - - numverts = mesh.m_numVertices; - (*vertexbase) = (const unsigned char *)mesh.m_vertexBase; - #ifdef BT_USE_DOUBLE_PRECISION - type = PHY_DOUBLE; - #else - type = PHY_FLOAT; - #endif - vertexStride = mesh.m_vertexStride; - - numfaces = mesh.m_numTriangles; - (*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase; - indexstride = mesh.m_triangleIndexStride; - indicestype = PHY_INTEGER; -} - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h deleted file mode 100644 index 3441a8325e2..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -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. -*/ - -#ifndef BT_TRIANGLE_INDEX_VERTEX_ARRAY_H -#define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H - -#include "btStridingMeshInterface.h" -#include "LinearMath/btAlignedObjectArray.h" -#include "LinearMath/btScalar.h" - - -///IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements -///instead of the number of indices, we pass the number of triangles -///todo: explain with pictures -ATTRIBUTE_ALIGNED16( struct) btIndexedMesh -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); - - int m_numTriangles; - const unsigned char * m_triangleIndexBase; - int m_triangleIndexStride; - int m_numVertices; - const unsigned char * m_vertexBase; - int m_vertexStride; - int pad[2]; -} -; - - -typedef btAlignedObjectArray IndexedMeshArray; - -///TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays. -///Additional meshes can be added using addIndexedMesh -///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays. -///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray. -ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface -{ - IndexedMeshArray m_indexedMeshes; - int m_pad[3]; - - -public: - - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btTriangleIndexVertexArray() - { - } - - virtual ~btTriangleIndexVertexArray(); - - //just to be backwards compatible - btTriangleIndexVertexArray(int numTriangleIndices,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride); - - void addIndexedMesh(const btIndexedMesh& mesh) - { - m_indexedMeshes.push_back(mesh); - } - - - virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0); - - virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const; - - /// unLockVertexBase finishes the access to a subpart of the triangle mesh - /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished - virtual void unLockVertexBase(int subpart) {(void)subpart;} - - virtual void unLockReadOnlyVertexBase(int subpart) const {(void)subpart;} - - /// getNumSubParts returns the number of seperate subparts - /// each subpart has a continuous array of vertices and indices - virtual int getNumSubParts() const { - return (int)m_indexedMeshes.size(); - } - - IndexedMeshArray& getIndexedMeshArray() - { - return m_indexedMeshes; - } - - const IndexedMeshArray& getIndexedMeshArray() const - { - return m_indexedMeshes; - } - - virtual void preallocateVertices(int numverts){(void) numverts;} - virtual void preallocateIndices(int numindices){(void) numindices;} - -} -; - -#endif //BT_TRIANGLE_INDEX_VERTEX_ARRAY_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp deleted file mode 100644 index 98c54ef45f8..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* -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. -*/ - -#include "btTriangleMesh.h" -#include - - -btTriangleMesh::btTriangleMesh () -{ - -} - -void btTriangleMesh::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) -{ - (void)subpart; - numverts = m_vertices.size(); - *vertexbase = (unsigned char*)&m_vertices[0]; - type = PHY_FLOAT; - stride = sizeof(btVector3); - - numfaces = m_indices.size()/3; - *indexbase = (unsigned char*) &m_indices[0]; - indicestype = PHY_INTEGER; - indexstride = 3*sizeof(int); - -} - -void btTriangleMesh::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const -{ - (void)subpart; - numverts = m_vertices.size(); - *vertexbase = (unsigned char*)&m_vertices[0]; - type = PHY_FLOAT; - stride = sizeof(btVector3); - - numfaces = m_indices.size()/3; - *indexbase = (unsigned char*) &m_indices[0]; - indicestype = PHY_INTEGER; - indexstride = 3*sizeof(int); - -} - - - -int btTriangleMesh::getNumSubParts() const -{ - return 1; -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h deleted file mode 100644 index 83e5a56d16a..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -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. -*/ - - -#ifndef TRIANGLE_MESH_H -#define TRIANGLE_MESH_H - -#include "btStridingMeshInterface.h" -#include "LinearMath/btVector3.h" -#include "LinearMath/btAlignedObjectArray.h" - -///TriangleMesh provides storage for a concave triangle mesh. It can be used as data for the btTriangleMeshShape. -class btTriangleMesh : public btStridingMeshInterface -{ - btAlignedObjectArray m_vertices; - btAlignedObjectArray m_indices; - - public: - btTriangleMesh (); - - void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2) - { - int curIndex = m_indices.size(); - m_vertices.push_back(vertex0); - m_vertices.push_back(vertex1); - m_vertices.push_back(vertex2); - - m_indices.push_back(curIndex++); - m_indices.push_back(curIndex++); - m_indices.push_back(curIndex++); - } - - int getNumTriangles() const - { - return m_indices.size() / 3; - } - - - -//StridingMeshInterface interface implementation - - virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0); - - virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const; - - /// unLockVertexBase finishes the access to a subpart of the triangle mesh - /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished - virtual void unLockVertexBase(int subpart) {(void) subpart;} - - virtual void unLockReadOnlyVertexBase(int subpart) const { (void) subpart;} - - /// getNumSubParts returns the number of seperate subparts - /// each subpart has a continuous array of vertices and indices - virtual int getNumSubParts() const; - - virtual void preallocateVertices(int numverts){(void) numverts;} - virtual void preallocateIndices(int numindices){(void) numindices;} - - -}; - -#endif //TRIANGLE_MESH_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp deleted file mode 100644 index 0d390c88b68..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* -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. -*/ - -#include "btTriangleMeshShape.h" -#include "LinearMath/btVector3.h" -#include "LinearMath/btQuaternion.h" -#include "btStridingMeshInterface.h" -#include "LinearMath/btAabbUtil2.h" -#include "BulletCollision/CollisionShapes/btCollisionMargin.h" - - -btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface) -: m_meshInterface(meshInterface) -{ - recalcLocalAabb(); -} - - -btTriangleMeshShape::~btTriangleMeshShape() -{ - -} - - - - -void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const -{ - - btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); - btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); - - btMatrix3x3 abs_b = trans.getBasis().absolute(); - - btPoint3 center = trans(localCenter); - - btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); - - aabbMin = center - extent; - aabbMax = center + extent; - - -} - -void btTriangleMeshShape::recalcLocalAabb() -{ - for (int i=0;i<3;i++) - { - btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); - vec[i] = btScalar(1.); - btVector3 tmp = localGetSupportingVertex(vec); - m_localAabbMax[i] = tmp[i]+m_collisionMargin; - vec[i] = btScalar(-1.); - tmp = localGetSupportingVertex(vec); - m_localAabbMin[i] = tmp[i]-m_collisionMargin; - } -} - - - -class SupportVertexCallback : public btTriangleCallback -{ - - btVector3 m_supportVertexLocal; -public: - - btTransform m_worldTrans; - btScalar m_maxDot; - btVector3 m_supportVecLocal; - - SupportVertexCallback(const btVector3& supportVecWorld,const btTransform& trans) - : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), m_worldTrans(trans) ,m_maxDot(btScalar(-1e30)) - - { - m_supportVecLocal = supportVecWorld * m_worldTrans.getBasis(); - } - - virtual void processTriangle( btVector3* triangle,int partId, int triangleIndex) - { - (void)partId; - (void)triangleIndex; - for (int i=0;i<3;i++) - { - btScalar dot = m_supportVecLocal.dot(triangle[i]); - if (dot > m_maxDot) - { - m_maxDot = dot; - m_supportVertexLocal = triangle[i]; - } - } - } - - btVector3 GetSupportVertexWorldSpace() - { - return m_worldTrans(m_supportVertexLocal); - } - - btVector3 GetSupportVertexLocal() - { - return m_supportVertexLocal; - } - -}; - - -void btTriangleMeshShape::setLocalScaling(const btVector3& scaling) -{ - m_meshInterface->setScaling(scaling); - recalcLocalAabb(); -} - -const btVector3& btTriangleMeshShape::getLocalScaling() const -{ - return m_meshInterface->getScaling(); -} - - - - - - -//#define DEBUG_TRIANGLE_MESH - - - -void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const -{ - struct FilteredCallback : public btInternalTriangleIndexCallback - { - btTriangleCallback* m_callback; - btVector3 m_aabbMin; - btVector3 m_aabbMax; - - FilteredCallback(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) - :m_callback(callback), - m_aabbMin(aabbMin), - m_aabbMax(aabbMax) - { - } - - virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) - { - if (TestTriangleAgainstAabb2(&triangle[0],m_aabbMin,m_aabbMax)) - { - //check aabb in triangle-space, before doing this - m_callback->processTriangle(triangle,partId,triangleIndex); - } - - } - - }; - - FilteredCallback filterCallback(callback,aabbMin,aabbMax); - - m_meshInterface->InternalProcessAllTriangles(&filterCallback,aabbMin,aabbMax); -} - - - - - -void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const -{ - (void)mass; - //moving concave objects not supported - btAssert(0); - inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); -} - - -btVector3 btTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const -{ - btVector3 supportVertex; - - btTransform ident; - ident.setIdentity(); - - SupportVertexCallback supportCallback(vec,ident); - - btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - - processAllTriangles(&supportCallback,-aabbMax,aabbMax); - - supportVertex = supportCallback.GetSupportVertexLocal(); - - return supportVertex; -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h deleted file mode 100644 index 6657fc09147..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -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. -*/ - -#ifndef TRIANGLE_MESH_SHAPE_H -#define TRIANGLE_MESH_SHAPE_H - -#include "btConcaveShape.h" -#include "btStridingMeshInterface.h" - - -///Concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead. -class btTriangleMeshShape : public btConcaveShape -{ -protected: - btVector3 m_localAabbMin; - btVector3 m_localAabbMax; - btStridingMeshInterface* m_meshInterface; - - ///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class. - ///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead! - btTriangleMeshShape(btStridingMeshInterface* meshInterface); - -public: - - virtual ~btTriangleMeshShape(); - - virtual btVector3 localGetSupportingVertex(const btVector3& vec) const; - - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const - { - assert(0); - return localGetSupportingVertex(vec); - } - - void recalcLocalAabb(); - - virtual int getShapeType() const - { - return TRIANGLE_MESH_SHAPE_PROXYTYPE; - } - - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - - virtual void setLocalScaling(const btVector3& scaling); - virtual const btVector3& getLocalScaling() const; - - btStridingMeshInterface* getMeshInterface() - { - return m_meshInterface; - } - - const btStridingMeshInterface* getMeshInterface() const - { - return m_meshInterface; - } - - - //debugging - virtual const char* getName()const {return "TRIANGLEMESH";} - - -}; - -#endif //TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h deleted file mode 100644 index 064c64fa6ab..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h +++ /dev/null @@ -1,179 +0,0 @@ -/* -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. -*/ - -#ifndef OBB_TRIANGLE_MINKOWSKI_H -#define OBB_TRIANGLE_MINKOWSKI_H - -#include "btConvexShape.h" -#include "btBoxShape.h" - -class btTriangleShape : public btPolyhedralConvexShape -{ - - -public: - - btVector3 m_vertices1[3]; - - - virtual int getNumVertices() const - { - return 3; - } - - const btVector3& getVertexPtr(int index) const - { - return m_vertices1[index]; - } - virtual void getVertex(int index,btVector3& vert) const - { - vert = m_vertices1[index]; - } - virtual int getShapeType() const - { - return TRIANGLE_SHAPE_PROXYTYPE; - } - - virtual int getNumEdges() const - { - return 3; - } - - virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const - { - getVertex(i,pa); - getVertex((i+1)%3,pb); - } - - - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const - { -// btAssert(0); - getAabbSlow(t,aabbMin,aabbMax); - } - - btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir)const - { - btVector3 dots(dir.dot(m_vertices1[0]), dir.dot(m_vertices1[1]), dir.dot(m_vertices1[2])); - return m_vertices1[dots.maxAxis()]; - - } - - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const - { - for (int i=0;i= -tolerance && dist <= tolerance) - { - //inside check on edge-planes - int i; - for (i=0;i<3;i++) - { - btPoint3 pa,pb; - getEdge(i,pa,pb); - btVector3 edge = pb-pa; - btVector3 edgeNormal = edge.cross(normal); - edgeNormal.normalize(); - btScalar dist = pt.dot( edgeNormal); - btScalar edgeConst = pa.dot(edgeNormal); - dist -= edgeConst; - if (dist < -tolerance) - return false; - } - - return true; - } - - return false; - } - //debugging - virtual const char* getName()const - { - return "Triangle"; - } - - virtual int getNumPreferredPenetrationDirections() const - { - return 2; - } - - virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const - { - calcNormal(penetrationVector); - if (index) - penetrationVector *= btScalar(-1.); - } - - -}; - -#endif //OBB_TRIANGLE_MINKOWSKI_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp deleted file mode 100644 index ef340286cb0..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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. -*/ - -#include "btUniformScalingShape.h" - -btUniformScalingShape::btUniformScalingShape( btConvexShape* convexChildShape,btScalar uniformScalingFactor): -m_childConvexShape(convexChildShape), -m_uniformScalingFactor(uniformScalingFactor) -{ -} - -btUniformScalingShape::~btUniformScalingShape() -{ -} - - -btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const -{ - btVector3 tmpVertex; - tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec); - return tmpVertex*m_uniformScalingFactor; -} - -void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const -{ - m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors); - int i; - for (i=0;ilocalGetSupportingVertex(vec); - return tmpVertex*m_uniformScalingFactor; -} - - -void btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const -{ - - ///this linear upscaling is not realistic, but we don't deal with large mass ratios... - btVector3 tmpInertia; - m_childConvexShape->calculateLocalInertia(mass,tmpInertia); - inertia = tmpInertia * m_uniformScalingFactor; -} - - - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version -void btUniformScalingShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const -{ - m_childConvexShape->getAabb(t,aabbMin,aabbMax); - btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5); - btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor; - - aabbMin = aabbCenter - scaledAabbHalfExtends; - aabbMax = aabbCenter + scaledAabbHalfExtends; - -} - -void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const -{ - m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax); - btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5); - btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor; - - aabbMin = aabbCenter - scaledAabbHalfExtends; - aabbMax = aabbCenter + scaledAabbHalfExtends; -} - -void btUniformScalingShape::setLocalScaling(const btVector3& scaling) -{ - m_childConvexShape->setLocalScaling(scaling); -} - -const btVector3& btUniformScalingShape::getLocalScaling() const -{ - return m_childConvexShape->getLocalScaling(); -} - -void btUniformScalingShape::setMargin(btScalar margin) -{ - m_childConvexShape->setMargin(margin); -} -btScalar btUniformScalingShape::getMargin() const -{ - return m_childConvexShape->getMargin() * m_uniformScalingFactor; -} - -int btUniformScalingShape::getNumPreferredPenetrationDirections() const -{ - return m_childConvexShape->getNumPreferredPenetrationDirections(); -} - -void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const -{ - m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector); -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h deleted file mode 100644 index 3a0ecf021d3..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -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. -*/ - -#ifndef BT_UNIFORM_SCALING_SHAPE_H -#define BT_UNIFORM_SCALING_SHAPE_H - -#include "btConvexShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types - -class btUniformScalingShape : public btConvexShape -{ - btConvexShape* m_childConvexShape; - - btScalar m_uniformScalingFactor; - - public: - - btUniformScalingShape( btConvexShape* convexChildShape, btScalar uniformScalingFactor); - - virtual ~btUniformScalingShape(); - - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; - - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; - - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - - btScalar getUniformScalingFactor() const - { - return m_uniformScalingFactor; - } - - btConvexShape* getChildShape() - { - return m_childConvexShape; - } - - const btConvexShape* getChildShape() const - { - return m_childConvexShape; - } - - virtual const char* getName()const - { - return "UniformScalingShape"; - } - - virtual int getShapeType() const { return UNIFORM_SCALING_SHAPE_PROXYTYPE; } - - - /////////////////////////// - - - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - virtual void setLocalScaling(const btVector3& scaling) ; - virtual const btVector3& getLocalScaling() const ; - - virtual void setMargin(btScalar margin); - virtual btScalar getMargin() const; - - virtual int getNumPreferredPenetrationDirections() const; - - virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const; - - -}; - -#endif //BT_UNIFORM_SCALING_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/Doxyfile b/extern/bullet2/src/BulletCollision/Doxyfile deleted file mode 100644 index 4ecb6acb62f..00000000000 --- a/extern/bullet2/src/BulletCollision/Doxyfile +++ /dev/null @@ -1,746 +0,0 @@ -# Doxyfile 1.2.4 - -# This file describes the settings to be used by doxygen for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# General configuration options -#--------------------------------------------------------------------------- - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. -PROJECT_NAME = "Bullet Continuous Collision Detection Library" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, -# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, -# Polish, Portuguese and Slovene. - -OUTPUT_LANGUAGE = English - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these class will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = NO - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. It is allowed to use relative paths in the argument list. - -STRIP_FROM_PATH = - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a class diagram (in Html and LaTeX) for classes with base or -# super classes. Setting the tag to NO turns the diagrams off. - -CLASS_DIAGRAMS = YES - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower case letters. If set to YES upper case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# users are adviced to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explict @brief command for a brief description. - -JAVADOC_AUTOBRIEF = YES - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# reimplements. - -INHERIT_DOCS = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# The ENABLE_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = . - - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -FILE_PATTERNS = *.h *.cpp *.c - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. - -EXCLUDE_PATTERNS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. - -INPUT_FILTER = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse. - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript and frames is required (for instance Netscape 4.0+ -# or Internet explorer 4.0+). - -GENERATE_TREEVIEW = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimised for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using a WORD or other. -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assigments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. Warning: This feature -# is still experimental and very incomplete. - -GENERATE_XML = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_PREDEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = ../../generic/extern - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -#--------------------------------------------------------------------------- -# Configuration::addtions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES tag can be used to specify one or more tagfiles. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = YES - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to -# YES then doxygen will generate a graph for each documented file showing -# the direct and indirect include dependencies of the file with other -# documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to -# YES then doxygen will generate a graph for each documented header file showing -# the documented files that directly or indirectly include this file - -INCLUDED_BY_GRAPH = YES - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found on the path. - -DOT_PATH = - -# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_WIDTH = 1024 - -# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_HEIGHT = 1024 - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -#--------------------------------------------------------------------------- -# Configuration::addtions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO - -# The CGI_NAME tag should be the name of the CGI script that -# starts the search engine (doxysearch) with the correct parameters. -# A script with this name will be generated by doxygen. - -CGI_NAME = search.cgi - -# The CGI_URL tag should be the absolute URL to the directory where the -# cgi binaries are located. See the documentation of your http daemon for -# details. - -CGI_URL = - -# The DOC_URL tag should be the absolute URL to the directory where the -# documentation is located. If left blank the absolute path to the -# documentation, with file:// prepended to it, will be used. - -DOC_URL = - -# The DOC_ABSPATH tag should be the absolute path to the directory where the -# documentation is located. If left blank the directory on the local machine -# will be used. - -DOC_ABSPATH = - -# The BIN_ABSPATH tag must point to the directory where the doxysearch binary -# is installed. - -BIN_ABSPATH = c:\program files\doxygen\bin - -# The EXT_DOC_PATHS tag can be used to specify one or more paths to -# documentation generated for other projects. This allows doxysearch to search -# the documentation for these projects as well. - -EXT_DOC_PATHS = diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp deleted file mode 100644 index c6a2b396d78..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* -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. -*/ - - -#include "btContinuousConvexCollision.h" -#include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" -#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" -#include "LinearMath/btTransformUtil.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" - -#include "btGjkPairDetector.h" -#include "btPointCollector.h" - - - -btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) -:m_simplexSolver(simplexSolver), -m_penetrationDepthSolver(penetrationDepthSolver), -m_convexA(convexA),m_convexB(convexB) -{ -} - -/// This maximum should not be necessary. It allows for untested/degenerate cases in production code. -/// You don't want your game ever to lock-up. -#define MAX_ITERATIONS 1000 - -bool btContinuousConvexCollision::calcTimeOfImpact( - const btTransform& fromA, - const btTransform& toA, - const btTransform& fromB, - const btTransform& toB, - CastResult& result) -{ - - m_simplexSolver->reset(); - - /// compute linear and angular velocity for this interval, to interpolate - btVector3 linVelA,angVelA,linVelB,angVelB; - btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA); - btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB); - - btScalar boundingRadiusA = m_convexA->getAngularMotionDisc(); - btScalar boundingRadiusB = m_convexB->getAngularMotionDisc(); - - btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB; - - btScalar radius = btScalar(0.001); - - btScalar lambda = btScalar(0.); - btVector3 v(1,0,0); - - int maxIter = MAX_ITERATIONS; - - btVector3 n; - n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - bool hasResult = false; - btVector3 c; - - btScalar lastLambda = lambda; - //btScalar epsilon = btScalar(0.001); - - int numIter = 0; - //first solution, using GJK - - - btTransform identityTrans; - identityTrans.setIdentity(); - - btSphereShape raySphere(btScalar(0.0)); - raySphere.setMargin(btScalar(0.)); - - -// result.drawCoordSystem(sphereTr); - - btPointCollector pointCollector1; - - { - - btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver); - btGjkPairDetector::ClosestPointInput input; - - //we don't use margins during CCD - // gjk.setIgnoreMargin(true); - - input.m_transformA = fromA; - input.m_transformB = fromB; - gjk.getClosestPoints(input,pointCollector1,0); - - hasResult = pointCollector1.m_hasResult; - c = pointCollector1.m_pointInWorld; - } - - if (hasResult) - { - btScalar dist; - dist = pointCollector1.m_distance; - n = pointCollector1.m_normalOnBInWorld; - - - - //not close enough - while (dist > radius) - { - numIter++; - if (numIter > maxIter) - { - return false; //todo: report a failure - } - btScalar dLambda = btScalar(0.); - - btScalar projectedLinearVelocity = (linVelB-linVelA).dot(n); - - //calculate safe moving fraction from distance / (linear+rotational velocity) - - //btScalar clippedDist = GEN_min(angularConservativeRadius,dist); - //btScalar clippedDist = dist; - - - dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); - - lambda = lambda + dLambda; - - if (lambda > btScalar(1.)) - return false; - - if (lambda < btScalar(0.)) - return false; - - - //todo: next check with relative epsilon - if (lambda <= lastLambda) - { - return false; - //n.setValue(0,0,0); - break; - } - lastLambda = lambda; - - - - //interpolate to next lambda - btTransform interpolatedTransA,interpolatedTransB,relativeTrans; - - btTransformUtil::integrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA); - btTransformUtil::integrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB); - relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA); - - result.DebugDraw( lambda ); - - btPointCollector pointCollector; - btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver); - btGjkPairDetector::ClosestPointInput input; - input.m_transformA = interpolatedTransA; - input.m_transformB = interpolatedTransB; - gjk.getClosestPoints(input,pointCollector,0); - if (pointCollector.m_hasResult) - { - if (pointCollector.m_distance < btScalar(0.)) - { - //degenerate ?! - result.m_fraction = lastLambda; - n = pointCollector.m_normalOnBInWorld; - result.m_normal=n;//.setValue(1,1,1);// = n; - return true; - } - c = pointCollector.m_pointInWorld; - n = pointCollector.m_normalOnBInWorld; - dist = pointCollector.m_distance; - } else - { - //?? - return false; - } - - } - - result.m_fraction = lambda; - result.m_normal = n; - return true; - } - - return false; - -/* -//todo: - //if movement away from normal, discard result - btVector3 move = transBLocalTo.getOrigin() - transBLocalFrom.getOrigin(); - if (result.m_fraction < btScalar(1.)) - { - if (move.dot(result.m_normal) <= btScalar(0.)) - { - } - } -*/ - -} - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h deleted file mode 100644 index 28c2b4d6156..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -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. -*/ - - -#ifndef CONTINUOUS_COLLISION_CONVEX_CAST_H -#define CONTINUOUS_COLLISION_CONVEX_CAST_H - -#include "btConvexCast.h" -#include "btSimplexSolverInterface.h" -class btConvexPenetrationDepthSolver; -class btConvexShape; - -/// btContinuousConvexCollision implements angular and linear time of impact for convex objects. -/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis). -/// Algorithm operates in worldspace, in order to keep inbetween motion globally consistent. -/// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops -class btContinuousConvexCollision : public btConvexCast -{ - btSimplexSolverInterface* m_simplexSolver; - btConvexPenetrationDepthSolver* m_penetrationDepthSolver; - const btConvexShape* m_convexA; - const btConvexShape* m_convexB; - - -public: - - btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); - - virtual bool calcTimeOfImpact( - const btTransform& fromA, - const btTransform& toA, - const btTransform& fromB, - const btTransform& toB, - CastResult& result); - - -}; - -#endif //CONTINUOUS_COLLISION_CONVEX_CAST_H - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp deleted file mode 100644 index d2a1310b232..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/* -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. -*/ - -#include "btConvexCast.h" - -btConvexCast::~btConvexCast() -{ -} diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h deleted file mode 100644 index cc80f0aa8da..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -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. -*/ - - -#ifndef CONVEX_CAST_H -#define CONVEX_CAST_H - -#include "LinearMath/btTransform.h" -#include "LinearMath/btVector3.h" -#include "LinearMath/btScalar.h" -class btMinkowskiSumShape; -#include "LinearMath/btIDebugDraw.h" - -/// btConvexCast is an interface for Casting -class btConvexCast -{ -public: - - - virtual ~btConvexCast(); - - ///RayResult stores the closest result - /// alternatively, add a callback method to decide about closest/all results - struct CastResult - { - //virtual bool addRayResult(const btVector3& normal,btScalar fraction) = 0; - - virtual void DebugDraw(btScalar fraction) {(void)fraction;} - virtual void drawCoordSystem(const btTransform& trans) {(void)trans;} - - CastResult() - :m_fraction(btScalar(1e30)), - m_debugDrawer(0) - { - } - - - virtual ~CastResult() {}; - - btVector3 m_normal; - btScalar m_fraction; - btTransform m_hitTransformA; - btTransform m_hitTransformB; - - btIDebugDraw* m_debugDrawer; - - }; - - - /// cast a convex against another convex object - virtual bool calcTimeOfImpact( - const btTransform& fromA, - const btTransform& toA, - const btTransform& fromB, - const btTransform& toB, - CastResult& result) = 0; -}; - -#endif //CONVEX_CAST_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h deleted file mode 100644 index 99690921317..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -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. -*/ - - -#ifndef CONVEX_PENETRATION_DEPTH_H -#define CONVEX_PENETRATION_DEPTH_H - -class btStackAlloc; -class btVector3; -#include "btSimplexSolverInterface.h" -class btConvexShape; -#include "LinearMath/btPoint3.h" -class btTransform; - -///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation. -class btConvexPenetrationDepthSolver -{ -public: - - virtual ~btConvexPenetrationDepthSolver() {}; - virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - const btConvexShape* convexA,const btConvexShape* convexB, - const btTransform& transA,const btTransform& transB, - btVector3& v, btPoint3& pa, btPoint3& pb, - class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc - ) = 0; - - -}; -#endif //CONVEX_PENETRATION_DEPTH_H - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h deleted file mode 100644 index f11c8bd1290..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -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. -*/ - - -#ifndef DISCRETE_COLLISION_DETECTOR1_INTERFACE_H -#define DISCRETE_COLLISION_DETECTOR1_INTERFACE_H -#include "LinearMath/btTransform.h" -#include "LinearMath/btVector3.h" -class btStackAlloc; - -/// This interface is made to be used by an iterative approach to do TimeOfImpact calculations -/// This interface allows to query for closest points and penetration depth between two (convex) objects -/// the closest point is on the second object (B), and the normal points from the surface on B towards A. -/// distance is between closest points on B and closest point on A. So you can calculate closest point on A -/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB -struct btDiscreteCollisionDetectorInterface -{ - - struct Result - { - - virtual ~Result(){} - - ///setShapeIdentifiers provides experimental support for per-triangle material / custom material combiner - virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1)=0; - virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)=0; - }; - - struct ClosestPointInput - { - ClosestPointInput() - :m_maximumDistanceSquared(btScalar(1e30)), - m_stackAlloc(0) - { - } - - btTransform m_transformA; - btTransform m_transformB; - btScalar m_maximumDistanceSquared; - btStackAlloc* m_stackAlloc; - }; - - virtual ~btDiscreteCollisionDetectorInterface() {}; - - // - // give either closest points (distance > 0) or penetration (distance) - // the normal always points from B towards A - // - virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) = 0; - -}; - -struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result -{ - btVector3 m_normalOnSurfaceB; - btVector3 m_closestPointInB; - btScalar m_distance; //negative means penetration ! - - btStorageResult() : m_distance(btScalar(1e30)) - { - - } - virtual ~btStorageResult() {}; - - virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) - { - if (depth < m_distance) - { - m_normalOnSurfaceB = normalOnBInWorld; - m_closestPointInB = pointInWorld; - m_distance = depth; - } - } -}; - -#endif //DISCRETE_COLLISION_DETECTOR_INTERFACE1_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp deleted file mode 100644 index da2a02b9839..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* -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. -*/ - - - -#include "btGjkConvexCast.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" -#include "btGjkPairDetector.h" -#include "btPointCollector.h" - - -btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) -:m_simplexSolver(simplexSolver), -m_convexA(convexA), -m_convexB(convexB) -{ -} - -bool btGjkConvexCast::calcTimeOfImpact( - const btTransform& fromA, - const btTransform& toA, - const btTransform& fromB, - const btTransform& toB, - CastResult& result) -{ - - - btMinkowskiSumShape combi(m_convexA,m_convexB); - btMinkowskiSumShape* convex = &combi; - - btTransform rayFromLocalA; - btTransform rayToLocalA; - - rayFromLocalA = fromA.inverse()* fromB; - rayToLocalA = toA.inverse()* toB; - - - btTransform trA,trB; - trA = btTransform(fromA); - trB = btTransform(fromB); - trA.setOrigin(btPoint3(0,0,0)); - trB.setOrigin(btPoint3(0,0,0)); - - convex->setTransformA(trA); - convex->setTransformB(trB); - - - - - btScalar radius = btScalar(0.01); - - btScalar lambda = btScalar(0.); - btVector3 s = rayFromLocalA.getOrigin(); - btVector3 r = rayToLocalA.getOrigin()-rayFromLocalA.getOrigin(); - btVector3 x = s; - btVector3 n; - n.setValue(0,0,0); - bool hasResult = false; - btVector3 c; - - btScalar lastLambda = lambda; - - //first solution, using GJK - - //no penetration support for now, perhaps pass a pointer when we really want it - btConvexPenetrationDepthSolver* penSolverPtr = 0; - - btTransform identityTrans; - identityTrans.setIdentity(); - - btSphereShape raySphere(btScalar(0.0)); - raySphere.setMargin(btScalar(0.)); - - btTransform sphereTr; - sphereTr.setIdentity(); - sphereTr.setOrigin( rayFromLocalA.getOrigin()); - - result.drawCoordSystem(sphereTr); - { - btPointCollector pointCollector1; - btGjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr); - - btGjkPairDetector::ClosestPointInput input; - input.m_transformA = sphereTr; - input.m_transformB = identityTrans; - gjk.getClosestPoints(input,pointCollector1,0); - - hasResult = pointCollector1.m_hasResult; - c = pointCollector1.m_pointInWorld; - n = pointCollector1.m_normalOnBInWorld; - } - - - - if (hasResult) - { - btScalar dist; - dist = (c-x).length(); - if (dist < radius) - { - //penetration - lastLambda = btScalar(1.); - } - - //not close enough - while (dist > radius) - { - - n = x - c; - btScalar nDotr = n.dot(r); - - if (nDotr >= -(SIMD_EPSILON*SIMD_EPSILON)) - return false; - - lambda = lambda - n.dot(n) / nDotr; - if (lambda <= lastLambda) - break; - - lastLambda = lambda; - - x = s + lambda * r; - - sphereTr.setOrigin( x ); - result.drawCoordSystem(sphereTr); - btPointCollector pointCollector; - btGjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr); - btGjkPairDetector::ClosestPointInput input; - input.m_transformA = sphereTr; - input.m_transformB = identityTrans; - gjk.getClosestPoints(input,pointCollector,0); - if (pointCollector.m_hasResult) - { - if (pointCollector.m_distance < btScalar(0.)) - { - //degeneracy, report a hit - result.m_fraction = lastLambda; - result.m_normal = n; - return true; - } - c = pointCollector.m_pointInWorld; - dist = (c-x).length(); - } else - { - //?? - return false; - } - - } - - if (lastLambda < btScalar(1.)) - { - - result.m_fraction = lastLambda; - result.m_normal = n; - return true; - } - } - - return false; -} - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h deleted file mode 100644 index a977c9e83f7..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -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. -*/ - - - -#ifndef GJK_CONVEX_CAST_H -#define GJK_CONVEX_CAST_H - -#include "BulletCollision/CollisionShapes/btCollisionMargin.h" - -#include "LinearMath/btVector3.h" -#include "btConvexCast.h" -class btConvexShape; -class btMinkowskiSumShape; -#include "btSimplexSolverInterface.h" - -///GjkConvexCast performs a raycast on a convex object using support mapping. -class btGjkConvexCast : public btConvexCast -{ - btSimplexSolverInterface* m_simplexSolver; - const btConvexShape* m_convexA; - const btConvexShape* m_convexB; - -public: - - btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); - - /// cast a convex against another convex object - virtual bool calcTimeOfImpact( - const btTransform& fromA, - const btTransform& toA, - const btTransform& fromB, - const btTransform& toB, - CastResult& result); - -}; - -#endif //GJK_CONVEX_CAST_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp deleted file mode 100644 index f57868be044..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp +++ /dev/null @@ -1,628 +0,0 @@ -/* -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. -*/ - -/* -GJK-EPA collision solver by Nathanael Presson -Nov.2006 -*/ - -#include "btGjkEpa.h" -#include //for memset -#include - -#if defined(DEBUG) || defined (_DEBUG) -#include //for debug printf -#ifdef __SPU__ -#include -#define printf spu_printf -#endif //__SPU__ -#endif - -namespace gjkepa_impl -{ - -// -// Port. typedefs -// - -typedef btScalar F; -typedef bool Z; -typedef int I; -typedef unsigned int U; -typedef unsigned char U1; -typedef unsigned short U2; - -typedef btVector3 Vector3; -typedef btMatrix3x3 Rotation; - -// -// Config -// - -#if 0 -#define BTLOCALSUPPORT localGetSupportingVertexWithoutMargin -#else -#define BTLOCALSUPPORT localGetSupportingVertex -#endif - -// -// Const -// - - -#define cstInf SIMD_INFINITY -#define cstPi SIMD_PI -#define cst2Pi SIMD_2_PI -#define GJK_maxiterations (128) -#define GJK_hashsize (1<<6) -#define GJK_hashmask (GJK_hashsize-1) -#define GJK_insimplex_eps F(0.0001) -#define GJK_sqinsimplex_eps (GJK_insimplex_eps*GJK_insimplex_eps) -#define EPA_maxiterations 256 -#define EPA_inface_eps F(0.01) -#define EPA_accuracy F(0.001) - -// -// Utils -// - -static inline F Abs(F v) { return(v<0?-v:v); } -static inline F Sign(F v) { return(F(v<0?-1:1)); } -template static inline void Swap(T& a,T& b) { T -t(a);a=b;b=t; } -template static inline T Min(const T& a,const T& b) { -return(a static inline T Max(const T& a,const T& b) { -return(a>b?a:b); } -static inline void ClearMemory(void* p,U sz) { memset(p,0,(size_t)sz); -} -#if 0 -template static inline void Raise(const T& object) { -throw(object); } -#else -template static inline void Raise(const T&) {} -#endif - - - -// -// GJK -// -struct GJK - { - struct Mkv - { - Vector3 w; /* Minkowski vertice */ - Vector3 r; /* Ray */ - }; - struct He - { - Vector3 v; - He* n; - }; - btStackAlloc* sa; - btBlock* sablock; - He* table[GJK_hashsize]; - Rotation wrotations[2]; - Vector3 positions[2]; - const btConvexShape* shapes[2]; - Mkv simplex[5]; - Vector3 ray; - U order; - U iterations; - F margin; - Z failed; - // - GJK(btStackAlloc* psa, - const Rotation& wrot0,const Vector3& pos0,const btConvexShape* shape0, - const Rotation& wrot1,const Vector3& pos1,const btConvexShape* shape1, - F pmargin=0) - { - wrotations[0]=wrot0;positions[0]=pos0;shapes[0]=shape0; - wrotations[1]=wrot1;positions[1]=pos1;shapes[1]=shape1; - sa =psa; - sablock =sa->beginBlock(); - margin =pmargin; - failed =false; - } - // - ~GJK() - { - sa->endBlock(sablock); - } - // vdh : very dumm hash - static inline U Hash(const Vector3& v) - { - //this doesn't compile under GCC 3.3.5, so add the ()... - //const U h(U(v[0]*15461)^U(v[1]*83003)^U(v[2]*15473)); - //return(((*((const U*)&h))*169639)&GJK_hashmask); - const U h((U)(v[0]*15461)^(U)(v[1]*83003)^(U)(v[2]*15473)); - return(((*((const U*)&h))*169639)&GJK_hashmask); - } - // - inline Vector3 LocalSupport(const Vector3& d,U i) const - { - return(wrotations[i]*shapes[i]->BTLOCALSUPPORT(d*wrotations[i])+positions[i]); - } - // - inline void Support(const Vector3& d,Mkv& v) const - { - v.r = d; - v.w = LocalSupport(d,0)-LocalSupport(-d,1)+d*margin; - } - #define SPX(_i_) simplex[_i_] - #define SPXW(_i_) simplex[_i_].w - // - inline Z FetchSupport() - { - const U h(Hash(ray)); - He* e = (He*)(table[h]); - while(e) { if(e->v==ray) { --order;return(false); } else e=e->n; } - e=(He*)sa->allocate(sizeof(He));e->v=ray;e->n=table[h];table[h]=e; - Support(ray,simplex[++order]); - return(ray.dot(SPXW(order))>0); - } - // - inline Z SolveSimplex2(const Vector3& ao,const Vector3& ab) - { - if(ab.dot(ao)>=0) - { - const Vector3 cabo(cross(ab,ao)); - if(cabo.length2()>GJK_sqinsimplex_eps) - { ray=cross(cabo,ab); } - else - { return(true); } - } - else - { order=0;SPX(0)=SPX(1);ray=ao; } - return(false); - } - // - inline Z SolveSimplex3(const Vector3& ao,const Vector3& ab,const Vector3& -ac) - { - return(SolveSimplex3a(ao,ab,ac,cross(ab,ac))); - } - // - inline Z SolveSimplex3a(const Vector3& ao,const Vector3& ab,const Vector3& -ac,const Vector3& cabc) - { - if((cross(cabc,ab)).dot(ao)<-GJK_insimplex_eps) - { order=1;SPX(0)=SPX(1);SPX(1)=SPX(2);return(SolveSimplex2(ao,ab)); } - else if((cross(cabc,ac)).dot(ao)>+GJK_insimplex_eps) - { order=1;SPX(1)=SPX(2);return(SolveSimplex2(ao,ac)); } - else - { - const F d(cabc.dot(ao)); - if(Abs(d)>GJK_insimplex_eps) - { - if(d>0) - { ray=cabc; } - else - { ray=-cabc;Swap(SPX(0),SPX(1)); } - return(false); - } else return(true); - } - } - // - inline Z SolveSimplex4(const Vector3& ao,const Vector3& ab,const Vector3& -ac,const Vector3& ad) - { - Vector3 crs; - if((crs=cross(ab,ac)).dot(ao)>GJK_insimplex_eps) - { -order=2;SPX(0)=SPX(1);SPX(1)=SPX(2);SPX(2)=SPX(3);return(SolveSimplex3a(ao,ab,ac,crs)); -} - else if((crs=cross(ac,ad)).dot(ao)>GJK_insimplex_eps) - { order=2;SPX(2)=SPX(3);return(SolveSimplex3a(ao,ac,ad,crs)); } - else if((crs=cross(ad,ab)).dot(ao)>GJK_insimplex_eps) - { -order=2;SPX(1)=SPX(0);SPX(0)=SPX(2);SPX(2)=SPX(3);return(SolveSimplex3a(ao,ad,ab,crs)); -} - else return(true); - } - // - inline Z SearchOrigin(const Vector3& initray=Vector3(1,0,0)) - { - iterations = 0; - order = (U)-1; - failed = false; - ray = initray.normalized(); - ClearMemory(table,sizeof(void*)*GJK_hashsize); - FetchSupport(); - ray = -SPXW(0); - for(;iterations0?rl:1; - if(FetchSupport()) - { - Z found(false); - switch(order) - { - case 1: found=SolveSimplex2(-SPXW(1),SPXW(0)-SPXW(1));break; - case 2: found=SolveSimplex3(-SPXW(2),SPXW(1)-SPXW(2),SPXW(0)-SPXW(2));break; - case 3: found=SolveSimplex4(-SPXW(3),SPXW(2)-SPXW(3),SPXW(1)-SPXW(3),SPXW(0)-SPXW(3));break; - } - if(found) return(true); - } else return(false); - } - failed=true; - return(false); - } - // - inline Z EncloseOrigin() - { - switch(order) - { - /* Point */ - case 0: break; - /* Line */ - case 1: - { - const Vector3 ab(SPXW(1)-SPXW(0)); - const Vector3 b[]={ cross(ab,Vector3(1,0,0)), - cross(ab,Vector3(0,1,0)), - cross(ab,Vector3(0,0,1))}; - const F m[]={b[0].length2(),b[1].length2(),b[2].length2()}; - const Rotation r(btQuaternion(ab.normalized(),cst2Pi/3)); - Vector3 w(b[m[0]>m[1]?m[0]>m[2]?0:2:m[1]>m[2]?1:2]); - Support(w.normalized(),simplex[4]);w=r*w; - Support(w.normalized(),simplex[2]);w=r*w; - Support(w.normalized(),simplex[3]);w=r*w; - order=4; - return(true); - } - break; - /* Triangle */ - case 2: - { - const -Vector3 n(cross((SPXW(1)-SPXW(0)),(SPXW(2)-SPXW(0))).normalized()); - Support( n,simplex[3]); - Support(-n,simplex[4]); - order=4; - return(true); - } - break; - /* Tetrahedron */ - case 3: return(true); - /* Hexahedron */ - case 4: return(true); - } - return(false); - } - #undef SPX - #undef SPXW - }; - -// -// EPA -// -struct EPA - { - // - struct Face - { - const GJK::Mkv* v[3]; - Face* f[3]; - U e[3]; - Vector3 n; - F d; - U mark; - Face* prev; - Face* next; - Face() {} - }; - // - GJK* gjk; - btStackAlloc* sa; - Face* root; - U nfaces; - U iterations; - Vector3 features[2][3]; - Vector3 nearest[2]; - Vector3 normal; - F depth; - Z failed; - // - EPA(GJK* pgjk) - { - gjk = pgjk; - sa = pgjk->sa; - } - // - ~EPA() - { - } - // - inline Vector3 GetCoordinates(const Face* face) const - { - const Vector3 o(face->n*-face->d); - const F a[]={ cross(face->v[0]->w-o,face->v[1]->w-o).length(), - cross(face->v[1]->w-o,face->v[2]->w-o).length(), - cross(face->v[2]->w-o,face->v[0]->w-o).length()}; - const F sm(a[0]+a[1]+a[2]); - return(Vector3(a[1],a[2],a[0])/(sm>0?sm:1)); - } - // - inline Face* FindBest() const - { - Face* bf = 0; - if(root) - { - Face* cf = root; - F bd(cstInf); - do { - if(cf->dd;bf=cf; } - } while(0!=(cf=cf->next)); - } - return(bf); - } - // - inline Z Set(Face* f,const GJK::Mkv* a,const GJK::Mkv* b,const GJK::Mkv* -c) const - { - const Vector3 nrm(cross(b->w-a->w,c->w-a->w)); - const F len(nrm.length()); - const Z valid( (cross(a->w,b->w).dot(nrm)>=-EPA_inface_eps)&& - (cross(b->w,c->w).dot(nrm)>=-EPA_inface_eps)&& - (cross(c->w,a->w).dot(nrm)>=-EPA_inface_eps)); - f->v[0] = a; - f->v[1] = b; - f->v[2] = c; - f->mark = 0; - f->n = nrm/(len>0?len:cstInf); - f->d = Max(0,-f->n.dot(a->w)); - return(valid); - } - // - inline Face* NewFace(const GJK::Mkv* a,const GJK::Mkv* b,const GJK::Mkv* c) - { - Face* pf = (Face*)sa->allocate(sizeof(Face)); - if(Set(pf,a,b,c)) - { - if(root) root->prev=pf; - pf->prev=0; - pf->next=root; - root =pf; - ++nfaces; - } - else - { - pf->prev=pf->next=0; - } - return(pf); - } - // - inline void Detach(Face* face) - { - if(face->prev||face->next) - { - --nfaces; - if(face==root) - { root=face->next;root->prev=0; } - else - { - if(face->next==0) - { face->prev->next=0; } - else - { face->prev->next=face->next;face->next->prev=face->prev; } - } - face->prev=face->next=0; - } - } - // - inline void Link(Face* f0,U e0,Face* f1,U e1) const - { - f0->f[e0]=f1;f1->e[e1]=e0; - f1->f[e1]=f0;f0->e[e0]=e1; - } - // - GJK::Mkv* Support(const Vector3& w) const - { - GJK::Mkv* v =(GJK::Mkv*)sa->allocate(sizeof(GJK::Mkv)); - gjk->Support(w,*v); - return(v); - } - // - U BuildHorizon(U markid,const GJK::Mkv* w,Face& f,U e,Face*& cf,Face*& -ff) - { - static const U mod3[]={0,1,2,0,1}; - U ne(0); - if(f.mark!=markid) - { - const U e1(mod3[e+1]); - if((f.n.dot(w->w)+f.d)>0) - { - Face* nf = NewFace(f.v[e1],f.v[e],w); - Link(nf,0,&f,e); - if(cf) Link(cf,1,nf,2); else ff=nf; - cf=nf;ne=1; - } - else - { - const U e2(mod3[e+2]); - Detach(&f); - f.mark = markid; - ne += BuildHorizon(markid,w,*f.f[e1],f.e[e1],cf,ff); - ne += BuildHorizon(markid,w,*f.f[e2],f.e[e2],cf,ff); - } - } - return(ne); - } - // - inline F EvaluatePD(F accuracy=EPA_accuracy) - { - btBlock* sablock = sa->beginBlock(); - Face* bestface = 0; - U markid(1); - depth = -cstInf; - normal = Vector3(0,0,0); - root = 0; - nfaces = 0; - iterations = 0; - failed = false; - /* Prepare hull */ - if(gjk->EncloseOrigin()) - { - const U* pfidx = 0; - U nfidx= 0; - const U* peidx = 0; - U neidx = 0; - GJK::Mkv* basemkv[5]; - Face* basefaces[6]; - switch(gjk->order) - { - /* Tetrahedron */ - case 3: { - static const U fidx[4][3]={{2,1,0},{3,0,1},{3,1,2},{3,2,0}}; - static const -U eidx[6][4]={{0,0,2,1},{0,1,1,1},{0,2,3,1},{1,0,3,2},{2,0,1,2},{3,0,2,2}}; - pfidx=(const U*)fidx;nfidx=4;peidx=(const U*)eidx;neidx=6; - } break; - /* Hexahedron */ - case 4: { - static const -U fidx[6][3]={{2,0,4},{4,1,2},{1,4,0},{0,3,1},{0,2,3},{1,3,2}}; - static const -U eidx[9][4]={{0,0,4,0},{0,1,2,1},{0,2,1,2},{1,1,5,2},{1,0,2,0},{2,2,3,2},{3,1,5,0},{3,0,4,2},{5,1,4,1}}; - pfidx=(const U*)fidx;nfidx=6;peidx=(const U*)eidx;neidx=9; - } break; - } - U i; - - for( i=0;i<=gjk->order;++i) { -basemkv[i]=(GJK::Mkv*)sa->allocate(sizeof(GJK::Mkv));*basemkv[i]=gjk->simplex[i]; -} - for( i=0;iendBlock(sablock); - return(depth); - } - /* Expand hull */ - for(;iterationsn); - const F d(bf->n.dot(w->w)+bf->d); - bestface = bf; - if(d<-accuracy) - { - Face* cf =0; - Face* ff =0; - U nf = 0; - Detach(bf); - bf->mark=++markid; - for(U i=0;i<3;++i) { -nf+=BuildHorizon(markid,w,*bf->f[i],bf->e[i],cf,ff); } - if(nf<=2) { break; } - Link(cf,1,ff,2); - } else break; - } else break; - } - /* Extract contact */ - if(bestface) - { - const Vector3 b(GetCoordinates(bestface)); - normal = bestface->n; - depth = Max(0,bestface->d); - for(U i=0;i<2;++i) - { - const F s(F(i?-1:1)); - for(U j=0;j<3;++j) - { - features[i][j]=gjk->LocalSupport(s*bestface->v[j]->r,i); - } - } - nearest[0] = features[0][0]*b.x()+features[0][1]*b.y()+features[0][2]*b.z(); - nearest[1] = features[1][0]*b.x()+features[1][1]*b.y()+features[1][2]*b.z(); - } else failed=true; - sa->endBlock(sablock); - return(depth); - } - }; -} - -// -// Api -// - -using namespace gjkepa_impl; - - - -// -bool btGjkEpaSolver::Collide(const btConvexShape *shape0,const btTransform &wtrs0, - const btConvexShape *shape1,const btTransform &wtrs1, - btScalar radialmargin, - btStackAlloc* stackAlloc, - sResults& results) -{ - - -/* Initialize */ -results.witnesses[0] = -results.witnesses[1] = -results.normal = Vector3(0,0,0); -results.depth = 0; -results.status = sResults::Separated; -results.epa_iterations = 0; -results.gjk_iterations = 0; -/* Use GJK to locate origin */ -GJK gjk(stackAlloc, - wtrs0.getBasis(),wtrs0.getOrigin(),shape0, - wtrs1.getBasis(),wtrs1.getOrigin(),shape1, - radialmargin+EPA_accuracy); -const Z collide(gjk.SearchOrigin()); -results.gjk_iterations = gjk.iterations+1; -if(collide) - { - /* Then EPA for penetration depth */ - EPA epa(&gjk); - const F pd(epa.EvaluatePD()); - results.epa_iterations = epa.iterations+1; - if(pd>0) - { - results.status = sResults::Penetrating; - results.normal = epa.normal; - results.depth = pd; - results.witnesses[0] = epa.nearest[0]; - results.witnesses[1] = epa.nearest[1]; - return(true); - } else { if(epa.failed) results.status=sResults::EPA_Failed; } - } else { if(gjk.failed) results.status=sResults::GJK_Failed; } -return(false); -} - - - - - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h deleted file mode 100644 index 1338e2714a8..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -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. -*/ - -/* -GJK-EPA collision solver by Nathanael Presson -Nov.2006 -*/ - - -#ifndef _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ -#define _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ -#include "BulletCollision/CollisionShapes/btConvexShape.h" - -class btStackAlloc; - -///btGjkEpaSolver contributed under zlib by Nathanael Presson -struct btGjkEpaSolver -{ -struct sResults - { - enum eStatus - { - Separated, /* Shapes doesnt penetrate */ - Penetrating, /* Shapes are penetrating */ - GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ - EPA_Failed, /* EPA phase fail, bigger problem, need to save parameters, and debug */ - } status; - btVector3 witnesses[2]; - btVector3 normal; - btScalar depth; - int epa_iterations; - int gjk_iterations; - }; -static bool Collide(const btConvexShape* shape0,const btTransform& wtrs0, - const btConvexShape* shape1,const btTransform& wtrs1, - btScalar radialmargin, - btStackAlloc* stackAlloc, - sResults& results); -}; - -#endif diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp deleted file mode 100644 index 9e600652333..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -EPA Copyright (c) Ricardo Padrela 2006 - -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. -*/ - -#include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "btGjkEpaPenetrationDepthSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" - -bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver, - const btConvexShape* pConvexA, const btConvexShape* pConvexB, - const btTransform& transformA, const btTransform& transformB, - btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, - class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc ) -{ - - (void)debugDraw; - (void)v; - (void)simplexSolver; - - const btScalar radialmargin(btScalar(0.)); - - btGjkEpaSolver::sResults results; - if(btGjkEpaSolver::Collide( pConvexA,transformA, - pConvexB,transformB, - radialmargin,stackAlloc,results)) - { - // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); - //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); - wWitnessOnA = results.witnesses[0]; - wWitnessOnB = results.witnesses[1]; - return true; - } - - return false; -} - - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h deleted file mode 100644 index 2dc069ce5cf..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -EPA Copyright (c) Ricardo Padrela 2006 - -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. -*/ -#ifndef BT_GJP_EPA_PENETRATION_DEPTH_H -#define BT_GJP_EPA_PENETRATION_DEPTH_H - -#include "btConvexPenetrationDepthSolver.h" - -///EpaPenetrationDepthSolver uses the Expanding Polytope Algorithm to -///calculate the penetration depth between two convex shapes. -class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver -{ - public : - - bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - const btConvexShape* pConvexA, const btConvexShape* pConvexB, - const btTransform& transformA, const btTransform& transformB, - btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, - class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc ); - - private : - -}; - -#endif // BT_GJP_EPA_PENETRATION_DEPTH_H - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp deleted file mode 100644 index c5f50d4dd1a..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/* -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. -*/ - -#include "btGjkPairDetector.h" -#include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" -#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" - -#if defined(DEBUG) || defined (_DEBUG) -#include //for debug printf -#ifdef __SPU__ -#include -#define printf spu_printf -#endif //__SPU__ -#endif - -//must be above the machine epsilon -#define REL_ERROR2 btScalar(1.0e-6) - -//temp globals, to improve GJK/EPA/penetration calculations -int gNumDeepPenetrationChecks = 0; -int gNumGjkChecks = 0; - - - -btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) -:m_cachedSeparatingAxis(btScalar(0.),btScalar(0.),btScalar(1.)), -m_penetrationDepthSolver(penetrationDepthSolver), -m_simplexSolver(simplexSolver), -m_minkowskiA(objectA), -m_minkowskiB(objectB), -m_ignoreMargin(false), -m_lastUsedMethod(-1), -m_catchDegeneracies(1) -{ -} - -void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) -{ - btScalar distance=btScalar(0.); - btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.)); - btVector3 pointOnA,pointOnB; - btTransform localTransA = input.m_transformA; - btTransform localTransB = input.m_transformB; - btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5); - localTransA.getOrigin() -= positionOffset; - localTransB.getOrigin() -= positionOffset; - - btScalar marginA = m_minkowskiA->getMargin(); - btScalar marginB = m_minkowskiB->getMargin(); - - gNumGjkChecks++; - - //for CCD we don't use margins - if (m_ignoreMargin) - { - marginA = btScalar(0.); - marginB = btScalar(0.); - } - - m_curIter = 0; - int gGjkMaxIter = 1000;//this is to catch invalid input, perhaps check for #NaN? - m_cachedSeparatingAxis.setValue(0,1,0); - - bool isValid = false; - bool checkSimplex = false; - bool checkPenetration = true; - m_degenerateSimplex = 0; - - m_lastUsedMethod = -1; - - { - btScalar squaredDistance = SIMD_INFINITY; - btScalar delta = btScalar(0.); - - btScalar margin = marginA + marginB; - - - - m_simplexSolver->reset(); - - for ( ; ; ) - //while (true) - { - - btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* input.m_transformA.getBasis(); - btVector3 seperatingAxisInB = m_cachedSeparatingAxis* input.m_transformB.getBasis(); - - btVector3 pInA = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA); - btVector3 qInB = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); - btPoint3 pWorld = localTransA(pInA); - btPoint3 qWorld = localTransB(qInB); - - btVector3 w = pWorld - qWorld; - delta = m_cachedSeparatingAxis.dot(w); - - // potential exit, they don't overlap - if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared)) - { - checkPenetration = false; - break; - } - - //exit 0: the new point is already in the simplex, or we didn't come any closer - if (m_simplexSolver->inSimplex(w)) - { - m_degenerateSimplex = 1; - checkSimplex = true; - break; - } - // are we getting any closer ? - btScalar f0 = squaredDistance - delta; - btScalar f1 = squaredDistance * REL_ERROR2; - - if (f0 <= f1) - { - if (f0 <= btScalar(0.)) - { - m_degenerateSimplex = 2; - } - checkSimplex = true; - break; - } - //add current vertex to simplex - m_simplexSolver->addVertex(w, pWorld, qWorld); - - //calculate the closest point to the origin (update vector v) - if (!m_simplexSolver->closest(m_cachedSeparatingAxis)) - { - m_degenerateSimplex = 3; - checkSimplex = true; - break; - } - - btScalar previousSquaredDistance = squaredDistance; - squaredDistance = m_cachedSeparatingAxis.length2(); - - //redundant m_simplexSolver->compute_points(pointOnA, pointOnB); - - //are we getting any closer ? - if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance) - { - m_simplexSolver->backup_closest(m_cachedSeparatingAxis); - checkSimplex = true; - break; - } - - //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject - if (m_curIter++ > gGjkMaxIter) - { - #if defined(DEBUG) || defined (_DEBUG) - - printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter); - printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n", - m_cachedSeparatingAxis.getX(), - m_cachedSeparatingAxis.getY(), - m_cachedSeparatingAxis.getZ(), - squaredDistance, - m_minkowskiA->getShapeType(), - m_minkowskiB->getShapeType()); - - #endif - break; - - } - - - bool check = (!m_simplexSolver->fullSimplex()); - //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex()); - - if (!check) - { - //do we need this backup_closest here ? - m_simplexSolver->backup_closest(m_cachedSeparatingAxis); - break; - } - } - - if (checkSimplex) - { - m_simplexSolver->compute_points(pointOnA, pointOnB); - normalInB = pointOnA-pointOnB; - btScalar lenSqr = m_cachedSeparatingAxis.length2(); - //valid normal - if (lenSqr < 0.0001) - { - m_degenerateSimplex = 5; - } - if (lenSqr > SIMD_EPSILON*SIMD_EPSILON) - { - btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); - normalInB *= rlen; //normalize - btScalar s = btSqrt(squaredDistance); - - btAssert(s > btScalar(0.0)); - pointOnA -= m_cachedSeparatingAxis * (marginA / s); - pointOnB += m_cachedSeparatingAxis * (marginB / s); - distance = ((btScalar(1.)/rlen) - margin); - isValid = true; - - m_lastUsedMethod = 1; - } else - { - m_lastUsedMethod = 2; - } - } - - bool catchDegeneratePenetrationCase = - (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance+margin) < 0.01)); - - //if (checkPenetration && !isValid) - if (checkPenetration && (!isValid || catchDegeneratePenetrationCase )) - { - //penetration case - - //if there is no way to handle penetrations, bail out - if (m_penetrationDepthSolver) - { - // Penetration depth case. - btVector3 tmpPointOnA,tmpPointOnB; - - gNumDeepPenetrationChecks++; - - bool isValid2 = m_penetrationDepthSolver->calcPenDepth( - *m_simplexSolver, - m_minkowskiA,m_minkowskiB, - localTransA,localTransB, - m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB, - debugDraw,input.m_stackAlloc - ); - - if (isValid2) - { - btVector3 tmpNormalInB = tmpPointOnB-tmpPointOnA; - btScalar lenSqr = tmpNormalInB.length2(); - if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON)) - { - tmpNormalInB /= btSqrt(lenSqr); - btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length(); - //only replace valid penetrations when the result is deeper (check) - if (!isValid || (distance2 < distance)) - { - distance = distance2; - pointOnA = tmpPointOnA; - pointOnB = tmpPointOnB; - normalInB = tmpNormalInB; - isValid = true; - m_lastUsedMethod = 3; - } else - { - - } - } else - { - //isValid = false; - m_lastUsedMethod = 4; - } - } else - { - m_lastUsedMethod = 5; - } - - } - } - } - - if (isValid) - { -#ifdef __SPU__ - //spu_printf("distance\n"); -#endif //__CELLOS_LV2__ - - - output.addContactPoint( - normalInB, - pointOnB+positionOffset, - distance); - //printf("gjk add:%f",distance); - } - - -} - - - - - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h deleted file mode 100644 index 1ec51f74069..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -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. -*/ - - - - -#ifndef GJK_PAIR_DETECTOR_H -#define GJK_PAIR_DETECTOR_H - -#include "btDiscreteCollisionDetectorInterface.h" -#include "LinearMath/btPoint3.h" -#include "BulletCollision/CollisionShapes/btCollisionMargin.h" - -class btConvexShape; -#include "btSimplexSolverInterface.h" -class btConvexPenetrationDepthSolver; - -/// btGjkPairDetector uses GJK to implement the btDiscreteCollisionDetectorInterface -class btGjkPairDetector : public btDiscreteCollisionDetectorInterface -{ - - - btVector3 m_cachedSeparatingAxis; - btConvexPenetrationDepthSolver* m_penetrationDepthSolver; - btSimplexSolverInterface* m_simplexSolver; - const btConvexShape* m_minkowskiA; - const btConvexShape* m_minkowskiB; - bool m_ignoreMargin; - - -public: - - //some debugging to fix degeneracy problems - int m_lastUsedMethod; - int m_curIter; - int m_degenerateSimplex; - int m_catchDegeneracies; - - - btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); - virtual ~btGjkPairDetector() {}; - - virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw); - - void setMinkowskiA(btConvexShape* minkA) - { - m_minkowskiA = minkA; - } - - void setMinkowskiB(btConvexShape* minkB) - { - m_minkowskiB = minkB; - } - void setCachedSeperatingAxis(const btVector3& seperatingAxis) - { - m_cachedSeparatingAxis = seperatingAxis; - } - - void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver) - { - m_penetrationDepthSolver = penetrationDepthSolver; - } - - ///don't use setIgnoreMargin, it's for Bullet's internal use - void setIgnoreMargin(bool ignoreMargin) - { - m_ignoreMargin = ignoreMargin; - } - - -}; - -#endif //GJK_PAIR_DETECTOR_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h deleted file mode 100644 index 1933d378f4f..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -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. -*/ - -#ifndef MANIFOLD_CONTACT_POINT_H -#define MANIFOLD_CONTACT_POINT_H - -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransformUtil.h" - - - - - -/// ManifoldContactPoint collects and maintains persistent contactpoints. -/// used to improve stability and performance of rigidbody dynamics response. -class btManifoldPoint - { - public: - btManifoldPoint() - :m_userPersistentData(0), - m_lifeTime(0) - { - } - - btManifoldPoint( const btVector3 &pointA, const btVector3 &pointB, - const btVector3 &normal, - btScalar distance ) : - m_localPointA( pointA ), - m_localPointB( pointB ), - m_normalWorldOnB( normal ), - m_distance1( distance ), - m_combinedFriction(btScalar(0.)), - m_combinedRestitution(btScalar(0.)), - m_userPersistentData(0), - m_lifeTime(0) - { - - - } - - - - btVector3 m_localPointA; - btVector3 m_localPointB; - btVector3 m_positionWorldOnB; - ///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity - btVector3 m_positionWorldOnA; - btVector3 m_normalWorldOnB; - - btScalar m_distance1; - btScalar m_combinedFriction; - btScalar m_combinedRestitution; - - - mutable void* m_userPersistentData; - - int m_lifeTime;//lifetime of the contactpoint in frames - - btScalar getDistance() const - { - return m_distance1; - } - int getLifeTime() const - { - return m_lifeTime; - } - - const btVector3& getPositionWorldOnA() const { - return m_positionWorldOnA; -// return m_positionWorldOnB + m_normalWorldOnB * m_distance1; - } - - const btVector3& getPositionWorldOnB() const - { - return m_positionWorldOnB; - } - - void setDistance(btScalar dist) - { - m_distance1 = dist; - } - - - - }; - -#endif //MANIFOLD_CONTACT_POINT_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp deleted file mode 100644 index 100bc240764..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* -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. -*/ - -#include "btMinkowskiPenetrationDepthSolver.h" -#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" -#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" -#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" - - - - -#define NUM_UNITSPHERE_POINTS 42 -static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = -{ -btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), -btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), -btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), -btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), -btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), -btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), -btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), -btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), -btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), -btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), -btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), -btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), -btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), -btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), -btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), -btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), -btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), -btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), -btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), -btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), -btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), -btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), -btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), -btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), -btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), -btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), -btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), -btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), -btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), -btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), -btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), -btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), -btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), -btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), -btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), -btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), -btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), -btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), -btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), -btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), -btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), -btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) -}; - - -bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver, - const btConvexShape* convexA,const btConvexShape* convexB, - const btTransform& transA,const btTransform& transB, - btVector3& v, btPoint3& pa, btPoint3& pb, - class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc - ) -{ - - (void)stackAlloc; - (void)v; - - - struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result - { - - btIntermediateResult():m_hasResult(false) - { - } - - btVector3 m_normalOnBInWorld; - btVector3 m_pointInWorld; - btScalar m_depth; - bool m_hasResult; - - virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1) - { - (void)partId0; - (void)index0; - (void)partId1; - (void)index1; - } - void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) - { - m_normalOnBInWorld = normalOnBInWorld; - m_pointInWorld = pointInWorld; - m_depth = depth; - m_hasResult = true; - } - }; - - //just take fixed number of orientation, and sample the penetration depth in that direction - btScalar minProj = btScalar(1e30); - btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.)); - btVector3 minA,minB; - btVector3 seperatingAxisInA,seperatingAxisInB; - btVector3 pInA,qInB,pWorld,qWorld,w; - -#define USE_BATCHED_SUPPORT 1 -#ifdef USE_BATCHED_SUPPORT - - btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; - btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; - btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; - btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; - int i; - - int numSampleDirections = NUM_UNITSPHERE_POINTS; - - for (i=0;igetNumPreferredPenetrationDirections(); - if (numPDA) - { - for (int i=0;igetPreferredPenetrationDirection(i,norm); - norm = transA.getBasis() * norm; - sPenetrationDirections[numSampleDirections] = norm; - seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); - seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); - numSampleDirections++; - } - } - } - - { - int numPDB = convexB->getNumPreferredPenetrationDirections(); - if (numPDB) - { - for (int i=0;igetPreferredPenetrationDirection(i,norm); - norm = transB.getBasis() * norm; - sPenetrationDirections[numSampleDirections] = norm; - seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); - seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); - numSampleDirections++; - } - } - } - - - - convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections); - convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections); - - for (i=0;igetNumPreferredPenetrationDirections(); - if (numPDA) - { - for (int i=0;igetPreferredPenetrationDirection(i,norm); - norm = transA.getBasis() * norm; - sPenetrationDirections[numSampleDirections] = norm; - numSampleDirections++; - } - } - } - - { - int numPDB = convexB->getNumPreferredPenetrationDirections(); - if (numPDB) - { - for (int i=0;igetPreferredPenetrationDirection(i,norm); - norm = transB.getBasis() * norm; - sPenetrationDirections[numSampleDirections] = norm; - numSampleDirections++; - } - } - } - - for (int i=0;ilocalGetSupportingVertexWithoutMargin(seperatingAxisInA); - qInB = convexB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); - pWorld = transA(pInA); - qWorld = transB(qInB); - w = qWorld - pWorld; - btScalar delta = norm.dot(w); - //find smallest delta - if (delta < minProj) - { - minProj = delta; - minNorm = norm; - minA = pWorld; - minB = qWorld; - } - } -#endif //USE_BATCHED_SUPPORT - - //add the margins - - minA += minNorm*convexA->getMargin(); - minB -= minNorm*convexB->getMargin(); - //no penetration - if (minProj < btScalar(0.)) - return false; - - minProj += (convexA->getMargin() + convexB->getMargin()); - - - - - -//#define DEBUG_DRAW 1 -#ifdef DEBUG_DRAW - if (debugDraw) - { - btVector3 color(0,1,0); - debugDraw->drawLine(minA,minB,color); - color = btVector3 (1,1,1); - btVector3 vec = minB-minA; - btScalar prj2 = minNorm.dot(vec); - debugDraw->drawLine(minA,minA+(minNorm*minProj),color); - - } -#endif //DEBUG_DRAW - - - - btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0); - - btScalar offsetDist = minProj; - btVector3 offset = minNorm * offsetDist; - - - - btGjkPairDetector::ClosestPointInput input; - - btVector3 newOrg = transA.getOrigin() + offset; - - btTransform displacedTrans = transA; - displacedTrans.setOrigin(newOrg); - - input.m_transformA = displacedTrans; - input.m_transformB = transB; - input.m_maximumDistanceSquared = btScalar(1e30);//minProj; - - btIntermediateResult res; - gjkdet.getClosestPoints(input,res,debugDraw); - - btScalar correctedMinNorm = minProj - res.m_depth; - - - //the penetration depth is over-estimated, relax it - btScalar penetration_relaxation= btScalar(1.); - minNorm*=penetration_relaxation; - - if (res.m_hasResult) - { - - pa = res.m_pointInWorld - minNorm * correctedMinNorm; - pb = res.m_pointInWorld; - -#ifdef DEBUG_DRAW - if (debugDraw) - { - btVector3 color(1,0,0); - debugDraw->drawLine(pa,pb,color); - } -#endif//DEBUG_DRAW - - - } - return res.m_hasResult; -} - - - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h deleted file mode 100644 index 27b42c2b47e..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -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. -*/ - -#ifndef MINKOWSKI_PENETRATION_DEPTH_SOLVER_H -#define MINKOWSKI_PENETRATION_DEPTH_SOLVER_H - -#include "btConvexPenetrationDepthSolver.h" - -///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation. -///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points. -class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver -{ -public: - - virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - const btConvexShape* convexA,const btConvexShape* convexB, - const btTransform& transA,const btTransform& transB, - btVector3& v, btPoint3& pa, btPoint3& pb, - class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc - ); - -}; - -#endif //MINKOWSKI_PENETRATION_DEPTH_SOLVER_H - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp deleted file mode 100644 index ee94ee01149..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* -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. -*/ - - -#include "btPersistentManifold.h" -#include "LinearMath/btTransform.h" -#include - -btScalar gContactBreakingThreshold = btScalar(0.02); -ContactDestroyedCallback gContactDestroyedCallback = 0; - - - -btPersistentManifold::btPersistentManifold() -:m_body0(0), -m_body1(0), -m_cachedPoints (0), -m_index1a(0) -{ -} - - - - -#ifdef DEBUG_PERSISTENCY -#include -void btPersistentManifold::DebugPersistency() -{ - int i; - printf("DebugPersistency : numPoints %d\n",m_cachedPoints); - for (i=0;i1) - printf("error in clearUserCache\n"); - } - } - assert(occurance<=0); -#endif //DEBUG_PERSISTENCY - - if (pt.m_userPersistentData && gContactDestroyedCallback) - { - (*gContactDestroyedCallback)(pt.m_userPersistentData); - pt.m_userPersistentData = 0; - } - -#ifdef DEBUG_PERSISTENCY - DebugPersistency(); -#endif - } - - -} - - -int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt) -{ - - //calculate 4 possible cases areas, and take biggest area - //also need to keep 'deepest' - - int maxPenetrationIndex = -1; -#define KEEP_DEEPEST_POINT 1 -#ifdef KEEP_DEEPEST_POINT - btScalar maxPenetration = pt.getDistance(); - for (int i=0;i<4;i++) - { - if (m_pointCache[i].getDistance() < maxPenetration) - { - maxPenetrationIndex = i; - maxPenetration = m_pointCache[i].getDistance(); - } - } -#endif //KEEP_DEEPEST_POINT - - btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.)); - if (maxPenetrationIndex != 0) - { - btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA; - btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA; - btVector3 cross = a0.cross(b0); - res0 = cross.length2(); - } - if (maxPenetrationIndex != 1) - { - btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA; - btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA; - btVector3 cross = a1.cross(b1); - res1 = cross.length2(); - } - - if (maxPenetrationIndex != 2) - { - btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA; - btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA; - btVector3 cross = a2.cross(b2); - res2 = cross.length2(); - } - - if (maxPenetrationIndex != 3) - { - btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA; - btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA; - btVector3 cross = a3.cross(b3); - res3 = cross.length2(); - } - - btVector4 maxvec(res0,res1,res2,res3); - int biggestarea = maxvec.closestAxis4(); - return biggestarea; -} - - -int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const -{ - btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold(); - int size = getNumContacts(); - int nearestPoint = -1; - for( int i = 0; i < size; i++ ) - { - const btManifoldPoint &mp = m_pointCache[i]; - - btVector3 diffA = mp.m_localPointA- newPoint.m_localPointA; - const btScalar distToManiPoint = diffA.dot(diffA); - if( distToManiPoint < shortestDist ) - { - shortestDist = distToManiPoint; - nearestPoint = i; - } - } - return nearestPoint; -} - -void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint) -{ - assert(validContactDistance(newPoint)); - - int insertIndex = getNumContacts(); - if (insertIndex == MANIFOLD_CACHE_SIZE) - { -#if MANIFOLD_CACHE_SIZE >= 4 - //sort cache so best points come first, based on area - insertIndex = sortCachedPoints(newPoint); -#else - insertIndex = 0; -#endif - - - } else - { - m_cachedPoints++; - - - } - replaceContactPoint(newPoint,insertIndex); -} - -btScalar btPersistentManifold::getContactBreakingThreshold() const -{ - return gContactBreakingThreshold; -} - - - -void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB) -{ - int i; -#ifdef DEBUG_PERSISTENCY - printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n", - trA.getOrigin().getX(), - trA.getOrigin().getY(), - trA.getOrigin().getZ(), - trB.getOrigin().getX(), - trB.getOrigin().getY(), - trB.getOrigin().getZ()); -#endif //DEBUG_PERSISTENCY - /// first refresh worldspace positions and distance - for (i=getNumContacts()-1;i>=0;i--) - { - btManifoldPoint &manifoldPoint = m_pointCache[i]; - manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA ); - manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB ); - manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB); - manifoldPoint.m_lifeTime++; - } - - /// then - btScalar distance2d; - btVector3 projectedDifference,projectedPoint; - for (i=getNumContacts()-1;i>=0;i--) - { - - btManifoldPoint &manifoldPoint = m_pointCache[i]; - //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction) - if (!validContactDistance(manifoldPoint)) - { - removeContactPoint(i); - } else - { - //contact also becomes invalid when relative movement orthogonal to normal exceeds margin - projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1; - projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint; - distance2d = projectedDifference.dot(projectedDifference); - if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() ) - { - removeContactPoint(i); - } - } - } -#ifdef DEBUG_PERSISTENCY - DebugPersistency(); -#endif // -} - - - - - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h deleted file mode 100644 index f0b1ce58db7..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h +++ /dev/null @@ -1,179 +0,0 @@ -/* -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. -*/ - -#ifndef PERSISTENT_MANIFOLD_H -#define PERSISTENT_MANIFOLD_H - - -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransform.h" -#include "btManifoldPoint.h" -#include "LinearMath/btAlignedAllocator.h" - -struct btCollisionResult; - -///contact breaking and merging threshold -extern btScalar gContactBreakingThreshold; - -typedef bool (*ContactDestroyedCallback)(void* userPersistentData); -extern ContactDestroyedCallback gContactDestroyedCallback; - - - - -#define MANIFOLD_CACHE_SIZE 4 - -///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase. -///Those contact points are created by the collision narrow phase. -///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time. -///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large) -///reduces the cache to 4 points, when more then 4 points are added, using following rules: -///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points -///note that some pairs of objects might have more then one contact manifold. -ATTRIBUTE_ALIGNED16( class) btPersistentManifold -{ - - btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE]; - - /// this two body pointers can point to the physics rigidbody class. - /// void* will allow any rigidbody class - void* m_body0; - void* m_body1; - int m_cachedPoints; - - - /// sort cached points so most isolated points come first - int sortCachedPoints(const btManifoldPoint& pt); - - int findContactPoint(const btManifoldPoint* unUsed, int numUnused,const btManifoldPoint& pt); - -public: - - BT_DECLARE_ALIGNED_ALLOCATOR(); - - int m_index1a; - - btPersistentManifold(); - - btPersistentManifold(void* body0,void* body1,int bla) - : m_body0(body0),m_body1(body1),m_cachedPoints(0) - { - } - - SIMD_FORCE_INLINE void* getBody0() { return m_body0;} - SIMD_FORCE_INLINE void* getBody1() { return m_body1;} - - SIMD_FORCE_INLINE const void* getBody0() const { return m_body0;} - SIMD_FORCE_INLINE const void* getBody1() const { return m_body1;} - - void setBodies(void* body0,void* body1) - { - m_body0 = body0; - m_body1 = body1; - } - - void clearUserCache(btManifoldPoint& pt); - -#ifdef DEBUG_PERSISTENCY - void DebugPersistency(); -#endif // - - SIMD_FORCE_INLINE int getNumContacts() const { return m_cachedPoints;} - - SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const - { - btAssert(index < m_cachedPoints); - return m_pointCache[index]; - } - - SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index) - { - btAssert(index < m_cachedPoints); - return m_pointCache[index]; - } - - /// todo: get this margin from the current physics / collision environment - btScalar getContactBreakingThreshold() const; - - int getCacheEntry(const btManifoldPoint& newPoint) const; - - void AddManifoldPoint( const btManifoldPoint& newPoint); - - void removeContactPoint (int index) - { - clearUserCache(m_pointCache[index]); - - int lastUsedIndex = getNumContacts() - 1; -// m_pointCache[index] = m_pointCache[lastUsedIndex]; - if(index != lastUsedIndex) - { - m_pointCache[index] = m_pointCache[lastUsedIndex]; - //get rid of duplicated userPersistentData pointer - m_pointCache[lastUsedIndex].m_userPersistentData = 0; - m_pointCache[lastUsedIndex].m_lifeTime = 0; - } - - btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0); - m_cachedPoints--; - } - void replaceContactPoint(const btManifoldPoint& newPoint,int insertIndex) - { - btAssert(validContactDistance(newPoint)); - -#define MAINTAIN_PERSISTENCY 1 -#ifdef MAINTAIN_PERSISTENCY - int lifeTime = m_pointCache[insertIndex].getLifeTime(); - btAssert(lifeTime>=0); - void* cache = m_pointCache[insertIndex].m_userPersistentData; - - m_pointCache[insertIndex] = newPoint; - - m_pointCache[insertIndex].m_userPersistentData = cache; - m_pointCache[insertIndex].m_lifeTime = lifeTime; -#else - clearUserCache(m_pointCache[insertIndex]); - m_pointCache[insertIndex] = newPoint; - -#endif - } - - bool validContactDistance(const btManifoldPoint& pt) const - { - return pt.m_distance1 <= getContactBreakingThreshold(); - } - /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin - void refreshContactPoints( const btTransform& trA,const btTransform& trB); - - - SIMD_FORCE_INLINE void clearManifold() - { - int i; - for (i=0;i= btScalar(0.0) ) - { - return ; // same sign - } - - const btScalar proj_length=dist_a-dist_b; - const btScalar distance = (dist_a)/(proj_length); - // Now we have the intersection point on the plane, we'll see if it's inside the triangle - // Add an epsilon as a tolerance for the raycast, - // in case the ray hits exacly on the edge of the triangle. - // It must be scaled for the triangle size. - - if(distance < m_hitFraction) - { - - - btScalar edge_tolerance =triangleNormal.length2(); - edge_tolerance *= btScalar(-0.0001); - btVector3 point; point.setInterpolate3( m_from, m_to, distance); - { - btVector3 v0p; v0p = vert0 - point; - btVector3 v1p; v1p = vert1 - point; - btVector3 cp0; cp0 = v0p.cross( v1p ); - - if ( (btScalar)(cp0.dot(triangleNormal)) >=edge_tolerance) - { - - - btVector3 v2p; v2p = vert2 - point; - btVector3 cp1; - cp1 = v1p.cross( v2p); - if ( (btScalar)(cp1.dot(triangleNormal)) >=edge_tolerance) - { - btVector3 cp2; - cp2 = v2p.cross(v0p); - - if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) - { - - if ( dist_a > 0 ) - { - m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex); - } - else - { - m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex); - } - } - } - } - } - } -} diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h deleted file mode 100644 index 87490a345a2..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -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. -*/ - -#ifndef RAYCAST_TRI_CALLBACK_H -#define RAYCAST_TRI_CALLBACK_H - -#include "BulletCollision/CollisionShapes/btTriangleCallback.h" -struct btBroadphaseProxy; - - -class btTriangleRaycastCallback: public btTriangleCallback -{ -public: - - //input - btVector3 m_from; - btVector3 m_to; - - btScalar m_hitFraction; - - btTriangleRaycastCallback(const btVector3& from,const btVector3& to); - - virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); - - virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) = 0; - -}; - -#endif //RAYCAST_TRI_CALLBACK_H - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h deleted file mode 100644 index cf65f46505b..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -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. -*/ - - - -#ifndef SIMPLEX_SOLVER_INTERFACE_H -#define SIMPLEX_SOLVER_INTERFACE_H - -#include "LinearMath/btVector3.h" -#include "LinearMath/btPoint3.h" - -#define NO_VIRTUAL_INTERFACE 1 -#ifdef NO_VIRTUAL_INTERFACE -#include "btVoronoiSimplexSolver.h" -#define btSimplexSolverInterface btVoronoiSimplexSolver -#else - -/// btSimplexSolverInterface can incrementally calculate distance between origin and up to 4 vertices -/// Used by GJK or Linear Casting. Can be implemented by the Johnson-algorithm or alternative approaches based on -/// voronoi regions or barycentric coordinates -class btSimplexSolverInterface -{ - public: - virtual ~btSimplexSolverInterface() {}; - - virtual void reset() = 0; - - virtual void addVertex(const btVector3& w, const btPoint3& p, const btPoint3& q) = 0; - - virtual bool closest(btVector3& v) = 0; - - virtual btScalar maxVertex() = 0; - - virtual bool fullSimplex() const = 0; - - virtual int getSimplex(btPoint3 *pBuf, btPoint3 *qBuf, btVector3 *yBuf) const = 0; - - virtual bool inSimplex(const btVector3& w) = 0; - - virtual void backup_closest(btVector3& v) = 0; - - virtual bool emptySimplex() const = 0; - - virtual void compute_points(btPoint3& p1, btPoint3& p2) = 0; - - virtual int numVertices() const =0; - - -}; -#endif -#endif //SIMPLEX_SOLVER_INTERFACE_H - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp deleted file mode 100644 index 687738b7fa9..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* -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. -*/ - - -#include "btSubSimplexConvexCast.h" -#include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" -#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" - - -btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) -:m_simplexSolver(simplexSolver), -m_convexA(convexA),m_convexB(convexB) -{ -} - -///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases. -///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565 -#ifdef BT_USE_DOUBLE_PRECISION -#define MAX_ITERATIONS 64 -#else -#define MAX_ITERATIONS 32 -#endif -bool btSubsimplexConvexCast::calcTimeOfImpact( - const btTransform& fromA, - const btTransform& toA, - const btTransform& fromB, - const btTransform& toB, - CastResult& result) -{ - - btMinkowskiSumShape combi(m_convexA,m_convexB); - btMinkowskiSumShape* convex = &combi; - - btTransform rayFromLocalA; - btTransform rayToLocalA; - - rayFromLocalA = fromA.inverse()* fromB; - rayToLocalA = toA.inverse()* toB; - - - m_simplexSolver->reset(); - - convex->setTransformB(btTransform(rayFromLocalA.getBasis())); - - //btScalar radius = btScalar(0.01); - - btScalar lambda = btScalar(0.); - //todo: need to verify this: - //because of minkowski difference, we need the inverse direction - - btVector3 s = -rayFromLocalA.getOrigin(); - btVector3 r = -(rayToLocalA.getOrigin()-rayFromLocalA.getOrigin()); - btVector3 x = s; - btVector3 v; - btVector3 arbitraryPoint = convex->localGetSupportingVertex(r); - - v = x - arbitraryPoint; - - int maxIter = MAX_ITERATIONS; - - btVector3 n; - n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - bool hasResult = false; - btVector3 c; - - btScalar lastLambda = lambda; - - - btScalar dist2 = v.length2(); -#ifdef BT_USE_DOUBLE_PRECISION - btScalar epsilon = btScalar(0.0001); -#else - btScalar epsilon = btScalar(0.0001); -#endif //BT_USE_DOUBLE_PRECISION - btVector3 w,p; - btScalar VdotR; - - while ( (dist2 > epsilon) && maxIter--) - { - p = convex->localGetSupportingVertex( v); - w = x - p; - - btScalar VdotW = v.dot(w); - - if ( VdotW > btScalar(0.)) - { - VdotR = v.dot(r); - - if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON)) - return false; - else - { - lambda = lambda - VdotW / VdotR; - x = s + lambda * r; - m_simplexSolver->reset(); - //check next line - w = x-p; - lastLambda = lambda; - n = v; - hasResult = true; - } - } - m_simplexSolver->addVertex( w, x , p); - if (m_simplexSolver->closest(v)) - { - dist2 = v.length2(); - hasResult = true; - //printf("V=%f , %f, %f\n",v[0],v[1],v[2]); - //printf("DIST2=%f\n",dist2); - //printf("numverts = %i\n",m_simplexSolver->numVertices()); - } else - { - dist2 = btScalar(0.); - } - } - - //int numiter = MAX_ITERATIONS - maxIter; -// printf("number of iterations: %d", numiter); - result.m_fraction = lambda; - result.m_normal = n; - - return true; -} - - - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h deleted file mode 100644 index 05662db5d23..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -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. -*/ - - -#ifndef SUBSIMPLEX_CONVEX_CAST_H -#define SUBSIMPLEX_CONVEX_CAST_H - -#include "btConvexCast.h" -#include "btSimplexSolverInterface.h" -class btConvexShape; - -/// btSubsimplexConvexCast implements Gino van den Bergens' paper -///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection" -/// GJK based Ray Cast, optimized version -/// Objects should not start in overlap, otherwise results are not defined. -class btSubsimplexConvexCast : public btConvexCast -{ - btSimplexSolverInterface* m_simplexSolver; - const btConvexShape* m_convexA; - const btConvexShape* m_convexB; - -public: - - btSubsimplexConvexCast (const btConvexShape* shapeA,const btConvexShape* shapeB,btSimplexSolverInterface* simplexSolver); - - //virtual ~btSubsimplexConvexCast(); - ///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects. - ///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector. - virtual bool calcTimeOfImpact( - const btTransform& fromA, - const btTransform& toA, - const btTransform& fromB, - const btTransform& toB, - CastResult& result); - -}; - -#endif //SUBSIMPLEX_CONVEX_CAST_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp deleted file mode 100644 index 105b7eccefa..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp +++ /dev/null @@ -1,607 +0,0 @@ - -/* -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. - - Elsevier CDROM license agreements grants nonexclusive license to use the software - for any purpose, commercial or non-commercial as long as the following credit is included - identifying the original source of the software: - - Parts of the source are "from the book Real-Time Collision Detection by - Christer Ericson, published by Morgan Kaufmann Publishers, - (c) 2005 Elsevier Inc." - -*/ - - -#include "btVoronoiSimplexSolver.h" -#include -#include - -#define VERTA 0 -#define VERTB 1 -#define VERTC 2 -#define VERTD 3 - -#define CATCH_DEGENERATE_TETRAHEDRON 1 -void btVoronoiSimplexSolver::removeVertex(int index) -{ - - assert(m_numVertices>0); - m_numVertices--; - m_simplexVectorW[index] = m_simplexVectorW[m_numVertices]; - m_simplexPointsP[index] = m_simplexPointsP[m_numVertices]; - m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices]; -} - -void btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts) -{ - if ((numVertices() >= 4) && (!usedVerts.usedVertexD)) - removeVertex(3); - - if ((numVertices() >= 3) && (!usedVerts.usedVertexC)) - removeVertex(2); - - if ((numVertices() >= 2) && (!usedVerts.usedVertexB)) - removeVertex(1); - - if ((numVertices() >= 1) && (!usedVerts.usedVertexA)) - removeVertex(0); - -} - - - - - -//clear the simplex, remove all the vertices -void btVoronoiSimplexSolver::reset() -{ - m_cachedValidClosest = false; - m_numVertices = 0; - m_needsUpdate = true; - m_lastW = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - m_cachedBC.reset(); -} - - - - //add a vertex -void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btPoint3& p, const btPoint3& q) -{ - m_lastW = w; - m_needsUpdate = true; - - m_simplexVectorW[m_numVertices] = w; - m_simplexPointsP[m_numVertices] = p; - m_simplexPointsQ[m_numVertices] = q; - - m_numVertices++; -} - -bool btVoronoiSimplexSolver::updateClosestVectorAndPoints() -{ - - if (m_needsUpdate) - { - m_cachedBC.reset(); - - m_needsUpdate = false; - - switch (numVertices()) - { - case 0: - m_cachedValidClosest = false; - break; - case 1: - { - m_cachedP1 = m_simplexPointsP[0]; - m_cachedP2 = m_simplexPointsQ[0]; - m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0] - m_cachedBC.reset(); - m_cachedBC.setBarycentricCoordinates(btScalar(1.),btScalar(0.),btScalar(0.),btScalar(0.)); - m_cachedValidClosest = m_cachedBC.isValid(); - break; - }; - case 2: - { - //closest point origin from line segment - const btVector3& from = m_simplexVectorW[0]; - const btVector3& to = m_simplexVectorW[1]; - btVector3 nearest; - - btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); - btVector3 diff = p - from; - btVector3 v = to - from; - btScalar t = v.dot(diff); - - if (t > 0) { - btScalar dotVV = v.dot(v); - if (t < dotVV) { - t /= dotVV; - diff -= t*v; - m_cachedBC.m_usedVertices.usedVertexA = true; - m_cachedBC.m_usedVertices.usedVertexB = true; - } else { - t = 1; - diff -= v; - //reduce to 1 point - m_cachedBC.m_usedVertices.usedVertexB = true; - } - } else - { - t = 0; - //reduce to 1 point - m_cachedBC.m_usedVertices.usedVertexA = true; - } - m_cachedBC.setBarycentricCoordinates(1-t,t); - nearest = from + t*v; - - m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]); - m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]); - m_cachedV = m_cachedP1 - m_cachedP2; - - reduceVertices(m_cachedBC.m_usedVertices); - - m_cachedValidClosest = m_cachedBC.isValid(); - break; - } - case 3: - { - //closest point origin from triangle - btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); - - const btVector3& a = m_simplexVectorW[0]; - const btVector3& b = m_simplexVectorW[1]; - const btVector3& c = m_simplexVectorW[2]; - - closestPtPointTriangle(p,a,b,c,m_cachedBC); - m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] + - m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] + - m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2]; - - m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] + - m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] + - m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2]; - - m_cachedV = m_cachedP1-m_cachedP2; - - reduceVertices (m_cachedBC.m_usedVertices); - m_cachedValidClosest = m_cachedBC.isValid(); - - break; - } - case 4: - { - - - btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); - - const btVector3& a = m_simplexVectorW[0]; - const btVector3& b = m_simplexVectorW[1]; - const btVector3& c = m_simplexVectorW[2]; - const btVector3& d = m_simplexVectorW[3]; - - bool hasSeperation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC); - - if (hasSeperation) - { - - m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] + - m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] + - m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] + - m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3]; - - m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] + - m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] + - m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] + - m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3]; - - m_cachedV = m_cachedP1-m_cachedP2; - reduceVertices (m_cachedBC.m_usedVertices); - } else - { -// printf("sub distance got penetration\n"); - - if (m_cachedBC.m_degenerate) - { - m_cachedValidClosest = false; - } else - { - m_cachedValidClosest = true; - //degenerate case == false, penetration = true + zero - m_cachedV.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - } - break; - } - - m_cachedValidClosest = m_cachedBC.isValid(); - - //closest point origin from tetrahedron - break; - } - default: - { - m_cachedValidClosest = false; - } - }; - } - - return m_cachedValidClosest; - -} - -//return/calculate the closest vertex -bool btVoronoiSimplexSolver::closest(btVector3& v) -{ - bool succes = updateClosestVectorAndPoints(); - v = m_cachedV; - return succes; -} - - - -btScalar btVoronoiSimplexSolver::maxVertex() -{ - int i, numverts = numVertices(); - btScalar maxV = btScalar(0.); - for (i=0;i= btScalar(0.0) && d4 <= d3) - { - result.m_closestPointOnSimplex = b; - result.m_usedVertices.usedVertexB = true; - result.setBarycentricCoordinates(0,1,0); - - return true; // b; // barycentric coordinates (0,1,0) - } - // Check if P in edge region of AB, if so return projection of P onto AB - btScalar vc = d1*d4 - d3*d2; - if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0)) { - btScalar v = d1 / (d1 - d3); - result.m_closestPointOnSimplex = a + v * ab; - result.m_usedVertices.usedVertexA = true; - result.m_usedVertices.usedVertexB = true; - result.setBarycentricCoordinates(1-v,v,0); - return true; - //return a + v * ab; // barycentric coordinates (1-v,v,0) - } - - // Check if P in vertex region outside C - btVector3 cp = p - c; - btScalar d5 = ab.dot(cp); - btScalar d6 = ac.dot(cp); - if (d6 >= btScalar(0.0) && d5 <= d6) - { - result.m_closestPointOnSimplex = c; - result.m_usedVertices.usedVertexC = true; - result.setBarycentricCoordinates(0,0,1); - return true;//c; // barycentric coordinates (0,0,1) - } - - // Check if P in edge region of AC, if so return projection of P onto AC - btScalar vb = d5*d2 - d1*d6; - if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0)) { - btScalar w = d2 / (d2 - d6); - result.m_closestPointOnSimplex = a + w * ac; - result.m_usedVertices.usedVertexA = true; - result.m_usedVertices.usedVertexC = true; - result.setBarycentricCoordinates(1-w,0,w); - return true; - //return a + w * ac; // barycentric coordinates (1-w,0,w) - } - - // Check if P in edge region of BC, if so return projection of P onto BC - btScalar va = d3*d6 - d5*d4; - if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0)) { - btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); - - result.m_closestPointOnSimplex = b + w * (c - b); - result.m_usedVertices.usedVertexB = true; - result.m_usedVertices.usedVertexC = true; - result.setBarycentricCoordinates(0,1-w,w); - return true; - // return b + w * (c - b); // barycentric coordinates (0,1-w,w) - } - - // P inside face region. Compute Q through its barycentric coordinates (u,v,w) - btScalar denom = btScalar(1.0) / (va + vb + vc); - btScalar v = vb * denom; - btScalar w = vc * denom; - - result.m_closestPointOnSimplex = a + ab * v + ac * w; - result.m_usedVertices.usedVertexA = true; - result.m_usedVertices.usedVertexB = true; - result.m_usedVertices.usedVertexC = true; - result.setBarycentricCoordinates(1-v-w,v,w); - - return true; -// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w - -} - - - - - -/// Test if point p and d lie on opposite sides of plane through abc -int btVoronoiSimplexSolver::pointOutsideOfPlane(const btPoint3& p, const btPoint3& a, const btPoint3& b, const btPoint3& c, const btPoint3& d) -{ - btVector3 normal = (b-a).cross(c-a); - - btScalar signp = (p - a).dot(normal); // [AP AB AC] - btScalar signd = (d - a).dot( normal); // [AD AB AC] - -#ifdef CATCH_DEGENERATE_TETRAHEDRON -#ifdef BT_USE_DOUBLE_PRECISION -if (signd * signd < (btScalar(1e-8) * btScalar(1e-8))) - { - return -1; - } -#else - if (signd * signd < (btScalar(1e-4) * btScalar(1e-4))) - { -// printf("affine dependent/degenerate\n");// - return -1; - } -#endif - -#endif - // Points on opposite sides if expression signs are opposite - return signp * signd < btScalar(0.); -} - - -bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btPoint3& p, const btPoint3& a, const btPoint3& b, const btPoint3& c, const btPoint3& d, btSubSimplexClosestResult& finalResult) -{ - btSubSimplexClosestResult tempResult; - - // Start out assuming point inside all halfspaces, so closest to itself - finalResult.m_closestPointOnSimplex = p; - finalResult.m_usedVertices.reset(); - finalResult.m_usedVertices.usedVertexA = true; - finalResult.m_usedVertices.usedVertexB = true; - finalResult.m_usedVertices.usedVertexC = true; - finalResult.m_usedVertices.usedVertexD = true; - - int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d); - int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b); - int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c); - int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a); - - if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0) - { - finalResult.m_degenerate = true; - return false; - } - - if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC) - { - return false; - } - - - btScalar bestSqDist = FLT_MAX; - // If point outside face abc then compute closest point on abc - if (pointOutsideABC) - { - closestPtPointTriangle(p, a, b, c,tempResult); - btPoint3 q = tempResult.m_closestPointOnSimplex; - - btScalar sqDist = (q - p).dot( q - p); - // Update best closest point if (squared) distance is less than current best - if (sqDist < bestSqDist) { - bestSqDist = sqDist; - finalResult.m_closestPointOnSimplex = q; - //convert result bitmask! - finalResult.m_usedVertices.reset(); - finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; - finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB; - finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC; - finalResult.setBarycentricCoordinates( - tempResult.m_barycentricCoords[VERTA], - tempResult.m_barycentricCoords[VERTB], - tempResult.m_barycentricCoords[VERTC], - 0 - ); - - } - } - - - // Repeat test for face acd - if (pointOutsideACD) - { - closestPtPointTriangle(p, a, c, d,tempResult); - btPoint3 q = tempResult.m_closestPointOnSimplex; - //convert result bitmask! - - btScalar sqDist = (q - p).dot( q - p); - if (sqDist < bestSqDist) - { - bestSqDist = sqDist; - finalResult.m_closestPointOnSimplex = q; - finalResult.m_usedVertices.reset(); - finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; - - finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB; - finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC; - finalResult.setBarycentricCoordinates( - tempResult.m_barycentricCoords[VERTA], - 0, - tempResult.m_barycentricCoords[VERTB], - tempResult.m_barycentricCoords[VERTC] - ); - - } - } - // Repeat test for face adb - - - if (pointOutsideADB) - { - closestPtPointTriangle(p, a, d, b,tempResult); - btPoint3 q = tempResult.m_closestPointOnSimplex; - //convert result bitmask! - - btScalar sqDist = (q - p).dot( q - p); - if (sqDist < bestSqDist) - { - bestSqDist = sqDist; - finalResult.m_closestPointOnSimplex = q; - finalResult.m_usedVertices.reset(); - finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; - finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC; - - finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB; - finalResult.setBarycentricCoordinates( - tempResult.m_barycentricCoords[VERTA], - tempResult.m_barycentricCoords[VERTC], - 0, - tempResult.m_barycentricCoords[VERTB] - ); - - } - } - // Repeat test for face bdc - - - if (pointOutsideBDC) - { - closestPtPointTriangle(p, b, d, c,tempResult); - btPoint3 q = tempResult.m_closestPointOnSimplex; - //convert result bitmask! - btScalar sqDist = (q - p).dot( q - p); - if (sqDist < bestSqDist) - { - bestSqDist = sqDist; - finalResult.m_closestPointOnSimplex = q; - finalResult.m_usedVertices.reset(); - // - finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA; - finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC; - finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB; - - finalResult.setBarycentricCoordinates( - 0, - tempResult.m_barycentricCoords[VERTA], - tempResult.m_barycentricCoords[VERTC], - tempResult.m_barycentricCoords[VERTB] - ); - - } - } - - //help! we ended up full ! - - if (finalResult.m_usedVertices.usedVertexA && - finalResult.m_usedVertices.usedVertexB && - finalResult.m_usedVertices.usedVertexC && - finalResult.m_usedVertices.usedVertexD) - { - return true; - } - - return true; -} - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h deleted file mode 100644 index 356d335bc93..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h +++ /dev/null @@ -1,157 +0,0 @@ -/* -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. -*/ - - - -#ifndef btVoronoiSimplexSolver_H -#define btVoronoiSimplexSolver_H - -#include "btSimplexSolverInterface.h" - - - -#define VORONOI_SIMPLEX_MAX_VERTS 5 - -struct btUsageBitfield{ - btUsageBitfield() - { - reset(); - } - - void reset() - { - usedVertexA = false; - usedVertexB = false; - usedVertexC = false; - usedVertexD = false; - } - unsigned short usedVertexA : 1; - unsigned short usedVertexB : 1; - unsigned short usedVertexC : 1; - unsigned short usedVertexD : 1; - unsigned short unused1 : 1; - unsigned short unused2 : 1; - unsigned short unused3 : 1; - unsigned short unused4 : 1; -}; - - -struct btSubSimplexClosestResult -{ - btPoint3 m_closestPointOnSimplex; - //MASK for m_usedVertices - //stores the simplex vertex-usage, using the MASK, - // if m_usedVertices & MASK then the related vertex is used - btUsageBitfield m_usedVertices; - btScalar m_barycentricCoords[4]; - bool m_degenerate; - - void reset() - { - m_degenerate = false; - setBarycentricCoordinates(); - m_usedVertices.reset(); - } - bool isValid() - { - bool valid = (m_barycentricCoords[0] >= btScalar(0.)) && - (m_barycentricCoords[1] >= btScalar(0.)) && - (m_barycentricCoords[2] >= btScalar(0.)) && - (m_barycentricCoords[3] >= btScalar(0.)); - - - return valid; - } - void setBarycentricCoordinates(btScalar a=btScalar(0.),btScalar b=btScalar(0.),btScalar c=btScalar(0.),btScalar d=btScalar(0.)) - { - m_barycentricCoords[0] = a; - m_barycentricCoords[1] = b; - m_barycentricCoords[2] = c; - m_barycentricCoords[3] = d; - } - -}; - -/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin. -/// Can be used with GJK, as an alternative to Johnson distance algorithm. -#ifdef NO_VIRTUAL_INTERFACE -class btVoronoiSimplexSolver -#else -class btVoronoiSimplexSolver : public btSimplexSolverInterface -#endif -{ -public: - - int m_numVertices; - - btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS]; - btPoint3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS]; - btPoint3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS]; - - - - btPoint3 m_cachedP1; - btPoint3 m_cachedP2; - btVector3 m_cachedV; - btVector3 m_lastW; - bool m_cachedValidClosest; - - btSubSimplexClosestResult m_cachedBC; - - bool m_needsUpdate; - - void removeVertex(int index); - void reduceVertices (const btUsageBitfield& usedVerts); - bool updateClosestVectorAndPoints(); - - bool closestPtPointTetrahedron(const btPoint3& p, const btPoint3& a, const btPoint3& b, const btPoint3& c, const btPoint3& d, btSubSimplexClosestResult& finalResult); - int pointOutsideOfPlane(const btPoint3& p, const btPoint3& a, const btPoint3& b, const btPoint3& c, const btPoint3& d); - bool closestPtPointTriangle(const btPoint3& p, const btPoint3& a, const btPoint3& b, const btPoint3& c,btSubSimplexClosestResult& result); - -public: - - void reset(); - - void addVertex(const btVector3& w, const btPoint3& p, const btPoint3& q); - - - bool closest(btVector3& v); - - btScalar maxVertex(); - - bool fullSimplex() const - { - return (m_numVertices == 4); - } - - int getSimplex(btPoint3 *pBuf, btPoint3 *qBuf, btVector3 *yBuf) const; - - bool inSimplex(const btVector3& w); - - void backup_closest(btVector3& v) ; - - bool emptySimplex() const ; - - void compute_points(btPoint3& p1, btPoint3& p2) ; - - int numVertices() const - { - return m_numVertices; - } - - -}; - -#endif //VoronoiSimplexSolver diff --git a/extern/bullet2/src/BulletCollision/ibmsdk/Makefile b/extern/bullet2/src/BulletCollision/ibmsdk/Makefile deleted file mode 100644 index ad04ef1d295..00000000000 --- a/extern/bullet2/src/BulletCollision/ibmsdk/Makefile +++ /dev/null @@ -1,95 +0,0 @@ -#### Source code Dirs -VPATH = \ -../BroadphaseCollision \ -../CollisionDispatch \ -../NarrowPhaseCollision \ -../CollisionShapes - -ROOT = ../../.. - -#### Library -LIBRARY_ppu = bulletcollision.a - -#### Compiler flags -CPPFLAGS = \ --DUSE_LIBSPE2 \ --I../BroadphaseCollision \ --I../CollisionDispath \ --I../NarrowPhaseCollision \ --I../CollisionShapes \ --I$(ROOT)/src/ \ --I$(SDKINC) - -#### Optimization level flags -#CC_OPT_LEVEL = $(CC_OPT_LEVEL_DEBUG) -CC_OPT_LEVEL = -O3 - -##### Objects to be archived in lib - -OBJS = \ -btAxisSweep3.o \ -btBroadphaseProxy.o \ -btCollisionAlgorithm.o \ -btDispatcher.o \ -btOverlappingPairCache.o \ -btSimpleBroadphase.o \ -btContinuousConvexCollision.o \ -btConvexCast.o \ -btGjkConvexCast.o \ -btGjkEpa.o \ -btGjkEpaPenetrationDepthSolver.o \ -btGjkPairDetector.o \ -btDefaultCollisionConfiguration.o \ -btMinkowskiPenetrationDepthSolver.o \ -btPersistentManifold.o \ -btRaycastCallback.o \ -btSubSimplexConvexCast.o \ -btVoronoiSimplexSolver.o \ -btCollisionDispatcher.o \ -btCollisionObject.o \ -btCollisionWorld.o \ -btCompoundCollisionAlgorithm.o \ -btConvexConcaveCollisionAlgorithm.o \ -btConvexConvexAlgorithm.o \ -btEmptyCollisionAlgorithm.o \ -btManifoldResult.o \ -btSimulationIslandManager.o \ -btSphereBoxCollisionAlgorithm.o \ -btSphereSphereCollisionAlgorithm.o \ -btSphereTriangleCollisionAlgorithm.o \ -btUnionFind.o \ -SphereTriangleDetector.o \ -btBoxShape.o \ -btBvhTriangleMeshShape.o \ -btCapsuleShape.o \ -btCollisionShape.o \ -btCompoundShape.o \ -btConcaveShape.o \ -btConeShape.o \ -btConvexHullShape.o \ -btConvexShape.o \ -btConvexInternalShape.o \ -btConvexTriangleMeshShape.o \ -btCylinderShape.o \ -btEmptyShape.o \ -btHeightfieldTerrainShape.o \ -btMinkowskiSumShape.o \ -btMultiSphereShape.o \ -btOptimizedBvh.o \ -btPolyhedralConvexShape.o \ -btSphereShape.o \ -btStaticPlaneShape.o \ -btStridingMeshInterface.o \ -btTetrahedronShape.o \ -btTriangleBuffer.o \ -btTriangleCallback.o \ -btTriangleIndexVertexArray.o \ -btTriangleMesh.o \ -btTriangleMeshShape.o \ -btUniformScalingShape.o - -#### Install directories -INSTALL_DIR = $(ROOT)/lib/ibmsdk -INSTALL_FILES = $(LIBRARY_ppu) -CELL_TOP ?= /opt/ibm/cell-sdk/prototype -include $(CELL_TOP)/make.footer diff --git a/extern/bullet2/src/BulletDynamics/CMakeLists.txt b/extern/bullet2/src/BulletDynamics/CMakeLists.txt deleted file mode 100644 index 97ccd7ed08a..00000000000 --- a/extern/bullet2/src/BulletDynamics/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -INCLUDE_DIRECTORIES( -${BULLET_PHYSICS_SOURCE_DIR}/src } -) - -ADD_LIBRARY(LibBulletDynamics - - ConstraintSolver/btContactConstraint.cpp - ConstraintSolver/btConeTwistConstraint.cpp - ConstraintSolver/btGeneric6DofConstraint.cpp - ConstraintSolver/btHingeConstraint.cpp - ConstraintSolver/btPoint2PointConstraint.cpp - ConstraintSolver/btSequentialImpulseConstraintSolver.cpp - ConstraintSolver/btSolve2LinearConstraint.cpp - ConstraintSolver/btTypedConstraint.cpp - Dynamics/Bullet-C-API.cpp - Dynamics/btDiscreteDynamicsWorld.cpp - Dynamics/btSimpleDynamicsWorld.cpp - Dynamics/Bullet-C-API.cpp - Dynamics/btRigidBody.cpp - Vehicle/btRaycastVehicle.cpp - Vehicle/btWheelInfo.cpp -) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp deleted file mode 100644 index a8a2c4f6763..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios - -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. - -Written by: Marcus Hennix -*/ - - -#include "btConeTwistConstraint.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "LinearMath/btTransformUtil.h" -#include "LinearMath/btMinMax.h" -#include - -btConeTwistConstraint::btConeTwistConstraint() -:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE) -{ -} - - -btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, - const btTransform& rbAFrame,const btTransform& rbBFrame) - :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), - m_angularOnly(false) -{ - // flip axis for correct angles - m_rbBFrame.getBasis()[1][0] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][1] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); - - m_swingSpan1 = btScalar(1e30); - m_swingSpan2 = btScalar(1e30); - m_twistSpan = btScalar(1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - - m_solveTwistLimit = false; - m_solveSwingLimit = false; - -} - -btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) - :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame), - m_angularOnly(false) -{ - m_rbBFrame = m_rbAFrame; - - // flip axis for correct angles - m_rbBFrame.getBasis()[1][0] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][1] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); - - m_rbBFrame.getBasis()[2][0] *= btScalar(-1.); - m_rbBFrame.getBasis()[2][1] *= btScalar(-1.); - m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); - - m_swingSpan1 = btScalar(1e30); - m_swingSpan2 = btScalar(1e30); - m_twistSpan = btScalar(1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - - m_solveTwistLimit = false; - m_solveSwingLimit = false; - -} - -void btConeTwistConstraint::buildJacobian() -{ - m_appliedImpulse = btScalar(0.); - - //set bias, sign, clear accumulator - m_swingCorrection = btScalar(0.); - m_twistLimitSign = btScalar(0.); - m_solveTwistLimit = false; - m_solveSwingLimit = false; - m_accTwistLimitImpulse = btScalar(0.); - m_accSwingLimitImpulse = btScalar(0.); - - if (!m_angularOnly) - { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - btVector3 relPos = pivotBInW - pivotAInW; - - btVector3 normal[3]; - if (relPos.length2() > SIMD_EPSILON) - { - normal[0] = relPos.normalized(); - } - else - { - normal[0].setValue(btScalar(1.0),0,0); - } - - btPlaneSpace1(normal[0], normal[1], normal[2]); - - for (int i=0;i<3;i++) - { - new (&m_jac[i]) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - pivotAInW - m_rbA.getCenterOfMassPosition(), - pivotBInW - m_rbB.getCenterOfMassPosition(), - normal[i], - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); - } - } - - btVector3 b1Axis1,b1Axis2,b1Axis3; - btVector3 b2Axis1,b2Axis2; - - b1Axis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(0); - b2Axis1 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(0); - - btScalar swing1=btScalar(0.),swing2 = btScalar(0.); - - // Get Frame into world space - if (m_swingSpan1 >= btScalar(0.05f)) - { - b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1); - swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); - } - - if (m_swingSpan2 >= btScalar(0.05f)) - { - b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2); - swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); - } - - btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1); - btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2); - btScalar EllipseAngle = btFabs(swing1)* RMaxAngle1Sq + btFabs(swing2) * RMaxAngle2Sq; - - if (EllipseAngle > 1.0f) - { - m_swingCorrection = EllipseAngle-1.0f; - m_solveSwingLimit = true; - - // Calculate necessary axis & factors - m_swingAxis = b2Axis1.cross(b1Axis2* b2Axis1.dot(b1Axis2) + b1Axis3* b2Axis1.dot(b1Axis3)); - m_swingAxis.normalize(); - - btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f; - m_swingAxis *= swingAxisSign; - - m_kSwing = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_swingAxis) + - getRigidBodyB().computeAngularImpulseDenominator(m_swingAxis)); - - } - - // Twist limits - if (m_twistSpan >= btScalar(0.)) - { - btVector3 b2Axis2 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(1); - btQuaternion rotationArc = shortestArcQuat(b2Axis1,b1Axis1); - btVector3 TwistRef = quatRotate(rotationArc,b2Axis2); - btScalar twist = btAtan2Fast( TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2) ); - - btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.); - if (twist <= -m_twistSpan*lockedFreeFactor) - { - m_twistCorrection = -(twist + m_twistSpan); - m_solveTwistLimit = true; - - m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; - m_twistAxis.normalize(); - m_twistAxis *= -1.0f; - - m_kTwist = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_twistAxis) + - getRigidBodyB().computeAngularImpulseDenominator(m_twistAxis)); - - } else - if (twist > m_twistSpan*lockedFreeFactor) - { - m_twistCorrection = (twist - m_twistSpan); - m_solveTwistLimit = true; - - m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; - m_twistAxis.normalize(); - - m_kTwist = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_twistAxis) + - getRigidBodyB().computeAngularImpulseDenominator(m_twistAxis)); - - } - } -} - -void btConeTwistConstraint::solveConstraint(btScalar timeStep) -{ - - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - - btScalar tau = btScalar(0.3); - - //linear part - if (!m_angularOnly) - { - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - for (int i=0;i<3;i++) - { - const btVector3& normal = m_jac[i].m_linearJointAxis; - btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); - - btScalar rel_vel; - rel_vel = normal.dot(vel); - //positional error (zeroth order error) - btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; - m_appliedImpulse += impulse; - btVector3 impulse_vector = normal * impulse; - m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); - m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); - } - } - - { - ///solve angular part - const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); - const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); - - // solve swing limit - if (m_solveSwingLimit) - { - btScalar amplitude = ((angVelB - angVelA).dot( m_swingAxis )*m_relaxationFactor*m_relaxationFactor + m_swingCorrection*(btScalar(1.)/timeStep)*m_biasFactor); - btScalar impulseMag = amplitude * m_kSwing; - - // Clamp the accumulated impulse - btScalar temp = m_accSwingLimitImpulse; - m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); - impulseMag = m_accSwingLimitImpulse - temp; - - btVector3 impulse = m_swingAxis * impulseMag; - - m_rbA.applyTorqueImpulse(impulse); - m_rbB.applyTorqueImpulse(-impulse); - - } - - // solve twist limit - if (m_solveTwistLimit) - { - btScalar amplitude = ((angVelB - angVelA).dot( m_twistAxis )*m_relaxationFactor*m_relaxationFactor + m_twistCorrection*(btScalar(1.)/timeStep)*m_biasFactor ); - btScalar impulseMag = amplitude * m_kTwist; - - // Clamp the accumulated impulse - btScalar temp = m_accTwistLimitImpulse; - m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); - impulseMag = m_accTwistLimitImpulse - temp; - - btVector3 impulse = m_twistAxis * impulseMag; - - m_rbA.applyTorqueImpulse(impulse); - m_rbB.applyTorqueImpulse(-impulse); - - } - - } - -} - -void btConeTwistConstraint::updateRHS(btScalar timeStep) -{ - (void)timeStep; - -} diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h deleted file mode 100644 index f121919c8f9..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h +++ /dev/null @@ -1,126 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios - -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. - -Written by: Marcus Hennix -*/ - - - -#ifndef CONETWISTCONSTRAINT_H -#define CONETWISTCONSTRAINT_H - -#include "../../LinearMath/btVector3.h" -#include "btJacobianEntry.h" -#include "btTypedConstraint.h" - -class btRigidBody; - - -///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc) -class btConeTwistConstraint : public btTypedConstraint -{ -#ifdef IN_PARALLELL_SOLVER -public: -#endif - btJacobianEntry m_jac[3]; //3 orthogonal linear constraints - - btTransform m_rbAFrame; - btTransform m_rbBFrame; - - btScalar m_limitSoftness; - btScalar m_biasFactor; - btScalar m_relaxationFactor; - - btScalar m_swingSpan1; - btScalar m_swingSpan2; - btScalar m_twistSpan; - - btVector3 m_swingAxis; - btVector3 m_twistAxis; - - btScalar m_kSwing; - btScalar m_kTwist; - - btScalar m_twistLimitSign; - btScalar m_swingCorrection; - btScalar m_twistCorrection; - - btScalar m_accSwingLimitImpulse; - btScalar m_accTwistLimitImpulse; - - bool m_angularOnly; - bool m_solveTwistLimit; - bool m_solveSwingLimit; - - -public: - - btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame); - - btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame); - - btConeTwistConstraint(); - - virtual void buildJacobian(); - - virtual void solveConstraint(btScalar timeStep); - - void updateRHS(btScalar timeStep); - - const btRigidBody& getRigidBodyA() const - { - return m_rbA; - } - const btRigidBody& getRigidBodyB() const - { - return m_rbB; - } - - void setAngularOnly(bool angularOnly) - { - m_angularOnly = angularOnly; - } - - void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 0.8f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) - { - m_swingSpan1 = _swingSpan1; - m_swingSpan2 = _swingSpan2; - m_twistSpan = _twistSpan; - - m_limitSoftness = _softness; - m_biasFactor = _biasFactor; - m_relaxationFactor = _relaxationFactor; - } - - const btTransform& getAFrame() { return m_rbAFrame; }; - const btTransform& getBFrame() { return m_rbBFrame; }; - - inline int getSolveTwistLimit() - { - return m_solveTwistLimit; - } - - inline int getSolveSwingLimit() - { - return m_solveTwistLimit; - } - - inline btScalar getTwistLimitSign() - { - return m_twistLimitSign; - } - -}; - -#endif //CONETWISTCONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h deleted file mode 100644 index addfb67a839..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -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. -*/ - -#ifndef CONSTRAINT_SOLVER_H -#define CONSTRAINT_SOLVER_H - -#include "LinearMath/btScalar.h" - -class btPersistentManifold; -class btRigidBody; -class btCollisionObject; -class btTypedConstraint; -struct btContactSolverInfo; -struct btBroadphaseProxy; -class btIDebugDraw; -class btStackAlloc; -class btDispatcher; -/// btConstraintSolver provides solver interface -class btConstraintSolver -{ - -public: - - virtual ~btConstraintSolver() {} - - virtual void prepareSolve (int numBodies, int numManifolds) {;} - - ///solve a group of constraints - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) = 0; - - virtual void allSolved (const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) {;} - - ///clear internal cached data and reset random seed - virtual void reset() = 0; -}; - - - - -#endif //CONSTRAINT_SOLVER_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp deleted file mode 100644 index 1588428503a..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/* -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. -*/ - - -#include "btContactConstraint.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "LinearMath/btVector3.h" -#include "btJacobianEntry.h" -#include "btContactSolverInfo.h" -#include "LinearMath/btMinMax.h" -#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" - -#define ASSERT2 assert - -#define USE_INTERNAL_APPLY_IMPULSE 1 - - -//bilateral constraint between two dynamic objects -void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, - btRigidBody& body2, const btVector3& pos2, - btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep) -{ - (void)timeStep; - (void)distance; - - - btScalar normalLenSqr = normal.length2(); - ASSERT2(btFabs(normalLenSqr) < btScalar(1.1)); - if (normalLenSqr > btScalar(1.1)) - { - impulse = btScalar(0.); - return; - } - btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); - //this jacobian entry could be re-used for all iterations - - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - - btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(), - body2.getCenterOfMassTransform().getBasis().transpose(), - rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(), - body2.getInvInertiaDiagLocal(),body2.getInvMass()); - - btScalar jacDiagAB = jac.getDiagonal(); - btScalar jacDiagABInv = btScalar(1.) / jacDiagAB; - - btScalar rel_vel = jac.getRelativeVelocity( - body1.getLinearVelocity(), - body1.getCenterOfMassTransform().getBasis().transpose() * body1.getAngularVelocity(), - body2.getLinearVelocity(), - body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity()); - btScalar a; - a=jacDiagABInv; - - - rel_vel = normal.dot(vel); - - //todo: move this into proper structure - btScalar contactDamping = btScalar(0.2); - -#ifdef ONLY_USE_LINEAR_MASS - btScalar massTerm = btScalar(1.) / (body1.getInvMass() + body2.getInvMass()); - impulse = - contactDamping * rel_vel * massTerm; -#else - btScalar velocityImpulse = -contactDamping * rel_vel * jacDiagABInv; - impulse = velocityImpulse; -#endif -} - - - -//response between two dynamic objects with friction -btScalar resolveSingleCollision( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo) -{ - - const btVector3& pos1_ = contactPoint.getPositionWorldOnA(); - const btVector3& pos2_ = contactPoint.getPositionWorldOnB(); - const btVector3& normal = contactPoint.m_normalWorldOnB; - - //constant over all iterations - btVector3 rel_pos1 = pos1_ - body1.getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2_ - body2.getCenterOfMassPosition(); - - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; - rel_vel = normal.dot(vel); - - btScalar Kfps = btScalar(1.) / solverInfo.m_timeStep ; - - // btScalar damping = solverInfo.m_damping ; - btScalar Kerp = solverInfo.m_erp; - btScalar Kcor = Kerp *Kfps; - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - assert(cpd); - btScalar distance = cpd->m_penetration; - btScalar positionalError = Kcor *-distance; - btScalar velocityError = cpd->m_restitution - rel_vel;// * damping; - - btScalar penetrationImpulse = positionalError * cpd->m_jacDiagABInv; - - btScalar velocityImpulse = velocityError * cpd->m_jacDiagABInv; - - btScalar normalImpulse = penetrationImpulse+velocityImpulse; - - // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse - btScalar oldNormalImpulse = cpd->m_appliedImpulse; - btScalar sum = oldNormalImpulse + normalImpulse; - cpd->m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; - - normalImpulse = cpd->m_appliedImpulse - oldNormalImpulse; - -#ifdef USE_INTERNAL_APPLY_IMPULSE - if (body1.getInvMass()) - { - body1.internalApplyImpulse(contactPoint.m_normalWorldOnB*body1.getInvMass(),cpd->m_angularComponentA,normalImpulse); - } - if (body2.getInvMass()) - { - body2.internalApplyImpulse(contactPoint.m_normalWorldOnB*body2.getInvMass(),cpd->m_angularComponentB,-normalImpulse); - } -#else //USE_INTERNAL_APPLY_IMPULSE - body1.applyImpulse(normal*(normalImpulse), rel_pos1); - body2.applyImpulse(-normal*(normalImpulse), rel_pos2); -#endif //USE_INTERNAL_APPLY_IMPULSE - - return normalImpulse; -} - - -btScalar resolveSingleFriction( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo) -{ - - (void)solverInfo; - - const btVector3& pos1 = contactPoint.getPositionWorldOnA(); - const btVector3& pos2 = contactPoint.getPositionWorldOnB(); - - btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - assert(cpd); - - btScalar combinedFriction = cpd->m_friction; - - btScalar limit = cpd->m_appliedImpulse * combinedFriction; - - if (cpd->m_appliedImpulse>btScalar(0.)) - //friction - { - //apply friction in the 2 tangential directions - - // 1st tangent - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - btScalar j1,j2; - - { - - btScalar vrel = cpd->m_frictionWorldTangential0.dot(vel); - - // calculate j that moves us to zero relative velocity - j1 = -vrel * cpd->m_jacDiagABInvTangent0; - btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse0; - cpd->m_accumulatedTangentImpulse0 = oldTangentImpulse + j1; - btSetMin(cpd->m_accumulatedTangentImpulse0, limit); - btSetMax(cpd->m_accumulatedTangentImpulse0, -limit); - j1 = cpd->m_accumulatedTangentImpulse0 - oldTangentImpulse; - - } - { - // 2nd tangent - - btScalar vrel = cpd->m_frictionWorldTangential1.dot(vel); - - // calculate j that moves us to zero relative velocity - j2 = -vrel * cpd->m_jacDiagABInvTangent1; - btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse1; - cpd->m_accumulatedTangentImpulse1 = oldTangentImpulse + j2; - btSetMin(cpd->m_accumulatedTangentImpulse1, limit); - btSetMax(cpd->m_accumulatedTangentImpulse1, -limit); - j2 = cpd->m_accumulatedTangentImpulse1 - oldTangentImpulse; - } - -#ifdef USE_INTERNAL_APPLY_IMPULSE - if (body1.getInvMass()) - { - body1.internalApplyImpulse(cpd->m_frictionWorldTangential0*body1.getInvMass(),cpd->m_frictionAngularComponent0A,j1); - body1.internalApplyImpulse(cpd->m_frictionWorldTangential1*body1.getInvMass(),cpd->m_frictionAngularComponent1A,j2); - } - if (body2.getInvMass()) - { - body2.internalApplyImpulse(cpd->m_frictionWorldTangential0*body2.getInvMass(),cpd->m_frictionAngularComponent0B,-j1); - body2.internalApplyImpulse(cpd->m_frictionWorldTangential1*body2.getInvMass(),cpd->m_frictionAngularComponent1B,-j2); - } -#else //USE_INTERNAL_APPLY_IMPULSE - body1.applyImpulse((j1 * cpd->m_frictionWorldTangential0)+(j2 * cpd->m_frictionWorldTangential1), rel_pos1); - body2.applyImpulse((j1 * -cpd->m_frictionWorldTangential0)+(j2 * -cpd->m_frictionWorldTangential1), rel_pos2); -#endif //USE_INTERNAL_APPLY_IMPULSE - - - } - return cpd->m_appliedImpulse; -} - - -btScalar resolveSingleFrictionOriginal( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo) -{ - - (void)solverInfo; - - const btVector3& pos1 = contactPoint.getPositionWorldOnA(); - const btVector3& pos2 = contactPoint.getPositionWorldOnB(); - - btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - assert(cpd); - - btScalar combinedFriction = cpd->m_friction; - - btScalar limit = cpd->m_appliedImpulse * combinedFriction; - //if (contactPoint.m_appliedImpulse>btScalar(0.)) - //friction - { - //apply friction in the 2 tangential directions - - { - // 1st tangent - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - btScalar vrel = cpd->m_frictionWorldTangential0.dot(vel); - - // calculate j that moves us to zero relative velocity - btScalar j = -vrel * cpd->m_jacDiagABInvTangent0; - btScalar total = cpd->m_accumulatedTangentImpulse0 + j; - btSetMin(total, limit); - btSetMax(total, -limit); - j = total - cpd->m_accumulatedTangentImpulse0; - cpd->m_accumulatedTangentImpulse0 = total; - body1.applyImpulse(j * cpd->m_frictionWorldTangential0, rel_pos1); - body2.applyImpulse(j * -cpd->m_frictionWorldTangential0, rel_pos2); - } - - - { - // 2nd tangent - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - btScalar vrel = cpd->m_frictionWorldTangential1.dot(vel); - - // calculate j that moves us to zero relative velocity - btScalar j = -vrel * cpd->m_jacDiagABInvTangent1; - btScalar total = cpd->m_accumulatedTangentImpulse1 + j; - btSetMin(total, limit); - btSetMax(total, -limit); - j = total - cpd->m_accumulatedTangentImpulse1; - cpd->m_accumulatedTangentImpulse1 = total; - body1.applyImpulse(j * cpd->m_frictionWorldTangential1, rel_pos1); - body2.applyImpulse(j * -cpd->m_frictionWorldTangential1, rel_pos2); - } - } - return cpd->m_appliedImpulse; -} - - -//velocity + friction -//response between two dynamic objects with friction -btScalar resolveSingleCollisionCombined( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo) -{ - - const btVector3& pos1 = contactPoint.getPositionWorldOnA(); - const btVector3& pos2 = contactPoint.getPositionWorldOnB(); - const btVector3& normal = contactPoint.m_normalWorldOnB; - - btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); - - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; - rel_vel = normal.dot(vel); - - btScalar Kfps = btScalar(1.) / solverInfo.m_timeStep ; - - //btScalar damping = solverInfo.m_damping ; - btScalar Kerp = solverInfo.m_erp; - btScalar Kcor = Kerp *Kfps; - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; - assert(cpd); - btScalar distance = cpd->m_penetration; - btScalar positionalError = Kcor *-distance; - btScalar velocityError = cpd->m_restitution - rel_vel;// * damping; - - btScalar penetrationImpulse = positionalError * cpd->m_jacDiagABInv; - - btScalar velocityImpulse = velocityError * cpd->m_jacDiagABInv; - - btScalar normalImpulse = penetrationImpulse+velocityImpulse; - - // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse - btScalar oldNormalImpulse = cpd->m_appliedImpulse; - btScalar sum = oldNormalImpulse + normalImpulse; - cpd->m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; - - normalImpulse = cpd->m_appliedImpulse - oldNormalImpulse; - - -#ifdef USE_INTERNAL_APPLY_IMPULSE - if (body1.getInvMass()) - { - body1.internalApplyImpulse(contactPoint.m_normalWorldOnB*body1.getInvMass(),cpd->m_angularComponentA,normalImpulse); - } - if (body2.getInvMass()) - { - body2.internalApplyImpulse(contactPoint.m_normalWorldOnB*body2.getInvMass(),cpd->m_angularComponentB,-normalImpulse); - } -#else //USE_INTERNAL_APPLY_IMPULSE - body1.applyImpulse(normal*(normalImpulse), rel_pos1); - body2.applyImpulse(-normal*(normalImpulse), rel_pos2); -#endif //USE_INTERNAL_APPLY_IMPULSE - - { - //friction - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - rel_vel = normal.dot(vel); - - - btVector3 lat_vel = vel - normal * rel_vel; - btScalar lat_rel_vel = lat_vel.length(); - - btScalar combinedFriction = cpd->m_friction; - - if (cpd->m_appliedImpulse > 0) - if (lat_rel_vel > SIMD_EPSILON) - { - lat_vel /= lat_rel_vel; - btVector3 temp1 = body1.getInvInertiaTensorWorld() * rel_pos1.cross(lat_vel); - btVector3 temp2 = body2.getInvInertiaTensorWorld() * rel_pos2.cross(lat_vel); - btScalar friction_impulse = lat_rel_vel / - (body1.getInvMass() + body2.getInvMass() + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); - btScalar normal_impulse = cpd->m_appliedImpulse * combinedFriction; - - btSetMin(friction_impulse, normal_impulse); - btSetMax(friction_impulse, -normal_impulse); - body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1); - body2.applyImpulse(lat_vel * friction_impulse, rel_pos2); - } - } - - - - return normalImpulse; -} - -btScalar resolveSingleFrictionEmpty( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo) -{ - (void)contactPoint; - (void)body1; - (void)body2; - (void)solverInfo; - - - return btScalar(0.); -}; - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h deleted file mode 100644 index 826e79f78bd..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h +++ /dev/null @@ -1,122 +0,0 @@ -/* -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. -*/ - -#ifndef CONTACT_CONSTRAINT_H -#define CONTACT_CONSTRAINT_H - -//todo: make into a proper class working with the iterative constraint solver - -class btRigidBody; -#include "LinearMath/btVector3.h" -#include "LinearMath/btScalar.h" -struct btContactSolverInfo; -class btManifoldPoint; - -enum { - DEFAULT_CONTACT_SOLVER_TYPE=0, - CONTACT_SOLVER_TYPE1, - CONTACT_SOLVER_TYPE2, - USER_CONTACT_SOLVER_TYPE1, - MAX_CONTACT_SOLVER_TYPES -}; - - -typedef btScalar (*ContactSolverFunc)(btRigidBody& body1, - btRigidBody& body2, - class btManifoldPoint& contactPoint, - const btContactSolverInfo& info); - -///stores some extra information to each contact point. It is not in the contact point, because that want to keep the collision detection independent from the constraint solver. -struct btConstraintPersistentData -{ - inline btConstraintPersistentData() - :m_appliedImpulse(btScalar(0.)), - m_prevAppliedImpulse(btScalar(0.)), - m_accumulatedTangentImpulse0(btScalar(0.)), - m_accumulatedTangentImpulse1(btScalar(0.)), - m_jacDiagABInv(btScalar(0.)), - m_persistentLifeTime(0), - m_restitution(btScalar(0.)), - m_friction(btScalar(0.)), - m_penetration(btScalar(0.)), - m_contactSolverFunc(0), - m_frictionSolverFunc(0) - { - } - - - /// total applied impulse during most recent frame - btScalar m_appliedImpulse; - btScalar m_prevAppliedImpulse; - btScalar m_accumulatedTangentImpulse0; - btScalar m_accumulatedTangentImpulse1; - - btScalar m_jacDiagABInv; - btScalar m_jacDiagABInvTangent0; - btScalar m_jacDiagABInvTangent1; - int m_persistentLifeTime; - btScalar m_restitution; - btScalar m_friction; - btScalar m_penetration; - btVector3 m_frictionWorldTangential0; - btVector3 m_frictionWorldTangential1; - - btVector3 m_frictionAngularComponent0A; - btVector3 m_frictionAngularComponent0B; - btVector3 m_frictionAngularComponent1A; - btVector3 m_frictionAngularComponent1B; - - //some data doesn't need to be persistent over frames: todo: clean/reuse this - btVector3 m_angularComponentA; - btVector3 m_angularComponentB; - - ContactSolverFunc m_contactSolverFunc; - ContactSolverFunc m_frictionSolverFunc; - -}; - -///bilateral constraint between two dynamic objects -///positive distance = separation, negative distance = penetration -void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, - btRigidBody& body2, const btVector3& pos2, - btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep); - - -///contact constraint resolution: -///calculate and apply impulse to satisfy non-penetration and non-negative relative velocity constraint -///positive distance = separation, negative distance = penetration -btScalar resolveSingleCollision( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& info); - -btScalar resolveSingleFriction( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo - ); - - - -btScalar resolveSingleCollisionCombined( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo - ); - -#endif //CONTACT_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h deleted file mode 100644 index ad2c40e2107..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -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. -*/ - -#ifndef CONTACT_SOLVER_INFO -#define CONTACT_SOLVER_INFO - -struct btContactSolverInfoData -{ - btScalar m_tau; - btScalar m_damping; - btScalar m_friction; - btScalar m_timeStep; - btScalar m_restitution; - int m_numIterations; - btScalar m_maxErrorReduction; - btScalar m_sor; - btScalar m_erp; - -}; - -struct btContactSolverInfo : public btContactSolverInfoData -{ - - inline btContactSolverInfo() - { - m_tau = btScalar(0.6); - m_damping = btScalar(1.0); - m_friction = btScalar(0.3); - m_restitution = btScalar(0.); - m_maxErrorReduction = btScalar(20.); - m_numIterations = 10; - m_erp = btScalar(0.4); - m_sor = btScalar(1.3); - } - - -}; - -#endif //CONTACT_SOLVER_INFO diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp deleted file mode 100644 index 96d48f9f7dd..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp +++ /dev/null @@ -1,497 +0,0 @@ -/* -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. -*/ -/* -2007-09-09 -Refactored by Francisco León -email: projectileman@yahoo.com -http://gimpact.sf.net -*/ - - -#include "btGeneric6DofConstraint.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "LinearMath/btTransformUtil.h" -#include - - -static const btScalar kSign[] = { btScalar(1.0), btScalar(-1.0), btScalar(1.0) }; -static const int kAxisA[] = { 1, 0, 0 }; -static const int kAxisB[] = { 2, 2, 1 }; -#define GENERIC_D6_DISABLE_WARMSTARTING 1 - -btScalar btGetMatrixElem(const btMatrix3x3& mat, int index) -{ - int i = index%3; - int j = index/3; - return mat[i][j]; -} - -///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html -bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) -{ -// // rot = cy*cz -cy*sz sy -// // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx -// // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy -// - - if (btGetMatrixElem(mat,2) < btScalar(1.0)) - { - if (btGetMatrixElem(mat,2) > btScalar(-1.0)) - { - xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); - xyz[1] = btAsin(btGetMatrixElem(mat,2)); - xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); - return true; - } - else - { - // WARNING. Not unique. XA - ZA = -atan2(r10,r11) - xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); - xyz[1] = -SIMD_HALF_PI; - xyz[2] = btScalar(0.0); - return false; - } - } - else - { - // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) - xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); - xyz[1] = SIMD_HALF_PI; - xyz[2] = 0.0; - - } - - - return false; -} - - - -//////////////////////////// btRotationalLimitMotor //////////////////////////////////// - - -int btRotationalLimitMotor::testLimitValue(btScalar test_value) -{ - if(m_loLimit>m_hiLimit) - { - m_currentLimit = 0;//Free from violation - return 0; - } - - if (test_value < m_loLimit) - { - m_currentLimit = 1;//low limit violation - m_currentLimitError = test_value - m_loLimit; - return 1; - } - else if (test_value> m_hiLimit) - { - m_currentLimit = 2;//High limit violation - m_currentLimitError = test_value - m_hiLimit; - return 2; - } - else - { - m_currentLimit = 0;//Free from violation - return 0; - } - return 0; -} - - -btScalar btRotationalLimitMotor::solveAngularLimits( - btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, - btRigidBody * body0, btRigidBody * body1) -{ - if (needApplyTorques()==false) return 0.0f; - - btScalar target_velocity = m_targetVelocity; - btScalar maxMotorForce = m_maxMotorForce; - - //current error correction - if (m_currentLimit!=0) - { - target_velocity = -m_ERP*m_currentLimitError/(timeStep); - maxMotorForce = m_maxLimitForce; - } - - maxMotorForce *= timeStep; - - // current velocity difference - btVector3 vel_diff = body0->getAngularVelocity(); - if (body1) - { - vel_diff -= body1->getAngularVelocity(); - } - - - - btScalar rel_vel = axis.dot(vel_diff); - - // correction velocity - btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel); - - - if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON ) - { - return 0.0f;//no need for applying force - } - - - // correction impulse - btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv; - - // clip correction impulse - btScalar clippedMotorImpulse; - - //todo: should clip against accumulated impulse - if (unclippedMotorImpulse>0.0f) - { - clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse; - } - else - { - clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse; - } - - - // sort with accumulated impulses - btScalar lo = btScalar(-1e30); - btScalar hi = btScalar(1e30); - - btScalar oldaccumImpulse = m_accumulatedImpulse; - btScalar sum = oldaccumImpulse + clippedMotorImpulse; - m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; - - clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; - - - - btVector3 motorImp = clippedMotorImpulse * axis; - - - body0->applyTorqueImpulse(motorImp); - if (body1) body1->applyTorqueImpulse(-motorImp); - - return clippedMotorImpulse; - - -} - -//////////////////////////// End btRotationalLimitMotor //////////////////////////////////// - -//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// -btScalar btTranslationalLimitMotor::solveLinearAxis( - btScalar timeStep, - btScalar jacDiagABInv, - btRigidBody& body1,const btVector3 &pointInA, - btRigidBody& body2,const btVector3 &pointInB, - int limit_index, - const btVector3 & axis_normal_on_a) -{ - -///find relative velocity - btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); - btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); - - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - btScalar rel_vel = axis_normal_on_a.dot(vel); - - - -/// apply displacement correction - -//positional error (zeroth order error) - btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); - btScalar lo = btScalar(-1e30); - btScalar hi = btScalar(1e30); - - btScalar minLimit = m_lowerLimit[limit_index]; - btScalar maxLimit = m_upperLimit[limit_index]; - - //handle the limits - if (minLimit < maxLimit) - { - { - if (depth > maxLimit) - { - depth -= maxLimit; - lo = btScalar(0.); - - } - else - { - if (depth < minLimit) - { - depth -= minLimit; - hi = btScalar(0.); - } - else - { - return 0.0f; - } - } - } - } - - btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; - - - - - btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; - btScalar sum = oldNormalImpulse + normalImpulse; - m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; - normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; - - btVector3 impulse_vector = axis_normal_on_a * normalImpulse; - body1.applyImpulse( impulse_vector, rel_pos1); - body2.applyImpulse(-impulse_vector, rel_pos2); - return normalImpulse; -} - -//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// - - -btGeneric6DofConstraint::btGeneric6DofConstraint() - :btTypedConstraint(D6_CONSTRAINT_TYPE), - m_useLinearReferenceFrameA(true) -{ -} - -btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) - : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB) - , m_frameInA(frameInA) - , m_frameInB(frameInB), - m_useLinearReferenceFrameA(useLinearReferenceFrameA) -{ - -} - - - - - -void btGeneric6DofConstraint::calculateAngleInfo() -{ - btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis(); - - matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); - - - - // in euler angle mode we do not actually constrain the angular velocity - // along the axes axis[0] and axis[2] (although we do use axis[1]) : - // - // to get constrain w2-w1 along ...not - // ------ --------------------- ------ - // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] - // d(angle[1])/dt = 0 ax[1] - // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] - // - // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. - // to prove the result for angle[0], write the expression for angle[0] from - // GetInfo1 then take the derivative. to prove this for angle[2] it is - // easier to take the euler rate expression for d(angle[2])/dt with respect - // to the components of w and set that to 0. - - btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0); - btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2); - - m_calculatedAxis[1] = axis2.cross(axis0); - m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2); - m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); - - -// if(m_debugDrawer) -// { -// -// char buff[300]; -// sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", -// m_calculatedAxisAngleDiff[0], -// m_calculatedAxisAngleDiff[1], -// m_calculatedAxisAngleDiff[2]); -// m_debugDrawer->reportErrorWarning(buff); -// } - -} - -void btGeneric6DofConstraint::calculateTransforms() -{ - m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; - m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; - - calculateAngleInfo(); -} - - -void btGeneric6DofConstraint::buildLinearJacobian( - btJacobianEntry & jacLinear,const btVector3 & normalWorld, - const btVector3 & pivotAInW,const btVector3 & pivotBInW) -{ - new (&jacLinear) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - pivotAInW - m_rbA.getCenterOfMassPosition(), - pivotBInW - m_rbB.getCenterOfMassPosition(), - normalWorld, - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); - -} - -void btGeneric6DofConstraint::buildAngularJacobian( - btJacobianEntry & jacAngular,const btVector3 & jointAxisW) -{ - new (&jacAngular) btJacobianEntry(jointAxisW, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - -} - -bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index) -{ - btScalar angle = m_calculatedAxisAngleDiff[axis_index]; - - //test limits - m_angularLimits[axis_index].testLimitValue(angle); - return m_angularLimits[axis_index].needApplyTorques(); -} - -void btGeneric6DofConstraint::buildJacobian() -{ - //calculates transform - calculateTransforms(); - - const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); - const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); - - - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 normalWorld; - int i; - //linear part - for (i=0;i<3;i++) - { - if (m_linearLimits.isLimited(i)) - { - if (m_useLinearReferenceFrameA) - normalWorld = m_calculatedTransformA.getBasis().getColumn(i); - else - normalWorld = m_calculatedTransformB.getBasis().getColumn(i); - - buildLinearJacobian( - m_jacLinear[i],normalWorld , - pivotAInW,pivotBInW); - - } - } - - // angular part - for (i=0;i<3;i++) - { - //calculates error angle - if (testAngularLimitMotor(i)) - { - normalWorld = this->getAxis(i); - // Create angular atom - buildAngularJacobian(m_jacAng[i],normalWorld); - } - } - - -} - - -void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) -{ - m_timeStep = timeStep; - - //calculateTransforms(); - - int i; - - // linear - - btVector3 pointInA = m_calculatedTransformA.getOrigin(); - btVector3 pointInB = m_calculatedTransformB.getOrigin(); - - btScalar jacDiagABInv; - btVector3 linear_axis; - for (i=0;i<3;i++) - { - if (m_linearLimits.isLimited(i)) - { - jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); - - if (m_useLinearReferenceFrameA) - linear_axis = m_calculatedTransformA.getBasis().getColumn(i); - else - linear_axis = m_calculatedTransformB.getBasis().getColumn(i); - - m_linearLimits.solveLinearAxis( - m_timeStep, - jacDiagABInv, - m_rbA,pointInA, - m_rbB,pointInB, - i,linear_axis); - - } - } - - // angular - btVector3 angular_axis; - btScalar angularJacDiagABInv; - for (i=0;i<3;i++) - { - if (m_angularLimits[i].needApplyTorques()) - { - - // get axis - angular_axis = getAxis(i); - - angularJacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); - - m_angularLimits[i].solveAngularLimits(m_timeStep,angular_axis,angularJacDiagABInv, &m_rbA,&m_rbB); - } - } -} - -void btGeneric6DofConstraint::updateRHS(btScalar timeStep) -{ - (void)timeStep; - -} - -btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const -{ - return m_calculatedAxis[axis_index]; -} - -btScalar btGeneric6DofConstraint::getAngle(int axis_index) const -{ - return m_calculatedAxisAngleDiff[axis_index]; -} - - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h deleted file mode 100644 index e4683b91b9e..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h +++ /dev/null @@ -1,433 +0,0 @@ -/* -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. -*/ -/* -2007-09-09 -btGeneric6DofConstraint Refactored by Francisco León -email: projectileman@yahoo.com -http://gimpact.sf.net -*/ - - -#ifndef GENERIC_6DOF_CONSTRAINT_H -#define GENERIC_6DOF_CONSTRAINT_H - -#include "LinearMath/btVector3.h" -#include "btJacobianEntry.h" -#include "btTypedConstraint.h" - -class btRigidBody; - - -//! Rotation Limit structure for generic joints -class btRotationalLimitMotor -{ -public: - //! limit_parameters - //!@{ - btScalar m_loLimit;//!< joint limit - btScalar m_hiLimit;//!< joint limit - btScalar m_targetVelocity;//!< target motor velocity - btScalar m_maxMotorForce;//!< max force on motor - btScalar m_maxLimitForce;//!< max force on limit - btScalar m_damping;//!< Damping. - btScalar m_limitSoftness;//! Relaxation factor - btScalar m_ERP;//!< Error tolerance factor when joint is at limit - btScalar m_bounce;//!< restitution factor - bool m_enableMotor; - - //!@} - - //! temp_variables - //!@{ - btScalar m_currentLimitError;//! How much is violated this limit - int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit - btScalar m_accumulatedImpulse; - //!@} - - btRotationalLimitMotor() - { - m_accumulatedImpulse = 0.f; - m_targetVelocity = 0; - m_maxMotorForce = 0.1f; - m_maxLimitForce = 300.0f; - m_loLimit = -SIMD_INFINITY; - m_hiLimit = SIMD_INFINITY; - m_ERP = 0.5f; - m_bounce = 0.0f; - m_damping = 1.0f; - m_limitSoftness = 0.5f; - m_currentLimit = 0; - m_currentLimitError = 0; - m_enableMotor = false; - } - - btRotationalLimitMotor(const btRotationalLimitMotor & limot) - { - m_targetVelocity = limot.m_targetVelocity; - m_maxMotorForce = limot.m_maxMotorForce; - m_limitSoftness = limot.m_limitSoftness; - m_loLimit = limot.m_loLimit; - m_hiLimit = limot.m_hiLimit; - m_ERP = limot.m_ERP; - m_bounce = limot.m_bounce; - m_currentLimit = limot.m_currentLimit; - m_currentLimitError = limot.m_currentLimitError; - m_enableMotor = limot.m_enableMotor; - } - - - - //! Is limited - bool isLimited() - { - if(m_loLimit>=m_hiLimit) return false; - return true; - } - - //! Need apply correction - bool needApplyTorques() - { - if(m_currentLimit == 0 && m_enableMotor == false) return false; - return true; - } - - //! calculates error - /*! - calculates m_currentLimit and m_currentLimitError. - */ - int testLimitValue(btScalar test_value); - - //! apply the correction impulses for two bodies - btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1); - - -}; - - - -class btTranslationalLimitMotor -{ -public: - btVector3 m_lowerLimit;//!< the constraint lower limits - btVector3 m_upperLimit;//!< the constraint upper limits - btVector3 m_accumulatedImpulse; - //! Linear_Limit_parameters - //!@{ - btScalar m_limitSoftness;//!< Softness for linear limit - btScalar m_damping;//!< Damping for linear limit - btScalar m_restitution;//! Bounce parameter for linear limit - //!@} - - btTranslationalLimitMotor() - { - m_lowerLimit.setValue(0.f,0.f,0.f); - m_upperLimit.setValue(0.f,0.f,0.f); - m_accumulatedImpulse.setValue(0.f,0.f,0.f); - - m_limitSoftness = 0.7f; - m_damping = btScalar(1.0f); - m_restitution = btScalar(0.5f); - } - - btTranslationalLimitMotor(const btTranslationalLimitMotor & other ) - { - m_lowerLimit = other.m_lowerLimit; - m_upperLimit = other.m_upperLimit; - m_accumulatedImpulse = other.m_accumulatedImpulse; - - m_limitSoftness = other.m_limitSoftness ; - m_damping = other.m_damping; - m_restitution = other.m_restitution; - } - - //! Test limit - /*! - - free means upper < lower, - - locked means upper == lower - - limited means upper > lower - - limitIndex: first 3 are linear, next 3 are angular - */ - inline bool isLimited(int limitIndex) - { - return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); - } - - - btScalar solveLinearAxis( - btScalar timeStep, - btScalar jacDiagABInv, - btRigidBody& body1,const btVector3 &pointInA, - btRigidBody& body2,const btVector3 &pointInB, - int limit_index, - const btVector3 & axis_normal_on_a); - - -}; - -/// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space -/*! -btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'. -currently this limit supports rotational motors
-
    -
  • For Linear limits, use btGeneric6DofConstraint.setLinearUpperLimit, btGeneric6DofConstraint.setLinearLowerLimit. You can set the parameters with the btTranslationalLimitMotor structure accsesible through the btGeneric6DofConstraint.getTranslationalLimitMotor method. -At this moment translational motors are not supported. May be in the future.
  • - -
  • For Angular limits, use the btRotationalLimitMotor structure for configuring the limit. -This is accessible through btGeneric6DofConstraint.getLimitMotor method, -This brings support for limit parameters and motors.
  • - -
  • Angulars limits have these possible ranges: - -AXIS - - - - - - - - - - - - -
    MIN ANGLEMAX ANGLEX-PIPIY-PI/2PI/2Z-PI/2PI/2
    -
  • -
- -*/ -class btGeneric6DofConstraint : public btTypedConstraint -{ -protected: - - //! relative_frames - //!@{ - btTransform m_frameInA;//!< the constraint space w.r.t body A - btTransform m_frameInB;//!< the constraint space w.r.t body B - //!@} - - //! Jacobians - //!@{ - btJacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints - btJacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints - //!@} - - //! Linear_Limit_parameters - //!@{ - btTranslationalLimitMotor m_linearLimits; - //!@} - - - //! hinge_parameters - //!@{ - btRotationalLimitMotor m_angularLimits[3]; - //!@} - - -protected: - //! temporal variables - //!@{ - btScalar m_timeStep; - btTransform m_calculatedTransformA; - btTransform m_calculatedTransformB; - btVector3 m_calculatedAxisAngleDiff; - btVector3 m_calculatedAxis[3]; - - bool m_useLinearReferenceFrameA; - - //!@} - - btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) - { - btAssert(0); - (void) other; - return *this; - } - - - - void buildLinearJacobian( - btJacobianEntry & jacLinear,const btVector3 & normalWorld, - const btVector3 & pivotAInW,const btVector3 & pivotBInW); - - void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW); - - - //! calcs the euler angles between the two bodies. - void calculateAngleInfo(); - - - -public: - btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); - - btGeneric6DofConstraint(); - - //! Calcs global transform of the offsets - /*! - Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies. - \sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo - */ - void calculateTransforms(); - - //! Gets the global transform of the offset for body A - /*! - \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. - */ - const btTransform & getCalculatedTransformA() const - { - return m_calculatedTransformA; - } - - //! Gets the global transform of the offset for body B - /*! - \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. - */ - const btTransform & getCalculatedTransformB() const - { - return m_calculatedTransformB; - } - - const btTransform & getFrameOffsetA() const - { - return m_frameInA; - } - - const btTransform & getFrameOffsetB() const - { - return m_frameInB; - } - - - btTransform & getFrameOffsetA() - { - return m_frameInA; - } - - btTransform & getFrameOffsetB() - { - return m_frameInB; - } - - - //! performs Jacobian calculation, and also calculates angle differences and axis - virtual void buildJacobian(); - - virtual void solveConstraint(btScalar timeStep); - - void updateRHS(btScalar timeStep); - - //! Get the rotation axis in global coordinates - /*! - \pre btGeneric6DofConstraint.buildJacobian must be called previously. - */ - btVector3 getAxis(int axis_index) const; - - //! Get the relative Euler angle - /*! - \pre btGeneric6DofConstraint.buildJacobian must be called previously. - */ - btScalar getAngle(int axis_index) const; - - //! Test angular limit. - /*! - Calculates angular correction and returns true if limit needs to be corrected. - \pre btGeneric6DofConstraint.buildJacobian must be called previously. - */ - bool testAngularLimitMotor(int axis_index); - - void setLinearLowerLimit(const btVector3& linearLower) - { - m_linearLimits.m_lowerLimit = linearLower; - } - - void setLinearUpperLimit(const btVector3& linearUpper) - { - m_linearLimits.m_upperLimit = linearUpper; - } - - void setAngularLowerLimit(const btVector3& angularLower) - { - m_angularLimits[0].m_loLimit = angularLower.getX(); - m_angularLimits[1].m_loLimit = angularLower.getY(); - m_angularLimits[2].m_loLimit = angularLower.getZ(); - } - - void setAngularUpperLimit(const btVector3& angularUpper) - { - m_angularLimits[0].m_hiLimit = angularUpper.getX(); - m_angularLimits[1].m_hiLimit = angularUpper.getY(); - m_angularLimits[2].m_hiLimit = angularUpper.getZ(); - } - - //! Retrieves the angular limit informacion - btRotationalLimitMotor * getRotationalLimitMotor(int index) - { - return &m_angularLimits[index]; - } - - //! Retrieves the limit informacion - btTranslationalLimitMotor * getTranslationalLimitMotor() - { - return &m_linearLimits; - } - - //first 3 are linear, next 3 are angular - void setLimit(int axis, btScalar lo, btScalar hi) - { - if(axis<3) - { - m_linearLimits.m_lowerLimit[axis] = lo; - m_linearLimits.m_upperLimit[axis] = hi; - } - else - { - m_angularLimits[axis-3].m_loLimit = lo; - m_angularLimits[axis-3].m_hiLimit = hi; - } - } - - //! Test limit - /*! - - free means upper < lower, - - locked means upper == lower - - limited means upper > lower - - limitIndex: first 3 are linear, next 3 are angular - */ - bool isLimited(int limitIndex) - { - if(limitIndex<3) - { - return m_linearLimits.isLimited(limitIndex); - - } - return m_angularLimits[limitIndex-3].isLimited(); - } - - const btRigidBody& getRigidBodyA() const - { - return m_rbA; - } - const btRigidBody& getRigidBodyB() const - { - return m_rbB; - } - - -}; - -#endif //GENERIC_6DOF_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp deleted file mode 100644 index f71698fa6ee..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* -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. -*/ - - -#include "btHingeConstraint.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "LinearMath/btTransformUtil.h" -#include "LinearMath/btMinMax.h" -#include - - -btHingeConstraint::btHingeConstraint() -: btTypedConstraint (HINGE_CONSTRAINT_TYPE), -m_enableAngularMotor(false) -{ -} - -btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, - btVector3& axisInA,btVector3& axisInB) - :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB), - m_angularOnly(false), - m_enableAngularMotor(false) -{ - m_rbAFrame.getOrigin() = pivotInA; - - // since no frame is given, assume this to be zero angle and just pick rb transform axis - btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); - btScalar projection = rbAxisA1.dot(axisInA); - if (projection > SIMD_EPSILON) - rbAxisA1 = rbAxisA1*projection - axisInA; - else - rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); - - btVector3 rbAxisA2 = rbAxisA1.cross(axisInA); - - m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), - rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), - rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); - - btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); - btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); - btVector3 rbAxisB2 = rbAxisB1.cross(axisInB); - - - m_rbBFrame.getOrigin() = pivotInB; - m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),-axisInB.getX(), - rbAxisB1.getY(),rbAxisB2.getY(),-axisInB.getY(), - rbAxisB1.getZ(),rbAxisB2.getZ(),-axisInB.getZ() ); - - //start with free - m_lowerLimit = btScalar(1e30); - m_upperLimit = btScalar(-1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - m_limitSoftness = 0.9f; - m_solveLimit = false; - -} - - -btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA) -:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false) -{ - - // since no frame is given, assume this to be zero angle and just pick rb transform axis - // fixed axis in worldspace - btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); - btScalar projection = rbAxisA1.dot(axisInA); - if (projection > SIMD_EPSILON) - rbAxisA1 = rbAxisA1*projection - axisInA; - else - rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); - - btVector3 rbAxisA2 = axisInA.cross(rbAxisA1); - - m_rbAFrame.getOrigin() = pivotInA; - m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), - rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), - rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); - - - btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * -axisInA; - - btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); - btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); - btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); - - - m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA); - m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), - rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), - rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); - - //start with free - m_lowerLimit = btScalar(1e30); - m_upperLimit = btScalar(-1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - m_limitSoftness = 0.9f; - m_solveLimit = false; -} - -btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, - const btTransform& rbAFrame, const btTransform& rbBFrame) -:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), -m_angularOnly(false), -m_enableAngularMotor(false) -{ - // flip axis - m_rbBFrame.getBasis()[0][2] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); - m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); - - //start with free - m_lowerLimit = btScalar(1e30); - m_upperLimit = btScalar(-1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - m_limitSoftness = 0.9f; - m_solveLimit = false; -} - - - -btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame) -:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame), -m_angularOnly(false), -m_enableAngularMotor(false) -{ - ///not providing rigidbody B means implicitly using worldspace for body B - - // flip axis - m_rbBFrame.getBasis()[0][2] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); - m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); - - m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin()); - - //start with free - m_lowerLimit = btScalar(1e30); - m_upperLimit = btScalar(-1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - m_limitSoftness = 0.9f; - m_solveLimit = false; -} - -void btHingeConstraint::buildJacobian() -{ - m_appliedImpulse = btScalar(0.); - - if (!m_angularOnly) - { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - btVector3 relPos = pivotBInW - pivotAInW; - - btVector3 normal[3]; - if (relPos.length2() > SIMD_EPSILON) - { - normal[0] = relPos.normalized(); - } - else - { - normal[0].setValue(btScalar(1.0),0,0); - } - - btPlaneSpace1(normal[0], normal[1], normal[2]); - - for (int i=0;i<3;i++) - { - new (&m_jac[i]) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - pivotAInW - m_rbA.getCenterOfMassPosition(), - pivotBInW - m_rbB.getCenterOfMassPosition(), - normal[i], - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); - } - } - - //calculate two perpendicular jointAxis, orthogonal to hingeAxis - //these two jointAxis require equal angular velocities for both bodies - - //this is unused for now, it's a todo - btVector3 jointAxis0local; - btVector3 jointAxis1local; - - btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); - - getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); - btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local; - btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local; - btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); - - new (&m_jacAng[0]) btJacobianEntry(jointAxis0, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - - new (&m_jacAng[1]) btJacobianEntry(jointAxis1, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - - new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - - - // Compute limit information - btScalar hingeAngle = getHingeAngle(); - - //set bias, sign, clear accumulator - m_correction = btScalar(0.); - m_limitSign = btScalar(0.); - m_solveLimit = false; - m_accLimitImpulse = btScalar(0.); - - if (m_lowerLimit < m_upperLimit) - { - if (hingeAngle <= m_lowerLimit*m_limitSoftness) - { - m_correction = (m_lowerLimit - hingeAngle); - m_limitSign = 1.0f; - m_solveLimit = true; - } - else if (hingeAngle >= m_upperLimit*m_limitSoftness) - { - m_correction = m_upperLimit - hingeAngle; - m_limitSign = -1.0f; - m_solveLimit = true; - } - } - - //Compute K = J*W*J' for hinge axis - btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); - m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) + - getRigidBodyB().computeAngularImpulseDenominator(axisA)); - -} - -void btHingeConstraint::solveConstraint(btScalar timeStep) -{ - - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - - btScalar tau = btScalar(0.3); - - //linear part - if (!m_angularOnly) - { - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - for (int i=0;i<3;i++) - { - const btVector3& normal = m_jac[i].m_linearJointAxis; - btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); - - btScalar rel_vel; - rel_vel = normal.dot(vel); - //positional error (zeroth order error) - btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; - m_appliedImpulse += impulse; - btVector3 impulse_vector = normal * impulse; - m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); - m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); - } - } - - - { - ///solve angular part - - // get axes in world space - btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); - btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(2); - - const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); - const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); - - btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA); - btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB); - - btVector3 angAorthog = angVelA - angVelAroundHingeAxisA; - btVector3 angBorthog = angVelB - angVelAroundHingeAxisB; - btVector3 velrelOrthog = angAorthog-angBorthog; - { - //solve orthogonal angular velocity correction - btScalar relaxation = btScalar(1.); - btScalar len = velrelOrthog.length(); - if (len > btScalar(0.00001)) - { - btVector3 normal = velrelOrthog.normalized(); - btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) + - getRigidBodyB().computeAngularImpulseDenominator(normal); - // scale for mass and relaxation - //todo: expose this 0.9 factor to developer - velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor; - } - - //solve angular positional correction - btVector3 angularError = -axisA.cross(axisB) *(btScalar(1.)/timeStep); - btScalar len2 = angularError.length(); - if (len2>btScalar(0.00001)) - { - btVector3 normal2 = angularError.normalized(); - btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) + - getRigidBodyB().computeAngularImpulseDenominator(normal2); - angularError *= (btScalar(1.)/denom2) * relaxation; - } - - m_rbA.applyTorqueImpulse(-velrelOrthog+angularError); - m_rbB.applyTorqueImpulse(velrelOrthog-angularError); - - // solve limit - if (m_solveLimit) - { - btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor ) * m_limitSign; - - btScalar impulseMag = amplitude * m_kHinge; - - // Clamp the accumulated impulse - btScalar temp = m_accLimitImpulse; - m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) ); - impulseMag = m_accLimitImpulse - temp; - - - btVector3 impulse = axisA * impulseMag * m_limitSign; - m_rbA.applyTorqueImpulse(impulse); - m_rbB.applyTorqueImpulse(-impulse); - } - } - - //apply motor - if (m_enableAngularMotor) - { - //todo: add limits too - btVector3 angularLimit(0,0,0); - - btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB; - btScalar projRelVel = velrel.dot(axisA); - - btScalar desiredMotorVel = m_motorTargetVelocity; - btScalar motor_relvel = desiredMotorVel - projRelVel; - - btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;; - //todo: should clip against accumulated impulse - btScalar clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse; - clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse; - btVector3 motorImp = clippedMotorImpulse * axisA; - - m_rbA.applyTorqueImpulse(motorImp+angularLimit); - m_rbB.applyTorqueImpulse(-motorImp-angularLimit); - - } - } - -} - -void btHingeConstraint::updateRHS(btScalar timeStep) -{ - (void)timeStep; - -} - -btScalar btHingeConstraint::getHingeAngle() -{ - const btVector3 refAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0); - const btVector3 refAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1); - const btVector3 swingAxis = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(1); - - return btAtan2Fast( swingAxis.dot(refAxis0), swingAxis.dot(refAxis1) ); -} diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h deleted file mode 100644 index 8d8adfe9250..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -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. -*/ - -/* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */ - -#ifndef HINGECONSTRAINT_H -#define HINGECONSTRAINT_H - -#include "LinearMath/btVector3.h" -#include "btJacobianEntry.h" -#include "btTypedConstraint.h" - -class btRigidBody; - -/// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space -/// axis defines the orientation of the hinge axis -class btHingeConstraint : public btTypedConstraint -{ -#ifdef IN_PARALLELL_SOLVER -public: -#endif - btJacobianEntry m_jac[3]; //3 orthogonal linear constraints - btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor - - btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis. - btTransform m_rbBFrame; - - btScalar m_motorTargetVelocity; - btScalar m_maxMotorImpulse; - - btScalar m_limitSoftness; - btScalar m_biasFactor; - btScalar m_relaxationFactor; - - btScalar m_lowerLimit; - btScalar m_upperLimit; - - btScalar m_kHinge; - - btScalar m_limitSign; - btScalar m_correction; - - btScalar m_accLimitImpulse; - - bool m_angularOnly; - bool m_enableAngularMotor; - bool m_solveLimit; - - -public: - - btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, btVector3& axisInA,btVector3& axisInB); - - btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA); - - btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame); - - btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame); - - btHingeConstraint(); - - virtual void buildJacobian(); - - virtual void solveConstraint(btScalar timeStep); - - void updateRHS(btScalar timeStep); - - const btRigidBody& getRigidBodyA() const - { - return m_rbA; - } - const btRigidBody& getRigidBodyB() const - { - return m_rbB; - } - - void setAngularOnly(bool angularOnly) - { - m_angularOnly = angularOnly; - } - - void enableAngularMotor(bool enableMotor,btScalar targetVelocity,btScalar maxMotorImpulse) - { - m_enableAngularMotor = enableMotor; - m_motorTargetVelocity = targetVelocity; - m_maxMotorImpulse = maxMotorImpulse; - } - - void setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) - { - m_lowerLimit = low; - m_upperLimit = high; - - m_limitSoftness = _softness; - m_biasFactor = _biasFactor; - m_relaxationFactor = _relaxationFactor; - - } - - btScalar getHingeAngle(); - - - const btTransform& getAFrame() { return m_rbAFrame; }; - const btTransform& getBFrame() { return m_rbBFrame; }; - - inline int getSolveLimit() - { - return m_solveLimit; - } - - inline btScalar getLimitSign() - { - return m_limitSign; - } - -}; - -#endif //HINGECONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h deleted file mode 100644 index bfeb24c2dfb..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h +++ /dev/null @@ -1,156 +0,0 @@ -/* -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. -*/ - -#ifndef JACOBIAN_ENTRY_H -#define JACOBIAN_ENTRY_H - -#include "LinearMath/btVector3.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" - - -//notes: -// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components -// which makes the btJacobianEntry memory layout 16 bytes -// if you only are interested in angular part, just feed massInvA and massInvB zero - -/// Jacobian entry is an abstraction that allows to describe constraints -/// it can be used in combination with a constraint solver -/// Can be used to relate the effect of an impulse to the constraint error -class btJacobianEntry -{ -public: - btJacobianEntry() {}; - //constraint between two different rigidbodies - btJacobianEntry( - const btMatrix3x3& world2A, - const btMatrix3x3& world2B, - const btVector3& rel_pos1,const btVector3& rel_pos2, - const btVector3& jointAxis, - const btVector3& inertiaInvA, - const btScalar massInvA, - const btVector3& inertiaInvB, - const btScalar massInvB) - :m_linearJointAxis(jointAxis) - { - m_aJ = world2A*(rel_pos1.cross(m_linearJointAxis)); - m_bJ = world2B*(rel_pos2.cross(-m_linearJointAxis)); - m_0MinvJt = inertiaInvA * m_aJ; - m_1MinvJt = inertiaInvB * m_bJ; - m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ); - - btAssert(m_Adiag > btScalar(0.0)); - } - - //angular constraint between two different rigidbodies - btJacobianEntry(const btVector3& jointAxis, - const btMatrix3x3& world2A, - const btMatrix3x3& world2B, - const btVector3& inertiaInvA, - const btVector3& inertiaInvB) - :m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.))) - { - m_aJ= world2A*jointAxis; - m_bJ = world2B*-jointAxis; - m_0MinvJt = inertiaInvA * m_aJ; - m_1MinvJt = inertiaInvB * m_bJ; - m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); - - btAssert(m_Adiag > btScalar(0.0)); - } - - //angular constraint between two different rigidbodies - btJacobianEntry(const btVector3& axisInA, - const btVector3& axisInB, - const btVector3& inertiaInvA, - const btVector3& inertiaInvB) - : m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.))) - , m_aJ(axisInA) - , m_bJ(-axisInB) - { - m_0MinvJt = inertiaInvA * m_aJ; - m_1MinvJt = inertiaInvB * m_bJ; - m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); - - btAssert(m_Adiag > btScalar(0.0)); - } - - //constraint on one rigidbody - btJacobianEntry( - const btMatrix3x3& world2A, - const btVector3& rel_pos1,const btVector3& rel_pos2, - const btVector3& jointAxis, - const btVector3& inertiaInvA, - const btScalar massInvA) - :m_linearJointAxis(jointAxis) - { - m_aJ= world2A*(rel_pos1.cross(jointAxis)); - m_bJ = world2A*(rel_pos2.cross(-jointAxis)); - m_0MinvJt = inertiaInvA * m_aJ; - m_1MinvJt = btVector3(btScalar(0.),btScalar(0.),btScalar(0.)); - m_Adiag = massInvA + m_0MinvJt.dot(m_aJ); - - btAssert(m_Adiag > btScalar(0.0)); - } - - btScalar getDiagonal() const { return m_Adiag; } - - // for two constraints on the same rigidbody (for example vehicle friction) - btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const - { - const btJacobianEntry& jacA = *this; - btScalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis); - btScalar ang = jacA.m_0MinvJt.dot(jacB.m_aJ); - return lin + ang; - } - - - - // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies) - btScalar getNonDiagonal(const btJacobianEntry& jacB,const btScalar massInvA,const btScalar massInvB) const - { - const btJacobianEntry& jacA = *this; - btVector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis; - btVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ; - btVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ; - btVector3 lin0 = massInvA * lin ; - btVector3 lin1 = massInvB * lin; - btVector3 sum = ang0+ang1+lin0+lin1; - return sum[0]+sum[1]+sum[2]; - } - - btScalar getRelativeVelocity(const btVector3& linvelA,const btVector3& angvelA,const btVector3& linvelB,const btVector3& angvelB) - { - btVector3 linrel = linvelA - linvelB; - btVector3 angvela = angvelA * m_aJ; - btVector3 angvelb = angvelB * m_bJ; - linrel *= m_linearJointAxis; - angvela += angvelb; - angvela += linrel; - btScalar rel_vel2 = angvela[0]+angvela[1]+angvela[2]; - return rel_vel2 + SIMD_EPSILON; - } -//private: - - btVector3 m_linearJointAxis; - btVector3 m_aJ; - btVector3 m_bJ; - btVector3 m_0MinvJt; - btVector3 m_1MinvJt; - //Optimization: can be stored in the w/last component of one of the vectors - btScalar m_Adiag; - -}; - -#endif //JACOBIAN_ENTRY_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp deleted file mode 100644 index ff918ea5625..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* -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. -*/ - - -#include "btPoint2PointConstraint.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include - - - -btPoint2PointConstraint::btPoint2PointConstraint() -:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE) -{ -} - -btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB) -:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB) -{ - -} - - -btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) -:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) -{ - -} - -void btPoint2PointConstraint::buildJacobian() -{ - m_appliedImpulse = btScalar(0.); - - btVector3 normal(0,0,0); - - for (int i=0;i<3;i++) - { - normal[i] = 1; - new (&m_jac[i]) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(), - m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(), - normal, - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); - normal[i] = 0; - } - -} - -void btPoint2PointConstraint::solveConstraint(btScalar timeStep) -{ - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB; - - - btVector3 normal(0,0,0); - - -// btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); -// btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); - - for (int i=0;i<3;i++) - { - normal[i] = 1; - btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); - - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - //this jacobian entry could be re-used for all iterations - - btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - btScalar rel_vel; - rel_vel = normal.dot(vel); - - /* - //velocity error (first order error) - btScalar rel_vel = m_jac[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, - m_rbB.getLinearVelocity(),angvelB); - */ - - //positional error (zeroth order error) - btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - - btScalar impulse = depth*m_setting.m_tau/timeStep * jacDiagABInv - m_setting.m_damping * rel_vel * jacDiagABInv; - m_appliedImpulse+=impulse; - btVector3 impulse_vector = normal * impulse; - m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); - m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); - - normal[i] = 0; - } -} - -void btPoint2PointConstraint::updateRHS(btScalar timeStep) -{ - (void)timeStep; - -} - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h deleted file mode 100644 index 27872b9c8aa..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -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. -*/ - -#ifndef POINT2POINTCONSTRAINT_H -#define POINT2POINTCONSTRAINT_H - -#include "LinearMath/btVector3.h" -#include "btJacobianEntry.h" -#include "btTypedConstraint.h" - -class btRigidBody; - -struct btConstraintSetting -{ - btConstraintSetting() : - m_tau(btScalar(0.3)), - m_damping(btScalar(1.)) - { - } - btScalar m_tau; - btScalar m_damping; -}; - -/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space -class btPoint2PointConstraint : public btTypedConstraint -{ -#ifdef IN_PARALLELL_SOLVER -public: -#endif - btJacobianEntry m_jac[3]; //3 orthogonal linear constraints - - btVector3 m_pivotInA; - btVector3 m_pivotInB; - - - -public: - - btConstraintSetting m_setting; - - btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB); - - btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA); - - btPoint2PointConstraint(); - - virtual void buildJacobian(); - - - virtual void solveConstraint(btScalar timeStep); - - void updateRHS(btScalar timeStep); - - void setPivotA(const btVector3& pivotA) - { - m_pivotInA = pivotA; - } - - void setPivotB(const btVector3& pivotB) - { - m_pivotInB = pivotB; - } - - const btVector3& getPivotInA() const - { - return m_pivotInA; - } - - const btVector3& getPivotInB() const - { - return m_pivotInB; - } - - -}; - -#endif //POINT2POINTCONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp deleted file mode 100644 index 7d4ed7856c3..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ /dev/null @@ -1,1266 +0,0 @@ -/* -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. -*/ - -//#define COMPUTE_IMPULSE_DENOM 1 -//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms. -//#define FORCE_REFESH_CONTACT_MANIFOLDS 1 - -#include "btSequentialImpulseConstraintSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "btContactConstraint.h" -#include "btSolve2LinearConstraint.h" -#include "btContactSolverInfo.h" -#include "LinearMath/btIDebugDraw.h" -#include "btJacobianEntry.h" -#include "LinearMath/btMinMax.h" -#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" -#include -#include "LinearMath/btStackAlloc.h" -#include "LinearMath/btQuickprof.h" -#include "btSolverBody.h" -#include "btSolverConstraint.h" - -#include "LinearMath/btAlignedObjectArray.h" - -#ifdef USE_PROFILE -#include "LinearMath/btQuickprof.h" -#endif //USE_PROFILE - -int totalCpd = 0; - -int gTotalContactPoints = 0; - -struct btOrderIndex -{ - int m_manifoldIndex; - int m_pointIndex; -}; - - - -#define SEQUENTIAL_IMPULSE_MAX_SOLVER_POINTS 16384 -static btOrderIndex gOrder[SEQUENTIAL_IMPULSE_MAX_SOLVER_POINTS]; - - -unsigned long btSequentialImpulseConstraintSolver::btRand2() -{ - m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff; - return m_btSeed2; -} - - - -//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1) -int btSequentialImpulseConstraintSolver::btRandInt2 (int n) -{ - // seems good; xor-fold and modulus - const unsigned long un = n; - unsigned long r = btRand2(); - - // note: probably more aggressive than it needs to be -- might be - // able to get away without one or two of the innermost branches. - if (un <= 0x00010000UL) { - r ^= (r >> 16); - if (un <= 0x00000100UL) { - r ^= (r >> 8); - if (un <= 0x00000010UL) { - r ^= (r >> 4); - if (un <= 0x00000004UL) { - r ^= (r >> 2); - if (un <= 0x00000002UL) { - r ^= (r >> 1); - } - } - } - } - } - - return (int) (r % un); -} - - - - - -bool MyContactDestroyedCallback(void* userPersistentData) -{ - assert (userPersistentData); - btConstraintPersistentData* cpd = (btConstraintPersistentData*)userPersistentData; - btAlignedFree(cpd); - totalCpd--; - //printf("totalCpd = %i. DELETED Ptr %x\n",totalCpd,userPersistentData); - return true; -} - - - -btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() -:m_solverMode(SOLVER_RANDMIZE_ORDER | SOLVER_CACHE_FRIENDLY), //not using SOLVER_USE_WARMSTARTING, -m_btSeed2(0) -{ - gContactDestroyedCallback = &MyContactDestroyedCallback; - - //initialize default friction/contact funcs - int i,j; - for (i=0;im_angularVelocity = rigidbody->getAngularVelocity(); - solverBody->m_centerOfMassPosition = rigidbody->getCenterOfMassPosition(); - solverBody->m_friction = rigidbody->getFriction(); -// solverBody->m_invInertiaWorld = rigidbody->getInvInertiaTensorWorld(); - solverBody->m_invMass = rigidbody->getInvMass(); - solverBody->m_linearVelocity = rigidbody->getLinearVelocity(); - solverBody->m_originalBody = rigidbody; - solverBody->m_angularFactor = rigidbody->getAngularFactor(); -} - -btScalar penetrationResolveFactor = btScalar(0.9); -btScalar restitutionCurve(btScalar rel_vel, btScalar restitution) -{ - btScalar rest = restitution * -rel_vel; - return rest; -} - - - - - - -//velocity + friction -//response between two dynamic objects with friction -//SIMD_FORCE_INLINE -btScalar resolveSingleCollisionCombinedCacheFriendly( - btSolverBody& body1, - btSolverBody& body2, - const btSolverConstraint& contactConstraint, - const btContactSolverInfo& solverInfo) -{ - (void)solverInfo; - - btScalar normalImpulse; - - // Optimized version of projected relative velocity, use precomputed cross products with normal - // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); - // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); - // btVector3 vel = vel1 - vel2; - // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); - - btScalar rel_vel; - btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) - + contactConstraint.m_relpos1CrossNormal.dot(body1.m_angularVelocity); - btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_linearVelocity) - + contactConstraint.m_relpos2CrossNormal.dot(body2.m_angularVelocity); - - rel_vel = vel1Dotn-vel2Dotn; - - - btScalar positionalError = contactConstraint.m_penetration; - btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; - - btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; - btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; - normalImpulse = penetrationImpulse+velocityImpulse; - - // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse - btScalar oldNormalImpulse = contactConstraint.m_appliedImpulse; - btScalar sum = oldNormalImpulse + normalImpulse; - contactConstraint.m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; - - btScalar oldVelocityImpulse = contactConstraint.m_appliedVelocityImpulse; - btScalar velocitySum = oldVelocityImpulse + velocityImpulse; - contactConstraint.m_appliedVelocityImpulse = btScalar(0.) > velocitySum ? btScalar(0.): velocitySum; - - normalImpulse = contactConstraint.m_appliedImpulse - oldNormalImpulse; - - if (body1.m_invMass) - { - body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, - contactConstraint.m_angularComponentA,normalImpulse); - } - if (body2.m_invMass) - { - body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, - contactConstraint.m_angularComponentB,-normalImpulse); - } - - - - - - return normalImpulse; -} - - -#ifndef NO_FRICTION_TANGENTIALS - -//SIMD_FORCE_INLINE -btScalar resolveSingleFrictionCacheFriendly( - btSolverBody& body1, - btSolverBody& body2, - const btSolverConstraint& contactConstraint, - const btContactSolverInfo& solverInfo, - btScalar appliedNormalImpulse) -{ - (void)solverInfo; - - - const btScalar combinedFriction = contactConstraint.m_friction; - - const btScalar limit = appliedNormalImpulse * combinedFriction; - - if (appliedNormalImpulse>btScalar(0.)) - //friction - { - - btScalar j1; - { - - btScalar rel_vel; - const btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) - + contactConstraint.m_relpos1CrossNormal.dot(body1.m_angularVelocity); - const btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_linearVelocity) - + contactConstraint.m_relpos2CrossNormal.dot(body2.m_angularVelocity); - rel_vel = vel1Dotn-vel2Dotn; - - // calculate j that moves us to zero relative velocity - j1 = -rel_vel * contactConstraint.m_jacDiagABInv; -#define CLAMP_ACCUMULATED_FRICTION_IMPULSE 1 -#ifdef CLAMP_ACCUMULATED_FRICTION_IMPULSE - btScalar oldTangentImpulse = contactConstraint.m_appliedImpulse; - contactConstraint.m_appliedImpulse = oldTangentImpulse + j1; - - if (limit < contactConstraint.m_appliedImpulse) - { - contactConstraint.m_appliedImpulse = limit; - } else - { - if (contactConstraint.m_appliedImpulse < -limit) - contactConstraint.m_appliedImpulse = -limit; - } - j1 = contactConstraint.m_appliedImpulse - oldTangentImpulse; -#else - if (limit < j1) - { - j1 = limit; - } else - { - if (j1 < -limit) - j1 = -limit; - } - -#endif //CLAMP_ACCUMULATED_FRICTION_IMPULSE - - //GEN_set_min(contactConstraint.m_appliedImpulse, limit); - //GEN_set_max(contactConstraint.m_appliedImpulse, -limit); - - - - } - - if (body1.m_invMass) - { - body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass,contactConstraint.m_angularComponentA,j1); - } - if (body2.m_invMass) - { - body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass,contactConstraint.m_angularComponentB,-j1); - } - - } - return 0.f; -} - - -#else - -//velocity + friction -//response between two dynamic objects with friction -btScalar resolveSingleFrictionCacheFriendly( - btSolverBody& body1, - btSolverBody& body2, - btSolverConstraint& contactConstraint, - const btContactSolverInfo& solverInfo) -{ - - btVector3 vel1; - btVector3 vel2; - btScalar normalImpulse(0.f); - - { - const btVector3& normal = contactConstraint.m_contactNormal; - if (contactConstraint.m_penetration < 0.f) - return 0.f; - - - body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); - body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; - rel_vel = normal.dot(vel); - - btVector3 lat_vel = vel - normal * rel_vel; - btScalar lat_rel_vel = lat_vel.length2(); - - btScalar combinedFriction = contactConstraint.m_friction; - const btVector3& rel_pos1 = contactConstraint.m_rel_posA; - const btVector3& rel_pos2 = contactConstraint.m_rel_posB; - - - //if (contactConstraint.m_appliedVelocityImpulse > 0.f) - if (lat_rel_vel > SIMD_EPSILON*SIMD_EPSILON) - { - lat_rel_vel = btSqrt(lat_rel_vel); - - lat_vel /= lat_rel_vel; - btVector3 temp1 = body1.m_invInertiaWorld * rel_pos1.cross(lat_vel); - btVector3 temp2 = body2.m_invInertiaWorld * rel_pos2.cross(lat_vel); - btScalar friction_impulse = lat_rel_vel / - (body1.m_invMass + body2.m_invMass + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); - btScalar normal_impulse = contactConstraint.m_appliedVelocityImpulse * combinedFriction; - - GEN_set_min(friction_impulse, normal_impulse); - GEN_set_max(friction_impulse, -normal_impulse); - body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1); - body2.applyImpulse(lat_vel * friction_impulse, rel_pos2); - } - } - - return normalImpulse; -} - -#endif //NO_FRICTION_TANGENTIALS - - - - - -void btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btRigidBody* rb0,btRigidBody* rb1, btScalar relaxation) -{ - - btSolverConstraint& solverConstraint = m_tmpSolverFrictionConstraintPool.expand(); - solverConstraint.m_contactNormal = normalAxis; - - solverConstraint.m_solverBodyIdA = solverBodyIdA; - solverConstraint.m_solverBodyIdB = solverBodyIdB; - solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; - solverConstraint.m_frictionIndex = frictionIndex; - - solverConstraint.m_friction = cp.m_combinedFriction; - - solverConstraint.m_appliedImpulse = btScalar(0.); - solverConstraint.m_appliedVelocityImpulse = 0.f; - solverConstraint.m_penetration = 0.f; - { - btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis1; - } - { - btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis1; - } - -#ifdef COMPUTE_IMPULSE_DENOM - btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); - btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); -#else - btVector3 vec; - vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); - btScalar denom0 = rb0->getInvMass() + normalAxis.dot(vec); - vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2); - btScalar denom1 = rb1->getInvMass() + normalAxis.dot(vec); - - -#endif //COMPUTE_IMPULSE_DENOM - btScalar denom = relaxation/(denom0+denom1); - solverConstraint.m_jacDiagABInv = denom; - -} - - -btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) -{ - (void)stackAlloc; - (void)debugDrawer; - - if (!(numConstraints + numManifolds)) - { -// printf("empty\n"); - return 0.f; - } - btPersistentManifold* manifold = 0; - btRigidBody* rb0=0,*rb1=0; - -#ifdef FORCE_REFESH_CONTACT_MANIFOLDS - - BEGIN_PROFILE("refreshManifolds"); - - int i; - - - - for (i=0;igetBody1(); - rb0 = (btRigidBody*)manifold->getBody0(); - - manifold->refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); - - } - - END_PROFILE("refreshManifolds"); -#endif //FORCE_REFESH_CONTACT_MANIFOLDS - - btVector3 color(0,1,0); - - - BEGIN_PROFILE("gatherSolverData"); - - //int sizeofSB = sizeof(btSolverBody); - //int sizeofSC = sizeof(btSolverConstraint); - - - //if (1) - { - //if m_stackAlloc, try to pack bodies/constraints to speed up solving -// btBlock* sablock; -// sablock = stackAlloc->beginBlock(); - - // int memsize = 16; -// unsigned char* stackMemory = stackAlloc->allocate(memsize); - - - //todo: use stack allocator for this temp memory - int minReservation = numManifolds*2; - - //m_tmpSolverBodyPool.reserve(minReservation); - - //don't convert all bodies, only the one we need so solver the constraints -/* - { - for (int i=0;igetIslandTag() >= 0)) - { - btAssert(rb->getCompanionId() < 0); - int solverBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,rb); - rb->setCompanionId(solverBodyId); - } - } - } -*/ - - //m_tmpSolverConstraintPool.reserve(minReservation); - //m_tmpSolverFrictionConstraintPool.reserve(minReservation); - - { - int i; - - for (i=0;igetBody1(); - - rb0 = (btRigidBody*)manifold->getBody0(); - - - int solverBodyIdA=-1; - int solverBodyIdB=-1; - - if (manifold->getNumContacts()) - { - - - - if (rb0->getIslandTag() >= 0) - { - if (rb0->getCompanionId() >= 0) - { - //body has already been converted - solverBodyIdA = rb0->getCompanionId(); - } else - { - solverBodyIdA = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,rb0); - rb0->setCompanionId(solverBodyIdA); - } - } else - { - //create a static body - solverBodyIdA = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,rb0); - } - - if (rb1->getIslandTag() >= 0) - { - if (rb1->getCompanionId() >= 0) - { - solverBodyIdB = rb1->getCompanionId(); - } else - { - solverBodyIdB = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,rb1); - rb1->setCompanionId(solverBodyIdB); - } - } else - { - //create a static body - solverBodyIdB = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,rb1); - } - } - - btVector3 rel_pos1; - btVector3 rel_pos2; - btScalar relaxation; - - for (int j=0;jgetNumContacts();j++) - { - - btManifoldPoint& cp = manifold->getContactPoint(j); - - if (debugDrawer) - debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); - - - if (cp.getDistance() <= btScalar(0.)) - { - - const btVector3& pos1 = cp.getPositionWorldOnA(); - const btVector3& pos2 = cp.getPositionWorldOnB(); - - rel_pos1 = pos1 - rb0->getCenterOfMassPosition(); - rel_pos2 = pos2 - rb1->getCenterOfMassPosition(); - - - relaxation = 1.f; - btScalar rel_vel; - btVector3 vel; - - int frictionIndex = m_tmpSolverConstraintPool.size(); - - { - btSolverConstraint& solverConstraint = m_tmpSolverConstraintPool.expand(); - - solverConstraint.m_solverBodyIdA = solverBodyIdA; - solverConstraint.m_solverBodyIdB = solverBodyIdB; - solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_CONTACT_1D; - - btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*torqueAxis0; - btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*torqueAxis1; - { -#ifdef COMPUTE_IMPULSE_DENOM - btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB); - btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB); -#else - btVector3 vec; - vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); - btScalar denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec); - vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2); - btScalar denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec); -#endif //COMPUTE_IMPULSE_DENOM - - btScalar denom = relaxation/(denom0+denom1); - solverConstraint.m_jacDiagABInv = denom; - } - - solverConstraint.m_contactNormal = cp.m_normalWorldOnB; - solverConstraint.m_relpos1CrossNormal = rel_pos1.cross(cp.m_normalWorldOnB); - solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(cp.m_normalWorldOnB); - - - btVector3 vel1 = rb0->getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = rb1->getVelocityInLocalPoint(rel_pos2); - - vel = vel1 - vel2; - - rel_vel = cp.m_normalWorldOnB.dot(vel); - - - solverConstraint.m_penetration = cp.getDistance();///btScalar(infoGlobal.m_numIterations); - solverConstraint.m_friction = cp.m_combinedFriction; - solverConstraint.m_restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); - if (solverConstraint.m_restitution <= btScalar(0.)) - { - solverConstraint.m_restitution = 0.f; - }; - - btScalar penVel = -solverConstraint.m_penetration/infoGlobal.m_timeStep; - solverConstraint.m_penetration *= -(infoGlobal.m_erp/infoGlobal.m_timeStep); - - if (solverConstraint.m_restitution > penVel) - { - solverConstraint.m_penetration = btScalar(0.); - } - - - - solverConstraint.m_appliedImpulse = 0.f; - solverConstraint.m_appliedVelocityImpulse = 0.f; - - - - } - - - { - btVector3 frictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; - btScalar lat_rel_vel = frictionDir1.length2(); - if (lat_rel_vel > SIMD_EPSILON)//0.0f) - { - frictionDir1 /= btSqrt(lat_rel_vel); - addFrictionConstraint(frictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation); - btVector3 frictionDir2 = frictionDir1.cross(cp.m_normalWorldOnB); - frictionDir2.normalize();//?? - addFrictionConstraint(frictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation); - } else - { - //re-calculate friction direction every frame, todo: check if this is really needed - btVector3 frictionDir1,frictionDir2; - btPlaneSpace1(cp.m_normalWorldOnB,frictionDir1,frictionDir2); - addFrictionConstraint(frictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation); - addFrictionConstraint(frictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,rb0,rb1, relaxation); - } - - } - } - } - } - } - } - END_PROFILE("gatherSolverData"); - - BEGIN_PROFILE("prepareConstraints"); - - btContactSolverInfo info = infoGlobal; - - { - int j; - for (j=0;jbuildJacobian(); - } - } - - - - int numConstraintPool = m_tmpSolverConstraintPool.size(); - int numFrictionPool = m_tmpSolverFrictionConstraintPool.size(); - - ///todo: use stack allocator for such temporarily memory, same for solver bodies/constraints - m_orderTmpConstraintPool.resize(numConstraintPool); - m_orderFrictionConstraintPool.resize(numFrictionPool); - { - int i; - for (i=0;igetRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) - { - m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].writebackVelocity(); - } - if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) - { - m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); - } - - constraint->solveConstraint(infoGlobal.m_timeStep); - - if ((constraint->getRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) - { - m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].readVelocity(); - } - if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) - { - m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); - } - - } - - { - int numPoolConstraints = m_tmpSolverConstraintPool.size(); - for (j=0;jgetNumContacts();p++) - { - gOrder[totalPoints].m_manifoldIndex = j; - gOrder[totalPoints].m_pointIndex = p; - totalPoints++; - } - } - } - - { - int j; - for (j=0;jbuildJacobian(); - } - } - - END_PROFILE("prepareConstraints"); - - - BEGIN_PROFILE("solveConstraints"); - - //should traverse the contacts random order... - int iteration; - - { - for ( iteration = 0;iterationsolveConstraint(info.m_timeStep); - } - - for (j=0;jgetBody0(), - (btRigidBody*)manifold->getBody1() - ,manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); - } - - for (j=0;jgetBody0(), - (btRigidBody*)manifold->getBody1(),manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); - } - - } - } - - END_PROFILE("solveConstraints"); - - -#ifdef USE_PROFILE - btProfiler::endBlock("solve"); -#endif //USE_PROFILE - - - - - return btScalar(0.); -} - - - - - - - -void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer) -{ - - (void)debugDrawer; - - btRigidBody* body0 = (btRigidBody*)manifoldPtr->getBody0(); - btRigidBody* body1 = (btRigidBody*)manifoldPtr->getBody1(); - - - //only necessary to refresh the manifold once (first iteration). The integration is done outside the loop - { -#ifdef FORCE_REFESH_CONTACT_MANIFOLDS - manifoldPtr->refreshContactPoints(body0->getCenterOfMassTransform(),body1->getCenterOfMassTransform()); -#endif //FORCE_REFESH_CONTACT_MANIFOLDS - int numpoints = manifoldPtr->getNumContacts(); - - gTotalContactPoints += numpoints; - - btVector3 color(0,1,0); - for (int i=0;igetContactPoint(i); - if (cp.getDistance() <= btScalar(0.)) - { - const btVector3& pos1 = cp.getPositionWorldOnA(); - const btVector3& pos2 = cp.getPositionWorldOnB(); - - btVector3 rel_pos1 = pos1 - body0->getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - body1->getCenterOfMassPosition(); - - - //this jacobian entry is re-used for all iterations - btJacobianEntry jac(body0->getCenterOfMassTransform().getBasis().transpose(), - body1->getCenterOfMassTransform().getBasis().transpose(), - rel_pos1,rel_pos2,cp.m_normalWorldOnB,body0->getInvInertiaDiagLocal(),body0->getInvMass(), - body1->getInvInertiaDiagLocal(),body1->getInvMass()); - - - btScalar jacDiagAB = jac.getDiagonal(); - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; - if (cpd) - { - //might be invalid - cpd->m_persistentLifeTime++; - if (cpd->m_persistentLifeTime != cp.getLifeTime()) - { - //printf("Invalid: cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd->m_persistentLifeTime,cp.getLifeTime()); - new (cpd) btConstraintPersistentData; - cpd->m_persistentLifeTime = cp.getLifeTime(); - - } else - { - //printf("Persistent: cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd->m_persistentLifeTime,cp.getLifeTime()); - - } - } else - { - - //todo: should this be in a pool? - void* mem = btAlignedAlloc(sizeof(btConstraintPersistentData),16); - cpd = new (mem)btConstraintPersistentData; - assert(cpd); - - totalCpd ++; - //printf("totalCpd = %i Created Ptr %x\n",totalCpd,cpd); - cp.m_userPersistentData = cpd; - cpd->m_persistentLifeTime = cp.getLifeTime(); - //printf("CREATED: %x . cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd,cpd->m_persistentLifeTime,cp.getLifeTime()); - - } - assert(cpd); - - cpd->m_jacDiagABInv = btScalar(1.) / jacDiagAB; - - //Dependent on Rigidbody A and B types, fetch the contact/friction response func - //perhaps do a similar thing for friction/restutution combiner funcs... - - cpd->m_frictionSolverFunc = m_frictionDispatch[body0->m_frictionSolverType][body1->m_frictionSolverType]; - cpd->m_contactSolverFunc = m_contactDispatch[body0->m_contactSolverType][body1->m_contactSolverType]; - - btVector3 vel1 = body0->getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body1->getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; - rel_vel = cp.m_normalWorldOnB.dot(vel); - - btScalar combinedRestitution = cp.m_combinedRestitution; - - cpd->m_penetration = cp.getDistance();///btScalar(info.m_numIterations); - cpd->m_friction = cp.m_combinedFriction; - cpd->m_restitution = restitutionCurve(rel_vel, combinedRestitution); - if (cpd->m_restitution <= btScalar(0.)) - { - cpd->m_restitution = btScalar(0.0); - - }; - - //restitution and penetration work in same direction so - //rel_vel - - btScalar penVel = -cpd->m_penetration/info.m_timeStep; - - if (cpd->m_restitution > penVel) - { - cpd->m_penetration = btScalar(0.); - } - - - btScalar relaxation = info.m_damping; - if (m_solverMode & SOLVER_USE_WARMSTARTING) - { - cpd->m_appliedImpulse *= relaxation; - } else - { - cpd->m_appliedImpulse =btScalar(0.); - } - - //for friction - cpd->m_prevAppliedImpulse = cpd->m_appliedImpulse; - - //re-calculate friction direction every frame, todo: check if this is really needed - btPlaneSpace1(cp.m_normalWorldOnB,cpd->m_frictionWorldTangential0,cpd->m_frictionWorldTangential1); - - -#define NO_FRICTION_WARMSTART 1 - - #ifdef NO_FRICTION_WARMSTART - cpd->m_accumulatedTangentImpulse0 = btScalar(0.); - cpd->m_accumulatedTangentImpulse1 = btScalar(0.); - #endif //NO_FRICTION_WARMSTART - btScalar denom0 = body0->computeImpulseDenominator(pos1,cpd->m_frictionWorldTangential0); - btScalar denom1 = body1->computeImpulseDenominator(pos2,cpd->m_frictionWorldTangential0); - btScalar denom = relaxation/(denom0+denom1); - cpd->m_jacDiagABInvTangent0 = denom; - - - denom0 = body0->computeImpulseDenominator(pos1,cpd->m_frictionWorldTangential1); - denom1 = body1->computeImpulseDenominator(pos2,cpd->m_frictionWorldTangential1); - denom = relaxation/(denom0+denom1); - cpd->m_jacDiagABInvTangent1 = denom; - - btVector3 totalImpulse = - #ifndef NO_FRICTION_WARMSTART - cpd->m_frictionWorldTangential0*cpd->m_accumulatedTangentImpulse0+ - cpd->m_frictionWorldTangential1*cpd->m_accumulatedTangentImpulse1+ - #endif //NO_FRICTION_WARMSTART - cp.m_normalWorldOnB*cpd->m_appliedImpulse; - - - - /// - { - btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); - cpd->m_angularComponentA = body0->getInvInertiaTensorWorld()*torqueAxis0; - btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); - cpd->m_angularComponentB = body1->getInvInertiaTensorWorld()*torqueAxis1; - } - { - btVector3 ftorqueAxis0 = rel_pos1.cross(cpd->m_frictionWorldTangential0); - cpd->m_frictionAngularComponent0A = body0->getInvInertiaTensorWorld()*ftorqueAxis0; - } - { - btVector3 ftorqueAxis1 = rel_pos1.cross(cpd->m_frictionWorldTangential1); - cpd->m_frictionAngularComponent1A = body0->getInvInertiaTensorWorld()*ftorqueAxis1; - } - { - btVector3 ftorqueAxis0 = rel_pos2.cross(cpd->m_frictionWorldTangential0); - cpd->m_frictionAngularComponent0B = body1->getInvInertiaTensorWorld()*ftorqueAxis0; - } - { - btVector3 ftorqueAxis1 = rel_pos2.cross(cpd->m_frictionWorldTangential1); - cpd->m_frictionAngularComponent1B = body1->getInvInertiaTensorWorld()*ftorqueAxis1; - } - - /// - - - - //apply previous frames impulse on both bodies - body0->applyImpulse(totalImpulse, rel_pos1); - body1->applyImpulse(-totalImpulse, rel_pos2); - } - - } - } -} - - -btScalar btSequentialImpulseConstraintSolver::solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) -{ - btScalar maxImpulse = btScalar(0.); - - { - - btVector3 color(0,1,0); - { - if (cp.getDistance() <= btScalar(0.)) - { - - if (iter == 0) - { - if (debugDrawer) - debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); - } - - { - - //btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; - btScalar impulse = resolveSingleCollisionCombined( - *body0,*body1, - cp, - info); - - if (maxImpulse < impulse) - maxImpulse = impulse; - - } - } - } - } - return maxImpulse; -} - - - -btScalar btSequentialImpulseConstraintSolver::solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) -{ - - btScalar maxImpulse = btScalar(0.); - - { - - btVector3 color(0,1,0); - { - if (cp.getDistance() <= btScalar(0.)) - { - - if (iter == 0) - { - if (debugDrawer) - debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); - } - - { - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; - btScalar impulse = cpd->m_contactSolverFunc( - *body0,*body1, - cp, - info); - - if (maxImpulse < impulse) - maxImpulse = impulse; - - } - } - } - } - return maxImpulse; -} - -btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) -{ - - (void)debugDrawer; - (void)iter; - - - { - - btVector3 color(0,1,0); - { - - if (cp.getDistance() <= btScalar(0.)) - { - - btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; - cpd->m_frictionSolverFunc( - *body0,*body1, - cp, - info); - - - } - } - - - } - return btScalar(0.); -} - - -void btSequentialImpulseConstraintSolver::reset() -{ - m_btSeed2 = 0; -} - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h deleted file mode 100644 index 83a96d4dc44..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h +++ /dev/null @@ -1,126 +0,0 @@ -/* -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. -*/ - -#ifndef SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H -#define SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H - -#include "btConstraintSolver.h" -class btIDebugDraw; -#include "btContactConstraint.h" -#include "btSolverBody.h" -#include "btSolverConstraint.h" - - -/// btSequentialImpulseConstraintSolver uses a Propagation Method and Sequentially applies impulses -/// The approach is the 3D version of Erin Catto's GDC 2006 tutorial. See http://www.gphysics.com -/// Although Sequential Impulse is more intuitive, it is mathematically equivalent to Projected Successive Overrelaxation (iterative LCP) -/// Applies impulses for combined restitution and penetration recovery and to simulate friction -class btSequentialImpulseConstraintSolver : public btConstraintSolver -{ - - btAlignedObjectArray m_tmpSolverBodyPool; - btAlignedObjectArray m_tmpSolverConstraintPool; - btAlignedObjectArray m_tmpSolverFrictionConstraintPool; - btAlignedObjectArray m_orderTmpConstraintPool; - btAlignedObjectArray m_orderFrictionConstraintPool; - - -protected: - btScalar solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); - btScalar solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); - void prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer); - void addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btRigidBody* rb0,btRigidBody* rb1, btScalar relaxation); - - ContactSolverFunc m_contactDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; - ContactSolverFunc m_frictionDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; - - //choose between several modes, different friction model etc. - int m_solverMode; - ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction - unsigned long m_btSeed2; - -public: - - enum eSolverMode - { - SOLVER_RANDMIZE_ORDER = 1, - SOLVER_FRICTION_SEPARATE = 2, - SOLVER_USE_WARMSTARTING = 4, - SOLVER_CACHE_FRIENDLY = 8 - }; - - btSequentialImpulseConstraintSolver(); - - ///Advanced: Override the default contact solving function for contacts, for certain types of rigidbody - ///See btRigidBody::m_contactSolverType and btRigidBody::m_frictionSolverType - void setContactSolverFunc(ContactSolverFunc func,int type0,int type1) - { - m_contactDispatch[type0][type1] = func; - } - - ///Advanced: Override the default friction solving function for contacts, for certain types of rigidbody - ///See btRigidBody::m_contactSolverType and btRigidBody::m_frictionSolverType - void SetFrictionSolverFunc(ContactSolverFunc func,int type0,int type1) - { - m_frictionDispatch[type0][type1] = func; - } - - virtual ~btSequentialImpulseConstraintSolver(); - - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher); - - virtual btScalar solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); - btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); - btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); - - - ///clear internal cached data and reset random seed - virtual void reset(); - - btScalar solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); - - - void setSolverMode(int mode) - { - m_solverMode = mode; - } - - int getSolverMode() const - { - return m_solverMode; - } - - unsigned long btRand2(); - - int btRandInt2 (int n); - - void setRandSeed(unsigned long seed) - { - m_btSeed2 = seed; - } - unsigned long getRandSeed() const - { - return m_btSeed2; - } - -}; - -#ifndef BT_PREFER_SIMD -typedef btSequentialImpulseConstraintSolver btSequentialImpulseConstraintSolverPrefered; -#endif - - -#endif //SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp deleted file mode 100644 index 0c7dbd668bb..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* -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. -*/ - - - -#include "btSolve2LinearConstraint.h" - -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "LinearMath/btVector3.h" -#include "btJacobianEntry.h" - - -void btSolve2LinearConstraint::resolveUnilateralPairConstraint( - btRigidBody* body1, - btRigidBody* body2, - - const btMatrix3x3& world2A, - const btMatrix3x3& world2B, - - const btVector3& invInertiaADiag, - const btScalar invMassA, - const btVector3& linvelA,const btVector3& angvelA, - const btVector3& rel_posA1, - const btVector3& invInertiaBDiag, - const btScalar invMassB, - const btVector3& linvelB,const btVector3& angvelB, - const btVector3& rel_posA2, - - btScalar depthA, const btVector3& normalA, - const btVector3& rel_posB1,const btVector3& rel_posB2, - btScalar depthB, const btVector3& normalB, - btScalar& imp0,btScalar& imp1) -{ - (void)linvelA; - (void)linvelB; - (void)angvelB; - (void)angvelA; - - - - imp0 = btScalar(0.); - imp1 = btScalar(0.); - - btScalar len = btFabs(normalA.length()) - btScalar(1.); - if (btFabs(len) >= SIMD_EPSILON) - return; - - btAssert(len < SIMD_EPSILON); - - - //this jacobian entry could be re-used for all iterations - btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA, - invInertiaBDiag,invMassB); - btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA, - invInertiaBDiag,invMassB); - - //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); - //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); - - const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1)); - const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1)); - -// btScalar penetrationImpulse = (depth*contactTau*timeCorrection) * massTerm;//jacDiagABInv - btScalar massTerm = btScalar(1.) / (invMassA + invMassB); - - - // calculate rhs (or error) terms - const btScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping; - const btScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping; - - - // dC/dv * dv = -C - - // jacobian * impulse = -error - // - - //impulse = jacobianInverse * -error - - // inverting 2x2 symmetric system (offdiagonal are equal!) - // - - - btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB); - btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag ); - - //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; - //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; - - imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; - imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; - - //[a b] [d -c] - //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc) - - //[jA nD] * [imp0] = [dv0] - //[nD jB] [imp1] [dv1] - -} - - - -void btSolve2LinearConstraint::resolveBilateralPairConstraint( - btRigidBody* body1, - btRigidBody* body2, - const btMatrix3x3& world2A, - const btMatrix3x3& world2B, - - const btVector3& invInertiaADiag, - const btScalar invMassA, - const btVector3& linvelA,const btVector3& angvelA, - const btVector3& rel_posA1, - const btVector3& invInertiaBDiag, - const btScalar invMassB, - const btVector3& linvelB,const btVector3& angvelB, - const btVector3& rel_posA2, - - btScalar depthA, const btVector3& normalA, - const btVector3& rel_posB1,const btVector3& rel_posB2, - btScalar depthB, const btVector3& normalB, - btScalar& imp0,btScalar& imp1) -{ - - (void)linvelA; - (void)linvelB; - (void)angvelA; - (void)angvelB; - - - - imp0 = btScalar(0.); - imp1 = btScalar(0.); - - btScalar len = btFabs(normalA.length()) - btScalar(1.); - if (btFabs(len) >= SIMD_EPSILON) - return; - - btAssert(len < SIMD_EPSILON); - - - //this jacobian entry could be re-used for all iterations - btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA, - invInertiaBDiag,invMassB); - btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA, - invInertiaBDiag,invMassB); - - //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); - //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); - - const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1)); - const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1)); - - // calculate rhs (or error) terms - const btScalar dv0 = depthA * m_tau - vel0 * m_damping; - const btScalar dv1 = depthB * m_tau - vel1 * m_damping; - - // dC/dv * dv = -C - - // jacobian * impulse = -error - // - - //impulse = jacobianInverse * -error - - // inverting 2x2 symmetric system (offdiagonal are equal!) - // - - - btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB); - btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag ); - - //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; - //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; - - imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; - imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; - - //[a b] [d -c] - //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc) - - //[jA nD] * [imp0] = [dv0] - //[nD jB] [imp1] [dv1] - - if ( imp0 > btScalar(0.0)) - { - if ( imp1 > btScalar(0.0) ) - { - //both positive - } - else - { - imp1 = btScalar(0.); - - // now imp0>0 imp1<0 - imp0 = dv0 / jacA.getDiagonal(); - if ( imp0 > btScalar(0.0) ) - { - } else - { - imp0 = btScalar(0.); - } - } - } - else - { - imp0 = btScalar(0.); - - imp1 = dv1 / jacB.getDiagonal(); - if ( imp1 <= btScalar(0.0) ) - { - imp1 = btScalar(0.); - // now imp0>0 imp1<0 - imp0 = dv0 / jacA.getDiagonal(); - if ( imp0 > btScalar(0.0) ) - { - } else - { - imp0 = btScalar(0.); - } - } else - { - } - } -} - - -/* -void btSolve2LinearConstraint::resolveAngularConstraint( const btMatrix3x3& invInertiaAWS, - const btScalar invMassA, - const btVector3& linvelA,const btVector3& angvelA, - const btVector3& rel_posA1, - const btMatrix3x3& invInertiaBWS, - const btScalar invMassB, - const btVector3& linvelB,const btVector3& angvelB, - const btVector3& rel_posA2, - - btScalar depthA, const btVector3& normalA, - const btVector3& rel_posB1,const btVector3& rel_posB2, - btScalar depthB, const btVector3& normalB, - btScalar& imp0,btScalar& imp1) -{ - -} -*/ - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h deleted file mode 100644 index 057d3fac827..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -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. -*/ - -#ifndef SOLVE_2LINEAR_CONSTRAINT_H -#define SOLVE_2LINEAR_CONSTRAINT_H - -#include "LinearMath/btMatrix3x3.h" -#include "LinearMath/btVector3.h" - - -class btRigidBody; - - - -/// constraint class used for lateral tyre friction. -class btSolve2LinearConstraint -{ - btScalar m_tau; - btScalar m_damping; - -public: - - btSolve2LinearConstraint(btScalar tau,btScalar damping) - { - m_tau = tau; - m_damping = damping; - } - // - // solve unilateral constraint (equality, direct method) - // - void resolveUnilateralPairConstraint( - btRigidBody* body0, - btRigidBody* body1, - - const btMatrix3x3& world2A, - const btMatrix3x3& world2B, - - const btVector3& invInertiaADiag, - const btScalar invMassA, - const btVector3& linvelA,const btVector3& angvelA, - const btVector3& rel_posA1, - const btVector3& invInertiaBDiag, - const btScalar invMassB, - const btVector3& linvelB,const btVector3& angvelB, - const btVector3& rel_posA2, - - btScalar depthA, const btVector3& normalA, - const btVector3& rel_posB1,const btVector3& rel_posB2, - btScalar depthB, const btVector3& normalB, - btScalar& imp0,btScalar& imp1); - - - // - // solving 2x2 lcp problem (inequality, direct solution ) - // - void resolveBilateralPairConstraint( - btRigidBody* body0, - btRigidBody* body1, - const btMatrix3x3& world2A, - const btMatrix3x3& world2B, - - const btVector3& invInertiaADiag, - const btScalar invMassA, - const btVector3& linvelA,const btVector3& angvelA, - const btVector3& rel_posA1, - const btVector3& invInertiaBDiag, - const btScalar invMassB, - const btVector3& linvelB,const btVector3& angvelB, - const btVector3& rel_posA2, - - btScalar depthA, const btVector3& normalA, - const btVector3& rel_posB1,const btVector3& rel_posB2, - btScalar depthB, const btVector3& normalB, - btScalar& imp0,btScalar& imp1); - -/* - void resolveAngularConstraint( const btMatrix3x3& invInertiaAWS, - const btScalar invMassA, - const btVector3& linvelA,const btVector3& angvelA, - const btVector3& rel_posA1, - const btMatrix3x3& invInertiaBWS, - const btScalar invMassB, - const btVector3& linvelB,const btVector3& angvelB, - const btVector3& rel_posA2, - - btScalar depthA, const btVector3& normalA, - const btVector3& rel_posB1,const btVector3& rel_posB2, - btScalar depthB, const btVector3& normalB, - btScalar& imp0,btScalar& imp1); - -*/ - -}; - -#endif //SOLVE_2LINEAR_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h deleted file mode 100644 index 21305b3164e..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -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. -*/ - -#ifndef BT_SOLVER_BODY_H -#define BT_SOLVER_BODY_H - -class btRigidBody; -#include "LinearMath/btVector3.h" -#include "LinearMath/btMatrix3x3.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "LinearMath/btAlignedAllocator.h" - - -///btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance. -ATTRIBUTE_ALIGNED16 (struct) btSolverBody -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btVector3 m_angularVelocity; - float m_angularFactor; - float m_invMass; - float m_friction; - btRigidBody* m_originalBody; - btVector3 m_linearVelocity; - btVector3 m_centerOfMassPosition; - - SIMD_FORCE_INLINE void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const - { - velocity = m_linearVelocity + m_angularVelocity.cross(rel_pos); - } - - //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) - { - m_linearVelocity += linearComponent*impulseMagnitude; - m_angularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); - } - - void writebackVelocity() - { - if (m_invMass) - { - m_originalBody->setLinearVelocity(m_linearVelocity); - m_originalBody->setAngularVelocity(m_angularVelocity); - //m_originalBody->setCompanionId(-1); - } - } - - void readVelocity() - { - if (m_invMass) - { - m_linearVelocity = m_originalBody->getLinearVelocity(); - m_angularVelocity = m_originalBody->getAngularVelocity(); - } - } - - - - -}; - -#endif //BT_SOLVER_BODY_H - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h deleted file mode 100644 index a750560d33c..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h +++ /dev/null @@ -1,69 +0,0 @@ - - -/* -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. -*/ - -#ifndef BT_SOLVER_CONSTRAINT_H -#define BT_SOLVER_CONSTRAINT_H - -class btRigidBody; -#include "LinearMath/btVector3.h" -#include "LinearMath/btMatrix3x3.h" - -//#define NO_FRICTION_TANGENTIALS 1 - -///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints. -ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btVector3 m_relpos1CrossNormal; - btVector3 m_contactNormal; - - btVector3 m_relpos2CrossNormal; - btVector3 m_angularComponentA; - - btVector3 m_angularComponentB; - mutable btScalar m_appliedVelocityImpulse; - mutable btScalar m_appliedImpulse; - int m_solverBodyIdA; - int m_solverBodyIdB; - - btScalar m_friction; - btScalar m_restitution; - btScalar m_jacDiagABInv; - btScalar m_penetration; - - - - int m_constraintType; - int m_frictionIndex; - int m_unusedPadding[2]; - - enum btSolverConstraintType - { - BT_SOLVER_CONTACT_1D = 0, - BT_SOLVER_FRICTION_1D - }; -}; - - - - - - -#endif //BT_SOLVER_CONSTRAINT_H - - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp deleted file mode 100644 index 6e8b552dbbc..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* -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. -*/ - - -#include "btTypedConstraint.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" - -static btRigidBody s_fixed(0, 0,0); - -btTypedConstraint::btTypedConstraint(btTypedConstraintType type) -:m_userConstraintType(-1), -m_userConstraintId(-1), -m_constraintType (type), -m_rbA(s_fixed), -m_rbB(s_fixed), -m_appliedImpulse(btScalar(0.)) -{ - s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); -} -btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA) -:m_userConstraintType(-1), -m_userConstraintId(-1), -m_constraintType (type), -m_rbA(rbA), -m_rbB(s_fixed), -m_appliedImpulse(btScalar(0.)) -{ - s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); - -} - - -btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB) -:m_userConstraintType(-1), -m_userConstraintId(-1), -m_constraintType (type), -m_rbA(rbA), -m_rbB(rbB), -m_appliedImpulse(btScalar(0.)) -{ - s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); - -} - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h deleted file mode 100644 index 745d0afde6d..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -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. -*/ - -#ifndef TYPED_CONSTRAINT_H -#define TYPED_CONSTRAINT_H - -class btRigidBody; -#include "LinearMath/btScalar.h" - -enum btTypedConstraintType -{ - POINT2POINT_CONSTRAINT_TYPE, - HINGE_CONSTRAINT_TYPE, - CONETWIST_CONSTRAINT_TYPE, - D6_CONSTRAINT_TYPE, - VEHICLE_CONSTRAINT_TYPE -}; - -///TypedConstraint is the baseclass for Bullet constraints and vehicles -class btTypedConstraint -{ - int m_userConstraintType; - int m_userConstraintId; - - btTypedConstraintType m_constraintType; - - btTypedConstraint& operator=(btTypedConstraint& other) - { - btAssert(0); - (void) other; - return *this; - } - -protected: - btRigidBody& m_rbA; - btRigidBody& m_rbB; - btScalar m_appliedImpulse; - - -public: - - btTypedConstraint(btTypedConstraintType type); - virtual ~btTypedConstraint() {}; - btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA); - - btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); - - virtual void buildJacobian() = 0; - - virtual void solveConstraint(btScalar timeStep) = 0; - - const btRigidBody& getRigidBodyA() const - { - return m_rbA; - } - const btRigidBody& getRigidBodyB() const - { - return m_rbB; - } - - btRigidBody& getRigidBodyA() - { - return m_rbA; - } - btRigidBody& getRigidBodyB() - { - return m_rbB; - } - - int getUserConstraintType() const - { - return m_userConstraintType ; - } - - void setUserConstraintType(int userConstraintType) - { - m_userConstraintType = userConstraintType; - }; - - void setUserConstraintId(int uid) - { - m_userConstraintId = uid; - } - - int getUserConstraintId() const - { - return m_userConstraintId; - } - btScalar getAppliedImpulse() const - { - return m_appliedImpulse; - } - - btTypedConstraintType getConstraintType () const - { - return m_constraintType; - } -}; - -#endif //TYPED_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp deleted file mode 100644 index 248c582dcd8..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* -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 -*/ - -#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]) -{ - btVector3 vp(p1[0], p1[1], p1[2]); - btTriangleShape trishapeA(vp, - btVector3(p2[0], p2[1], p2[2]), - btVector3(p3[0], p3[1], p3[2])); - trishapeA.setMargin(0.000001f); - btVector3 vq(q1[0], q1[1], q1[2]); - btTriangleShape trishapeB(vq, - 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; -} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp deleted file mode 100644 index 4051d3f3e1f..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#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; -} - - diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp deleted file mode 100644 index 5e330cb64f2..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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. -*/ - - -#include "btContinuousDynamicsWorld.h" -#include "LinearMath/btQuickprof.h" - -//collision detection -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" -#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" - -//rigidbody & constraints -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" -#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" -#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" - - - -#include - -btContinuousDynamicsWorld::btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) -:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) -{ -} - -btContinuousDynamicsWorld::~btContinuousDynamicsWorld() -{ -} - - -void btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) -{ - - startProfiling(timeStep); - - ///update aabbs information - updateAabbs(); - //static int frame=0; -// printf("frame %d\n",frame++); - - ///apply gravity, predict motion - predictUnconstraintMotion(timeStep); - - btDispatcherInfo& dispatchInfo = getDispatchInfo(); - - dispatchInfo.m_timeStep = timeStep; - dispatchInfo.m_stepCount = 0; - dispatchInfo.m_debugDraw = getDebugDrawer(); - - ///perform collision detection - performDiscreteCollisionDetection(); - - calculateSimulationIslands(); - - - getSolverInfo().m_timeStep = timeStep; - - - - ///solve contact and other joint constraints - solveConstraints(getSolverInfo()); - - ///CallbackTriggers(); - - calculateTimeOfImpacts(timeStep); - - btScalar toi = dispatchInfo.m_timeOfImpact; -// if (toi < 1.f) -// printf("toi = %f\n",toi); - if (toi < 0.f) - printf("toi = %f\n",toi); - - - ///integrate transforms - integrateTransforms(timeStep * toi); - - ///update vehicle simulation - updateVehicles(timeStep); - - - updateActivationState( timeStep ); - -} - -void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep) -{ - ///these should be 'temporal' aabbs! - updateTemporalAabbs(timeStep); - - ///'toi' is the global smallest time of impact. However, we just calculate the time of impact for each object individually. - ///so we handle the case moving versus static properly, and we cheat for moving versus moving - float toi = 1.f; - - - btDispatcherInfo& dispatchInfo = getDispatchInfo(); - dispatchInfo.m_timeStep = timeStep; - dispatchInfo.m_timeOfImpact = 1.f; - dispatchInfo.m_stepCount = 0; - dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_CONTINUOUS; - - ///calculate time of impact for overlapping pairs - - BEGIN_PROFILE("performContinuousCollisionDetection"); - - btDispatcher* dispatcher = getDispatcher(); - if (dispatcher) - dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); - - END_PROFILE("performContinuousCollisionDetection"); - - toi = dispatchInfo.m_timeOfImpact; - - dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE; - -} - -void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep) -{ - BEGIN_PROFILE("perform Temporal Broadphase Collision Detection"); - - btVector3 temporalAabbMin,temporalAabbMax; - - for ( int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),temporalAabbMin,temporalAabbMax); - const btVector3& linvel = body->getLinearVelocity(); - - //make the AABB temporal - float temporalAabbMaxx = temporalAabbMax.getX(); - float temporalAabbMaxy = temporalAabbMax.getY(); - float temporalAabbMaxz = temporalAabbMax.getZ(); - float temporalAabbMinx = temporalAabbMin.getX(); - float temporalAabbMiny = temporalAabbMin.getY(); - float temporalAabbMinz = temporalAabbMin.getZ(); - - // add linear motion - btVector3 linMotion = linvel*timeStep; - - if (linMotion.x() > 0.f) - temporalAabbMaxx += linMotion.x(); - else - temporalAabbMinx += linMotion.x(); - if (linMotion.y() > 0.f) - temporalAabbMaxy += linMotion.y(); - else - temporalAabbMiny += linMotion.y(); - if (linMotion.z() > 0.f) - temporalAabbMaxz += linMotion.z(); - else - temporalAabbMinz += linMotion.z(); - - //add conservative angular motion - btScalar angularMotion(0);// = angvel.length() * GetAngularMotionDisc() * timeStep; - btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion); - temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz); - temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz); - - temporalAabbMin -= angularMotion3d; - temporalAabbMax += angularMotion3d; - - m_broadphasePairCache->setAabb(body->getBroadphaseHandle(),temporalAabbMin,temporalAabbMax,m_dispatcher1); - } - } - - //update aabb (of all moved objects) - - m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); - - END_PROFILE("perform Temporal Broadphase Collision Detection"); - - -} - - diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h deleted file mode 100644 index 61c8dea03eb..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 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. -*/ - -#ifndef BT_CONTINUOUS_DYNAMICS_WORLD_H -#define BT_CONTINUOUS_DYNAMICS_WORLD_H - -#include "btDiscreteDynamicsWorld.h" - -///btContinuousDynamicsWorld adds optional (per object) continuous collision detection for fast moving objects to the btDiscreteDynamicsWorld. -///This copes with fast moving objects that otherwise would tunnel/miss collisions. -///Under construction, don't use yet! Please use btDiscreteDynamicsWorld instead. -class btContinuousDynamicsWorld : public btDiscreteDynamicsWorld -{ - - void updateTemporalAabbs(btScalar timeStep); - - public: - - btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); - virtual ~btContinuousDynamicsWorld(); - - ///time stepping with calculation of time of impact for selected fast moving objects - virtual void internalSingleStepSimulation( btScalar timeStep); - - virtual void calculateTimeOfImpacts(btScalar timeStep); - - virtual btDynamicsWorldType getWorldType() const - { - return BT_CONTINUOUS_DYNAMICS_WORLD; - } - -}; - -#endif //BT_CONTINUOUS_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp deleted file mode 100644 index 88b11c878c5..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ /dev/null @@ -1,1004 +0,0 @@ -/* -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. -*/ - - -#include "btDiscreteDynamicsWorld.h" - -//collision detection -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" -#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" -#include - -//rigidbody & constraints -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" -#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" -#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" - -//for debug rendering -#include "BulletCollision/CollisionShapes/btBoxShape.h" -#include "BulletCollision/CollisionShapes/btCapsuleShape.h" -#include "BulletCollision/CollisionShapes/btCompoundShape.h" -#include "BulletCollision/CollisionShapes/btConeShape.h" -#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btCylinderShape.h" -#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" -#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionShapes/btTriangleCallback.h" -#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" -#include "LinearMath/btIDebugDraw.h" - - - -//vehicle -#include "BulletDynamics/Vehicle/btRaycastVehicle.h" -#include "BulletDynamics/Vehicle/btVehicleRaycaster.h" -#include "BulletDynamics/Vehicle/btWheelInfo.h" -#include "LinearMath/btIDebugDraw.h" -#include "LinearMath/btQuickprof.h" -#include "LinearMath/btMotionState.h" - - - - - -btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration) -:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), -m_constraintSolver(constraintSolver), -m_debugDrawer(0), -m_gravity(0,-10,0), -m_localTime(btScalar(1.)/btScalar(60.)), -m_profileTimings(0) -{ - if (!m_constraintSolver) - { - void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); - m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver; - m_ownsConstraintSolver = true; - } else - { - m_ownsConstraintSolver = false; - } - - { - void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16); - m_islandManager = new (mem) btSimulationIslandManager(); - } - - m_ownsIslandManager = true; -} - - -btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld() -{ - //only delete it when we created it - if (m_ownsIslandManager) - { - m_islandManager->~btSimulationIslandManager(); - btAlignedFree( m_islandManager); - } - if (m_ownsConstraintSolver) - { - - m_constraintSolver->~btConstraintSolver(); - btAlignedFree(m_constraintSolver); - } -} - -void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) -{ - - for (int i=0;igetActivationState() != ISLAND_SLEEPING) - { - if (body->isKinematicObject()) - { - //to calculate velocities next frame - body->saveKinematicState(timeStep); - } - } - } - } -} - -void btDiscreteDynamicsWorld::synchronizeMotionStates() -{ - //debug vehicle wheels - - - { - //todo: iterate over awake simulation islands! - for ( int i=0;igetDebugMode() & btIDebugDraw::DBG_DrawWireframe) - { - btVector3 color(btScalar(255.),btScalar(255.),btScalar(255.)); - switch(colObj->getActivationState()) - { - case ACTIVE_TAG: - color = btVector3(btScalar(255.),btScalar(255.),btScalar(255.)); break; - case ISLAND_SLEEPING: - color = btVector3(btScalar(0.),btScalar(255.),btScalar(0.));break; - case WANTS_DEACTIVATION: - color = btVector3(btScalar(0.),btScalar(255.),btScalar(255.));break; - case DISABLE_DEACTIVATION: - color = btVector3(btScalar(255.),btScalar(0.),btScalar(0.));break; - case DISABLE_SIMULATION: - color = btVector3(btScalar(255.),btScalar(255.),btScalar(0.));break; - default: - { - color = btVector3(btScalar(255.),btScalar(0.),btScalar(0.)); - } - }; - - debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color); - } - btRigidBody* body = btRigidBody::upcast(colObj); - if (body && body->getMotionState() && !body->isStaticOrKinematicObject()) - { - //we need to call the update at least once, even for sleeping objects - //otherwise the 'graphics' transform never updates properly - //so todo: add 'dirty' flag - //if (body->getActivationState() != ISLAND_SLEEPING) - { - btTransform interpolatedTransform; - btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), - body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime,interpolatedTransform); - body->getMotionState()->setWorldTransform(interpolatedTransform); - } - } - } - } - - if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe) - { - for ( int i=0;im_vehicles.size();i++) - { - for (int v=0;vgetNumWheels();v++) - { - btVector3 wheelColor(0,255,255); - if (m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_isInContact) - { - wheelColor.setValue(0,0,255); - } else - { - wheelColor.setValue(255,0,255); - } - - //synchronize the wheels with the (interpolated) chassis worldtransform - m_vehicles[i]->updateWheelTransform(v,true); - - btVector3 wheelPosWS = m_vehicles[i]->getWheelInfo(v).m_worldTransform.getOrigin(); - - btVector3 axle = btVector3( - m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[0][m_vehicles[i]->getRightAxis()], - m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[1][m_vehicles[i]->getRightAxis()], - m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[2][m_vehicles[i]->getRightAxis()]); - - - //m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_wheelAxleWS - //debug wheels (cylinders) - m_debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); - m_debugDrawer->drawLine(wheelPosWS,m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); - - } - } - } - -} - - -int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) -{ - int numSimulationSubSteps = 0; - - if (maxSubSteps) - { - //fixed timestep with interpolation - m_localTime += timeStep; - if (m_localTime >= fixedTimeStep) - { - numSimulationSubSteps = int( m_localTime / fixedTimeStep); - m_localTime -= numSimulationSubSteps * fixedTimeStep; - } - } else - { - //variable timestep - fixedTimeStep = timeStep; - m_localTime = timeStep; - if (btFuzzyZero(timeStep)) - { - numSimulationSubSteps = 0; - maxSubSteps = 0; - } else - { - numSimulationSubSteps = 1; - maxSubSteps = 1; - } - } - - //process some debugging flags - if (getDebugDrawer()) - { - gDisableDeactivation = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0; - } - if (numSimulationSubSteps) - { - - saveKinematicState(fixedTimeStep); - - //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt - int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps; - - for (int i=0;isetGravity(gravity); - } - } -} - - -void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body) -{ - removeCollisionObject(body); -} - -void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body) -{ - if (!body->isStaticOrKinematicObject()) - { - body->setGravity(m_gravity); - } - - if (body->getCollisionShape()) - { - bool isDynamic = !(body->isStaticObject() || body->isKinematicObject()); - short collisionFilterGroup = isDynamic? short(btBroadphaseProxy::DefaultFilter) : short(btBroadphaseProxy::StaticFilter); - short collisionFilterMask = isDynamic? short(btBroadphaseProxy::AllFilter) : short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); - - addCollisionObject(body,collisionFilterGroup,collisionFilterMask); - } -} - -void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask) -{ - if (!body->isStaticOrKinematicObject()) - { - body->setGravity(m_gravity); - } - - if (body->getCollisionShape()) - { - addCollisionObject(body,group,mask); - } -} - - -void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep) -{ - BEGIN_PROFILE("updateVehicles"); - - for ( int i=0;iupdateVehicle( timeStep); - } - END_PROFILE("updateVehicles"); -} - -void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) -{ - BEGIN_PROFILE("updateActivationState"); - - for ( int i=0;iupdateDeactivation(timeStep); - - if (body->wantsSleeping()) - { - if (body->isStaticOrKinematicObject()) - { - body->setActivationState(ISLAND_SLEEPING); - } else - { - if (body->getActivationState() == ACTIVE_TAG) - body->setActivationState( WANTS_DEACTIVATION ); - } - } else - { - if (body->getActivationState() != DISABLE_DEACTIVATION) - body->setActivationState( ACTIVE_TAG ); - } - } - } - END_PROFILE("updateActivationState"); -} - -void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies) -{ - m_constraints.push_back(constraint); - if (disableCollisionsBetweenLinkedBodies) - { - constraint->getRigidBodyA().addConstraintRef(constraint); - constraint->getRigidBodyB().addConstraintRef(constraint); - } -} - -void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint) -{ - m_constraints.remove(constraint); - constraint->getRigidBodyA().removeConstraintRef(constraint); - constraint->getRigidBodyB().removeConstraintRef(constraint); -} - -void btDiscreteDynamicsWorld::addVehicle(btRaycastVehicle* vehicle) -{ - m_vehicles.push_back(vehicle); -} - -void btDiscreteDynamicsWorld::removeVehicle(btRaycastVehicle* vehicle) -{ - m_vehicles.remove(vehicle); -} - -SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs) -{ - int islandId; - - const btCollisionObject& rcolObj0 = lhs->getRigidBodyA(); - const btCollisionObject& rcolObj1 = lhs->getRigidBodyB(); - islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag(); - return islandId; - -} - - -class btSortConstraintOnIslandPredicate -{ - public: - - bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) - { - int rIslandId0,lIslandId0; - rIslandId0 = btGetConstraintIslandId(rhs); - lIslandId0 = btGetConstraintIslandId(lhs); - return lIslandId0 < rIslandId0; - } -}; - - - - -void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) -{ - - struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback - { - - btContactSolverInfo& m_solverInfo; - btConstraintSolver* m_solver; - btTypedConstraint** m_sortedConstraints; - int m_numConstraints; - btIDebugDraw* m_debugDrawer; - btStackAlloc* m_stackAlloc; - btDispatcher* m_dispatcher; - - InplaceSolverIslandCallback( - btContactSolverInfo& solverInfo, - btConstraintSolver* solver, - btTypedConstraint** sortedConstraints, - int numConstraints, - btIDebugDraw* debugDrawer, - btStackAlloc* stackAlloc, - btDispatcher* dispatcher) - :m_solverInfo(solverInfo), - m_solver(solver), - m_sortedConstraints(sortedConstraints), - m_numConstraints(numConstraints), - m_debugDrawer(debugDrawer), - m_stackAlloc(stackAlloc), - m_dispatcher(dispatcher) - { - - } - - InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other) - { - btAssert(0); - (void)other; - return *this; - } - virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId) - { - if (islandId<0) - { - ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id - m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); - } else - { - //also add all non-contact constraints/joints for this island - btTypedConstraint** startConstraint = 0; - int numCurConstraints = 0; - int i; - - //find the first constraint for this island - for (i=0;isolveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); - - } - } - - }; - - //sorted version of all btTypedConstraint, based on islandId - btAlignedObjectArray sortedConstraints; - sortedConstraints.resize( m_constraints.size()); - int i; - for (i=0;iprepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); - - /// solve all the constraints for this island - m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld()->getCollisionObjectArray(),&solverCallback); - - m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc); -} - - - - -void btDiscreteDynamicsWorld::calculateSimulationIslands() -{ - BEGIN_PROFILE("calculateSimulationIslands"); - - getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher()); - - { - int i; - int numConstraints = int(m_constraints.size()); - for (i=0;i< numConstraints ; i++ ) - { - btTypedConstraint* constraint = m_constraints[i]; - - const btRigidBody* colObj0 = &constraint->getRigidBodyA(); - const btRigidBody* colObj1 = &constraint->getRigidBodyB(); - - if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && - ((colObj1) && ((colObj1)->mergesSimulationIslands()))) - { - if (colObj0->isActive() || colObj1->isActive()) - { - - getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), - (colObj1)->getIslandTag()); - } - } - } - } - - //Store the island id in each body - getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld()); - - END_PROFILE("calculateSimulationIslands"); - -} - - -void btDiscreteDynamicsWorld::updateAabbs() -{ - BEGIN_PROFILE("updateAabbs"); - - btVector3 colorvec(1,0,0); - btTransform predictedTrans; - for ( int i=0;iIsActive() && (!body->IsStatic())) - { - btPoint3 minAabb,maxAabb; - colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); - btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; - - //moving objects should be moderately sized, probably something wrong if not - if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) - { - bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); - } else - { - //something went wrong, investigate - //this assert is unwanted in 3D modelers (danger of loosing work) - body->setActivationState(DISABLE_SIMULATION); - - static bool reportMe = true; - if (reportMe && m_debugDrawer) - { - reportMe = false; - m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); - m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); - m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); - m_debugDrawer->reportErrorWarning("Thanks.\n"); - } - - - } - if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) - { - m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); - } - } - } - } - - END_PROFILE("updateAabbs"); -} - -void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) -{ - BEGIN_PROFILE("integrateTransforms"); - btTransform predictedTrans; - for ( int i=0;iisActive() && (!body->isStaticOrKinematicObject())) - { - body->predictIntegratedTransform(timeStep, predictedTrans); - body->proceedToTransform( predictedTrans); - } - } - } - END_PROFILE("integrateTransforms"); -} - - - -void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) -{ - BEGIN_PROFILE("predictUnconstraintMotion"); - for ( int i=0;iisStaticOrKinematicObject()) - { - if (body->isActive()) - { - body->applyForces( timeStep); - body->integrateVelocities( timeStep); - body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); - } - } - } - } - END_PROFILE("predictUnconstraintMotion"); -} - - -void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep) -{ - (void)timeStep; - #ifdef USE_QUICKPROF - - - //toggle btProfiler - if ( m_debugDrawer && m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_ProfileTimings) - { - if (!m_profileTimings) - { - m_profileTimings = 1; - // To disable profiling, simply comment out the following line. - static int counter = 0; - - char filename[128]; - sprintf(filename,"quickprof_bullet_timings%i.csv",counter++); - btProfiler::init(filename, btProfiler::BLOCK_CYCLE_SECONDS);//BLOCK_TOTAL_MICROSECONDS - } else - { - btProfiler::endProfilingCycle(); - } - - } else - { - if (m_profileTimings) - { - btProfiler::endProfilingCycle(); - - m_profileTimings = 0; - btProfiler::destroy(); - } - } -#endif //USE_QUICKPROF -} - - - - - - -class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback -{ - btIDebugDraw* m_debugDrawer; - btVector3 m_color; - btTransform m_worldTrans; - -public: - - DebugDrawcallback(btIDebugDraw* debugDrawer,const btTransform& worldTrans,const btVector3& color) : - m_debugDrawer(debugDrawer), - m_color(color), - m_worldTrans(worldTrans) - { - } - - virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) - { - processTriangle(triangle,partId,triangleIndex); - } - - virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex) - { - (void)partId; - (void)triangleIndex; - - btVector3 wv0,wv1,wv2; - wv0 = m_worldTrans*triangle[0]; - wv1 = m_worldTrans*triangle[1]; - wv2 = m_worldTrans*triangle[2]; - m_debugDrawer->drawLine(wv0,wv1,m_color); - m_debugDrawer->drawLine(wv1,wv2,m_color); - m_debugDrawer->drawLine(wv2,wv0,m_color); - } -}; - -void btDiscreteDynamicsWorld::debugDrawSphere(btScalar radius, const btTransform& transform, const btVector3& color) -{ - btVector3 start = transform.getOrigin(); - - const btVector3 xoffs = transform.getBasis() * btVector3(radius,0,0); - const btVector3 yoffs = transform.getBasis() * btVector3(0,radius,0); - const btVector3 zoffs = transform.getBasis() * btVector3(0,0,radius); - - // XY - getDebugDrawer()->drawLine(start-xoffs, start+yoffs, color); - getDebugDrawer()->drawLine(start+yoffs, start+xoffs, color); - getDebugDrawer()->drawLine(start+xoffs, start-yoffs, color); - getDebugDrawer()->drawLine(start-yoffs, start-xoffs, color); - - // XZ - getDebugDrawer()->drawLine(start-xoffs, start+zoffs, color); - getDebugDrawer()->drawLine(start+zoffs, start+xoffs, color); - getDebugDrawer()->drawLine(start+xoffs, start-zoffs, color); - getDebugDrawer()->drawLine(start-zoffs, start-xoffs, color); - - // YZ - getDebugDrawer()->drawLine(start-yoffs, start+zoffs, color); - getDebugDrawer()->drawLine(start+zoffs, start+yoffs, color); - getDebugDrawer()->drawLine(start+yoffs, start-zoffs, color); - getDebugDrawer()->drawLine(start-zoffs, start-yoffs, color); -} - -void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color) -{ - // Draw a small simplex at the center of the object - { - btVector3 start = worldTransform.getOrigin(); - getDebugDrawer()->drawLine(start, start+worldTransform.getBasis() * btVector3(1,0,0), btVector3(1,0,0)); - getDebugDrawer()->drawLine(start, start+worldTransform.getBasis() * btVector3(0,1,0), btVector3(0,1,0)); - getDebugDrawer()->drawLine(start, start+worldTransform.getBasis() * btVector3(0,0,1), btVector3(0,0,1)); - } - - if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) - { - const btCompoundShape* compoundShape = static_cast(shape); - for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--) - { - btTransform childTrans = compoundShape->getChildTransform(i); - const btCollisionShape* colShape = compoundShape->getChildShape(i); - debugDrawObject(worldTransform*childTrans,colShape,color); - } - - } else - { - switch (shape->getShapeType()) - { - - case SPHERE_SHAPE_PROXYTYPE: - { - const btSphereShape* sphereShape = static_cast(shape); - btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin - - debugDrawSphere(radius, worldTransform, color); - break; - } - case MULTI_SPHERE_SHAPE_PROXYTYPE: - { - const btMultiSphereShape* multiSphereShape = static_cast(shape); - - for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--) - { - btTransform childTransform = worldTransform; - childTransform.getOrigin() += multiSphereShape->getSpherePosition(i); - debugDrawSphere(multiSphereShape->getSphereRadius(i), childTransform, color); - } - - break; - } - case CAPSULE_SHAPE_PROXYTYPE: - { - const btCapsuleShape* capsuleShape = static_cast(shape); - - btScalar radius = capsuleShape->getRadius(); - btScalar halfHeight = capsuleShape->getHalfHeight(); - - // Draw the ends - { - btTransform childTransform = worldTransform; - childTransform.getOrigin() = worldTransform * btVector3(0,halfHeight,0); - debugDrawSphere(radius, childTransform, color); - } - - { - btTransform childTransform = worldTransform; - childTransform.getOrigin() = worldTransform * btVector3(0,-halfHeight,0); - debugDrawSphere(radius, childTransform, color); - } - - // Draw some additional lines - btVector3 start = worldTransform.getOrigin(); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(-radius,halfHeight,0),start+worldTransform.getBasis() * btVector3(-radius,-halfHeight,0), color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(radius,halfHeight,0),start+worldTransform.getBasis() * btVector3(radius,-halfHeight,0), color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(0,halfHeight,-radius),start+worldTransform.getBasis() * btVector3(0,-halfHeight,-radius), color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(0,halfHeight,radius),start+worldTransform.getBasis() * btVector3(0,-halfHeight,radius), color); - - break; - } - case CONE_SHAPE_PROXYTYPE: - { - const btConeShape* coneShape = static_cast(shape); - btScalar radius = coneShape->getRadius();//+coneShape->getMargin(); - btScalar height = coneShape->getHeight();//+coneShape->getMargin(); - btVector3 start = worldTransform.getOrigin(); - - int upAxis= coneShape->getConeUpIndex(); - - - btVector3 offsetHeight(0,0,0); - offsetHeight[upAxis] = height * btScalar(0.5); - btVector3 offsetRadius(0,0,0); - offsetRadius[(upAxis+1)%3] = radius; - btVector3 offset2Radius(0,0,0); - offset2Radius[(upAxis+2)%3] = radius; - - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offsetRadius),color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offset2Radius),color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offset2Radius),color); - - - - break; - - } - case CYLINDER_SHAPE_PROXYTYPE: - { - const btCylinderShape* cylinder = static_cast(shape); - int upAxis = cylinder->getUpAxis(); - btScalar radius = cylinder->getRadius(); - btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; - btVector3 start = worldTransform.getOrigin(); - btVector3 offsetHeight(0,0,0); - offsetHeight[upAxis] = halfHeight; - btVector3 offsetRadius(0,0,0); - offsetRadius[(upAxis+1)%3] = radius; - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight+offsetRadius),start+worldTransform.getBasis() * (-offsetHeight+offsetRadius),color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight-offsetRadius),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color); - break; - } - default: - { - - if (shape->isConcave()) - { - btConcaveShape* concaveMesh = (btConcaveShape*) shape; - - //todo pass camera, for some culling - btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); - - DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); - concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax); - - } - - if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE) - { - btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape; - //todo: pass camera for some culling - btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); - //DebugDrawcallback drawCallback; - DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); - convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); - } - - - /// for polyhedral shapes - if (shape->isPolyhedral()) - { - btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape; - - int i; - for (i=0;igetNumEdges();i++) - { - btPoint3 a,b; - polyshape->getEdge(i,a,b); - btVector3 wa = worldTransform * a; - btVector3 wb = worldTransform * b; - getDebugDrawer()->drawLine(wa,wb,color); - - } - - - } - } - } - } -} - - -void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) -{ - if (m_ownsConstraintSolver) - { - btAlignedFree( m_constraintSolver); - } - m_ownsConstraintSolver = false; - m_constraintSolver = solver; -} - -btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver() -{ - return m_constraintSolver; -} - - -int btDiscreteDynamicsWorld::getNumConstraints() const -{ - return int(m_constraints.size()); -} -btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) -{ - return m_constraints[index]; -} -const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const -{ - return m_constraints[index]; -} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h deleted file mode 100644 index 7364c4cd6b9..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ /dev/null @@ -1,164 +0,0 @@ -/* -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. -*/ - -#ifndef BT_DISCRETE_DYNAMICS_WORLD_H -#define BT_DISCRETE_DYNAMICS_WORLD_H - -#include "btDynamicsWorld.h" - -class btDispatcher; -class btOverlappingPairCache; -class btConstraintSolver; -class btSimulationIslandManager; -class btTypedConstraint; -#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" - -class btRaycastVehicle; -class btIDebugDraw; -#include "LinearMath/btAlignedObjectArray.h" - - -///btDiscreteDynamicsWorld provides discrete rigid body simulation -///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController -class btDiscreteDynamicsWorld : public btDynamicsWorld -{ -protected: - - btConstraintSolver* m_constraintSolver; - - btSimulationIslandManager* m_islandManager; - - btAlignedObjectArray m_constraints; - - btIDebugDraw* m_debugDrawer; - - btVector3 m_gravity; - - //for variable timesteps - btScalar m_localTime; - //for variable timesteps - - bool m_ownsIslandManager; - bool m_ownsConstraintSolver; - - btContactSolverInfo m_solverInfo; - - - btAlignedObjectArray m_vehicles; - - int m_profileTimings; - - void predictUnconstraintMotion(btScalar timeStep); - - void integrateTransforms(btScalar timeStep); - - void calculateSimulationIslands(); - - void solveConstraints(btContactSolverInfo& solverInfo); - - void updateActivationState(btScalar timeStep); - - void updateVehicles(btScalar timeStep); - - void startProfiling(btScalar timeStep); - - virtual void internalSingleStepSimulation( btScalar timeStep); - - void synchronizeMotionStates(); - - void saveKinematicState(btScalar timeStep); - - void debugDrawSphere(btScalar radius, const btTransform& transform, const btVector3& color); - -public: - - - ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those - btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); - - virtual ~btDiscreteDynamicsWorld(); - - ///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's - virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); - - virtual void updateAabbs(); - - void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false); - - void removeConstraint(btTypedConstraint* constraint); - - void addVehicle(btRaycastVehicle* vehicle); - - void removeVehicle(btRaycastVehicle* vehicle); - - btSimulationIslandManager* getSimulationIslandManager() - { - return m_islandManager; - } - - const btSimulationIslandManager* getSimulationIslandManager() const - { - return m_islandManager; - } - - btCollisionWorld* getCollisionWorld() - { - return this; - } - - virtual void setDebugDrawer(btIDebugDraw* debugDrawer) - { - m_debugDrawer = debugDrawer; - } - - virtual btIDebugDraw* getDebugDrawer() - { - return m_debugDrawer; - } - - virtual void setGravity(const btVector3& gravity); - - virtual void addRigidBody(btRigidBody* body); - - virtual void addRigidBody(btRigidBody* body, short group, short mask); - - virtual void removeRigidBody(btRigidBody* body); - - void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color); - - virtual void setConstraintSolver(btConstraintSolver* solver); - - virtual btConstraintSolver* getConstraintSolver(); - - virtual int getNumConstraints() const; - - virtual btTypedConstraint* getConstraint(int index) ; - - virtual const btTypedConstraint* getConstraint(int index) const; - - btContactSolverInfo& getSolverInfo() - { - return m_solverInfo; - } - - virtual btDynamicsWorldType getWorldType() const - { - return BT_DISCRETE_DYNAMICS_WORLD; - } - - -}; - -#endif //BT_DISCRETE_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h deleted file mode 100644 index a4c8bf3c559..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -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. -*/ - -#ifndef BT_DYNAMICS_WORLD_H -#define BT_DYNAMICS_WORLD_H - -#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" -class btTypedConstraint; -class btRaycastVehicle; -class btConstraintSolver; - - -enum btDynamicsWorldType -{ - BT_SIMPLE_DYNAMICS_WORLD=1, - BT_DISCRETE_DYNAMICS_WORLD=2, - BT_CONTINUOUS_DYNAMICS_WORLD=3 -}; - -///btDynamicsWorld is the baseclass for several dynamics implementation, basic, discrete, parallel, and continuous -class btDynamicsWorld : public btCollisionWorld -{ - public: - - - btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration) - :btCollisionWorld(dispatcher,broadphase,collisionConfiguration) - { - } - - virtual ~btDynamicsWorld() - { - } - - ///stepSimulation proceeds the simulation over timeStep units - ///if maxSubSteps > 0, it will interpolate time steps - virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0; - - virtual void updateAabbs() = 0; - - virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) { (void)constraint;}; - - virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;}; - - virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}; - - virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}; - - - virtual void setDebugDrawer(btIDebugDraw* debugDrawer) = 0; - - virtual btIDebugDraw* getDebugDrawer() = 0; - - //once a rigidbody is added to the dynamics world, it will get this gravity assigned - //existing rigidbodies in the world get gravity assigned too, during this method - virtual void setGravity(const btVector3& gravity) = 0; - - virtual void addRigidBody(btRigidBody* body) = 0; - - virtual void removeRigidBody(btRigidBody* body) = 0; - - virtual void setConstraintSolver(btConstraintSolver* solver) = 0; - - virtual btConstraintSolver* getConstraintSolver() = 0; - - virtual int getNumConstraints() const { return 0; } - - virtual btTypedConstraint* getConstraint(int index) { (void)index; return 0; } - - virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; } - - virtual btDynamicsWorldType getWorldType() const=0; - -}; - -#endif //BT_DYNAMICS_WORLD_H - diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp deleted file mode 100644 index 03e60acdb19..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/* -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. -*/ - -#include "btRigidBody.h" -#include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "LinearMath/btMinMax.h" -#include "LinearMath/btTransformUtil.h" -#include "LinearMath/btMotionState.h" -#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" - -btScalar gLinearAirDamping = btScalar(1.); -//'temporarily' global variables -btScalar gDeactivationTime = btScalar(2.); -bool gDisableDeactivation = false; - -btScalar gLinearSleepingThreshold = btScalar(0.8); -btScalar gAngularSleepingThreshold = btScalar(1.0); -static int uniqueId = 0; - -btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) -: - m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), - m_angularFactor(btScalar(1.)), - m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_linearDamping(btScalar(0.)), - m_angularDamping(btScalar(0.5)), - m_linearSleepingThreshold(gLinearSleepingThreshold), - m_angularSleepingThreshold(gAngularSleepingThreshold), - m_optionalMotionState(motionState), - m_contactSolverType(0), - m_frictionSolverType(0) -{ - - if (motionState) - { - motionState->getWorldTransform(m_worldTransform); - } else - { - m_worldTransform = btTransform::getIdentity(); - } - - m_interpolationWorldTransform = m_worldTransform; - m_interpolationLinearVelocity.setValue(0,0,0); - m_interpolationAngularVelocity.setValue(0,0,0); - - //moved to btCollisionObject - m_friction = friction; - m_restitution = restitution; - - m_collisionShape = collisionShape; - m_debugBodyId = uniqueId++; - - //m_internalOwner is to allow upcasting from collision object to rigid body - m_internalOwner = this; - - setMassProps(mass, localInertia); - setDamping(linearDamping, angularDamping); - updateInertiaTensor(); - -} - -#ifdef OBSOLETE_MOTIONSTATE_LESS -btRigidBody::btRigidBody( btScalar mass,const btTransform& worldTransform,btCollisionShape* collisionShape,const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) -: - m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), - m_linearSleepingThreshold(gLinearSleepingThreshold), - m_angularSleepingThreshold(gAngularSleepingThreshold), - m_linearDamping(btScalar(0.)), - m_angularDamping(btScalar(0.5)), - m_optionalMotionState(0), - m_contactSolverType(0), - m_frictionSolverType(0) - -{ - - m_worldTransform = worldTransform; - m_interpolationWorldTransform = m_worldTransform; - m_interpolationLinearVelocity.setValue(0,0,0); - m_interpolationAngularVelocity.setValue(0,0,0); - - //moved to btCollisionObject - m_friction = friction; - m_restitution = restitution; - - m_collisionShape = collisionShape; - m_debugBodyId = uniqueId++; - - //m_internalOwner is to allow upcasting from collision object to rigid body - m_internalOwner = this; - - setMassProps(mass, localInertia); - setDamping(linearDamping, angularDamping); - updateInertiaTensor(); - -} - -#endif //OBSOLETE_MOTIONSTATE_LESS - - - - -#define EXPERIMENTAL_JITTER_REMOVAL 1 -#ifdef EXPERIMENTAL_JITTER_REMOVAL -//Bullet 2.20b has experimental damping code to reduce jitter just before objects fall asleep/deactivate -//doesn't work very well yet (value 0 disabled this damping) -//note there this influences deactivation thresholds! -btScalar gClippedAngvelThresholdSqr = btScalar(0.01); -btScalar gClippedLinearThresholdSqr = btScalar(0.01); -#endif //EXPERIMENTAL_JITTER_REMOVAL - -btScalar gJitterVelocityDampingFactor = btScalar(0.7); - -void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform) -{ - -#ifdef EXPERIMENTAL_JITTER_REMOVAL - //if (wantsSleeping()) - { - //clip to avoid jitter - if ((m_angularVelocity.length2() < gClippedAngvelThresholdSqr) && - (m_linearVelocity.length2() < gClippedLinearThresholdSqr)) - { - m_angularVelocity *= gJitterVelocityDampingFactor; - m_linearVelocity *= gJitterVelocityDampingFactor; - } - } - -#endif //EXPERIMENTAL_JITTER_REMOVAL - - btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform); -} - -void btRigidBody::saveKinematicState(btScalar timeStep) -{ - //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities - if (timeStep != btScalar(0.)) - { - //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform - if (getMotionState()) - getMotionState()->getWorldTransform(m_worldTransform); - btVector3 linVel,angVel; - - btTransformUtil::calculateVelocity(m_interpolationWorldTransform,m_worldTransform,timeStep,m_linearVelocity,m_angularVelocity); - m_interpolationLinearVelocity = m_linearVelocity; - m_interpolationAngularVelocity = m_angularVelocity; - m_interpolationWorldTransform = m_worldTransform; - //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ()); - } -} - -void btRigidBody::getAabb(btVector3& aabbMin,btVector3& aabbMax) const -{ - getCollisionShape()->getAabb(m_worldTransform,aabbMin,aabbMax); -} - - - - -void btRigidBody::setGravity(const btVector3& acceleration) -{ - if (m_inverseMass != btScalar(0.0)) - { - m_gravity = acceleration * (btScalar(1.0) / m_inverseMass); - } -} - - - - - - -void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping) -{ - m_linearDamping = GEN_clamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); - m_angularDamping = GEN_clamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); -} - - - -#include - - -void btRigidBody::applyForces(btScalar step) -{ - if (isStaticOrKinematicObject()) - return; - - applyCentralForce(m_gravity); - - m_linearVelocity *= GEN_clamped((btScalar(1.) - step * gLinearAirDamping * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); - m_angularVelocity *= GEN_clamped((btScalar(1.) - step * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); - -#define FORCE_VELOCITY_DAMPING 1 -#ifdef FORCE_VELOCITY_DAMPING - btScalar speed = m_linearVelocity.length(); - if (speed < m_linearDamping) - { - btScalar dampVel = btScalar(0.005); - if (speed > dampVel) - { - btVector3 dir = m_linearVelocity.normalized(); - m_linearVelocity -= dir * dampVel; - } else - { - m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - } - } - - btScalar angSpeed = m_angularVelocity.length(); - if (angSpeed < m_angularDamping) - { - btScalar angDampVel = btScalar(0.005); - if (angSpeed > angDampVel) - { - btVector3 dir = m_angularVelocity.normalized(); - m_angularVelocity -= dir * angDampVel; - } else - { - m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - } - } -#endif //FORCE_VELOCITY_DAMPING - -} - -void btRigidBody::proceedToTransform(const btTransform& newTrans) -{ - setCenterOfMassTransform( newTrans ); -} - - -void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia) -{ - if (mass == btScalar(0.)) - { - m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT; - m_inverseMass = btScalar(0.); - } else - { - m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT); - m_inverseMass = btScalar(1.0) / mass; - } - - m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x(): btScalar(0.0), - inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y(): btScalar(0.0), - inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z(): btScalar(0.0)); - -} - - - -void btRigidBody::updateInertiaTensor() -{ - m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose(); -} - - -void btRigidBody::integrateVelocities(btScalar step) -{ - if (isStaticOrKinematicObject()) - return; - - m_linearVelocity += m_totalForce * (m_inverseMass * step); - m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step; - -#define MAX_ANGVEL SIMD_HALF_PI - /// clamp angular velocity. collision calculations will fail on higher angular velocities - btScalar angvel = m_angularVelocity.length(); - if (angvel*step > MAX_ANGVEL) - { - m_angularVelocity *= (MAX_ANGVEL/step) /angvel; - } - - clearForces(); -} - -btQuaternion btRigidBody::getOrientation() const -{ - btQuaternion orn; - m_worldTransform.getBasis().getRotation(orn); - return orn; -} - - -void btRigidBody::setCenterOfMassTransform(const btTransform& xform) -{ - - if (isStaticOrKinematicObject()) - { - m_interpolationWorldTransform = m_worldTransform; - } else - { - m_interpolationWorldTransform = xform; - } - m_interpolationLinearVelocity = getLinearVelocity(); - m_interpolationAngularVelocity = getAngularVelocity(); - m_worldTransform = xform; - updateInertiaTensor(); -} - - -bool btRigidBody::checkCollideWithOverride(btCollisionObject* co) -{ - btRigidBody* otherRb = btRigidBody::upcast(co); - if (!otherRb) - return true; - - for (int i = 0; i < m_constraintRefs.size(); ++i) - { - btTypedConstraint* c = m_constraintRefs[i]; - if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb) - return false; - } - - return true; -} - -void btRigidBody::addConstraintRef(btTypedConstraint* c) -{ - int index = m_constraintRefs.findLinearSearch(c); - if (index == m_constraintRefs.size()) - m_constraintRefs.push_back(c); - - m_checkCollideWith = true; -} - -void btRigidBody::removeConstraintRef(btTypedConstraint* c) -{ - m_constraintRefs.remove(c); - m_checkCollideWith = m_constraintRefs.size() > 0; -} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h deleted file mode 100644 index b11f9f76d7d..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h +++ /dev/null @@ -1,385 +0,0 @@ -/* -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. -*/ - -#ifndef RIGIDBODY_H -#define RIGIDBODY_H - -#include "LinearMath/btAlignedObjectArray.h" -#include "LinearMath/btPoint3.h" -#include "LinearMath/btTransform.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" - -class btCollisionShape; -class btMotionState; -class btTypedConstraint; - - -extern btScalar gLinearAirDamping; - -extern btScalar gDeactivationTime; -extern bool gDisableDeactivation; -extern btScalar gLinearSleepingThreshold; -extern btScalar gAngularSleepingThreshold; - - -/// btRigidBody class for btRigidBody Dynamics -/// -class btRigidBody : public btCollisionObject -{ - - btMatrix3x3 m_invInertiaTensorWorld; - btVector3 m_linearVelocity; - btVector3 m_angularVelocity; - btScalar m_inverseMass; - btScalar m_angularFactor; - - btVector3 m_gravity; - btVector3 m_invInertiaLocal; - btVector3 m_totalForce; - btVector3 m_totalTorque; - - btScalar m_linearDamping; - btScalar m_angularDamping; - - btScalar m_linearSleepingThreshold; - btScalar m_angularSleepingThreshold; - - - //m_optionalMotionState allows to automatic synchronize the world transform for active objects - btMotionState* m_optionalMotionState; - - //keep track of typed constraints referencing this rigid body - btAlignedObjectArray m_constraintRefs; - -public: - -#ifdef OBSOLETE_MOTIONSTATE_LESS - //not supported, please use btMotionState - btRigidBody(btScalar mass, const btTransform& worldTransform, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); -#endif //OBSOLETE_MOTIONSTATE_LESS - - btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); - - virtual ~btRigidBody() - { - //No constraints should point to this rigidbody - //Remove constraints from the dynamics world before you delete the related rigidbodies. - btAssert(m_constraintRefs.size()==0); - } - - - void proceedToTransform(const btTransform& newTrans); - - ///to keep collision detection and dynamics separate we don't store a rigidbody pointer - ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast - static const btRigidBody* upcast(const btCollisionObject* colObj) - { - return (const btRigidBody*)colObj->getInternalOwner(); - } - static btRigidBody* upcast(btCollisionObject* colObj) - { - return (btRigidBody*)colObj->getInternalOwner(); - } - - /// continuous collision detection needs prediction - void predictIntegratedTransform(btScalar step, btTransform& predictedTransform) ; - - void saveKinematicState(btScalar step); - - - void applyForces(btScalar step); - - void setGravity(const btVector3& acceleration); - - const btVector3& getGravity() const - { - return m_gravity; - } - - void setDamping(btScalar lin_damping, btScalar ang_damping); - - SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { - return m_collisionShape; - } - - SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() { - return m_collisionShape; - } - - void setMassProps(btScalar mass, const btVector3& inertia); - - btScalar getInvMass() const { return m_inverseMass; } - const btMatrix3x3& getInvInertiaTensorWorld() const { - return m_invInertiaTensorWorld; - } - - void integrateVelocities(btScalar step); - - void setCenterOfMassTransform(const btTransform& xform); - - void applyCentralForce(const btVector3& force) - { - m_totalForce += force; - } - - const btVector3& getInvInertiaDiagLocal() - { - return m_invInertiaLocal; - }; - - void setInvInertiaDiagLocal(const btVector3& diagInvInertia) - { - m_invInertiaLocal = diagInvInertia; - } - - void setSleepingThresholds(btScalar linear,btScalar angular) - { - m_linearSleepingThreshold = linear; - m_angularSleepingThreshold = angular; - } - - void applyTorque(const btVector3& torque) - { - m_totalTorque += torque; - } - - void applyForce(const btVector3& force, const btVector3& rel_pos) - { - applyCentralForce(force); - applyTorque(rel_pos.cross(force)); - } - - void applyCentralImpulse(const btVector3& impulse) - { - m_linearVelocity += impulse * m_inverseMass; - } - - void applyTorqueImpulse(const btVector3& torque) - { - m_angularVelocity += m_invInertiaTensorWorld * torque; - } - - void applyImpulse(const btVector3& impulse, const btVector3& rel_pos) - { - if (m_inverseMass != btScalar(0.)) - { - applyCentralImpulse(impulse); - if (m_angularFactor) - { - applyTorqueImpulse(rel_pos.cross(impulse)*m_angularFactor); - } - } - } - - //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) - { - if (m_inverseMass != btScalar(0.)) - { - m_linearVelocity += linearComponent*impulseMagnitude; - if (m_angularFactor) - { - m_angularVelocity += angularComponent*impulseMagnitude*m_angularFactor; - } - } - } - - void clearForces() - { - m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); - m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); - } - - void updateInertiaTensor(); - - const btPoint3& getCenterOfMassPosition() const { - return m_worldTransform.getOrigin(); - } - btQuaternion getOrientation() const; - - const btTransform& getCenterOfMassTransform() const { - return m_worldTransform; - } - const btVector3& getLinearVelocity() const { - return m_linearVelocity; - } - const btVector3& getAngularVelocity() const { - return m_angularVelocity; - } - - - inline void setLinearVelocity(const btVector3& lin_vel) - { - assert (m_collisionFlags != btCollisionObject::CF_STATIC_OBJECT); - m_linearVelocity = lin_vel; - } - - inline void setAngularVelocity(const btVector3& ang_vel) { - assert (m_collisionFlags != btCollisionObject::CF_STATIC_OBJECT); - { - m_angularVelocity = ang_vel; - } - } - - btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const - { - //we also calculate lin/ang velocity for kinematic objects - return m_linearVelocity + m_angularVelocity.cross(rel_pos); - - //for kinematic objects, we could also use use: - // return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep; - } - - void translate(const btVector3& v) - { - m_worldTransform.getOrigin() += v; - } - - - void getAabb(btVector3& aabbMin,btVector3& aabbMax) const; - - - - - - SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btPoint3& pos, const btVector3& normal) const - { - btVector3 r0 = pos - getCenterOfMassPosition(); - - btVector3 c0 = (r0).cross(normal); - - btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0); - - return m_inverseMass + normal.dot(vec); - - } - - SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const - { - btVector3 vec = axis * getInvInertiaTensorWorld(); - return axis.dot(vec); - } - - SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep) - { - if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION)) - return; - - if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) && - (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold)) - { - m_deactivationTime += timeStep; - } else - { - m_deactivationTime=btScalar(0.); - setActivationState(0); - } - - } - - SIMD_FORCE_INLINE bool wantsSleeping() - { - - if (getActivationState() == DISABLE_DEACTIVATION) - return false; - - //disable deactivation - if (gDisableDeactivation || (gDeactivationTime == btScalar(0.))) - return false; - - if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION)) - return true; - - if (m_deactivationTime> gDeactivationTime) - { - return true; - } - return false; - } - - - - const btBroadphaseProxy* getBroadphaseProxy() const - { - return m_broadphaseHandle; - } - btBroadphaseProxy* getBroadphaseProxy() - { - return m_broadphaseHandle; - } - void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy) - { - m_broadphaseHandle = broadphaseProxy; - } - - //btMotionState allows to automatic synchronize the world transform for active objects - btMotionState* getMotionState() - { - return m_optionalMotionState; - } - const btMotionState* getMotionState() const - { - return m_optionalMotionState; - } - void setMotionState(btMotionState* motionState) - { - m_optionalMotionState = motionState; - if (m_optionalMotionState) - motionState->getWorldTransform(m_worldTransform); - } - - //for experimental overriding of friction/contact solver func - int m_contactSolverType; - int m_frictionSolverType; - - void setAngularFactor(btScalar angFac) - { - m_angularFactor = angFac; - } - btScalar getAngularFactor() const - { - return m_angularFactor; - } - - //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase? - bool isInWorld() const - { - return (getBroadphaseProxy() != 0); - } - - virtual bool checkCollideWithOverride(btCollisionObject* co); - - void addConstraintRef(btTypedConstraint* c); - void removeConstraintRef(btTypedConstraint* c); - - btTypedConstraint* getConstraintRef(int index) - { - return m_constraintRefs[index]; - } - - int getNumConstraintRefs() - { - return m_constraintRefs.size(); - } - - - int m_debugBodyId; -}; - - - -#endif - diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp deleted file mode 100644 index 3a78ec54f1c..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* -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. -*/ - -#include "btSimpleDynamicsWorld.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" -#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" - - -/* - Make sure this dummy function never changes so that it - can be used by probes that are checking whether the - library is actually installed. -*/ -extern "C" void btBulletDynamicsProbe () {} - - - - -btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) -:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), -m_constraintSolver(constraintSolver), -m_ownsConstraintSolver(false), -m_debugDrawer(0), -m_gravity(0,0,-10) -{ - -} - - -btSimpleDynamicsWorld::~btSimpleDynamicsWorld() -{ - if (m_ownsConstraintSolver) - btAlignedFree( m_constraintSolver); -} - -int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) -{ - (void)fixedTimeStep; - (void)maxSubSteps; - - - ///apply gravity, predict motion - predictUnconstraintMotion(timeStep); - - btDispatcherInfo& dispatchInfo = getDispatchInfo(); - dispatchInfo.m_timeStep = timeStep; - dispatchInfo.m_stepCount = 0; - dispatchInfo.m_debugDraw = getDebugDrawer(); - - ///perform collision detection - performDiscreteCollisionDetection(); - - ///solve contact constraints - int numManifolds = m_dispatcher1->getNumManifolds(); - if (numManifolds) - { - btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer(); - - btContactSolverInfo infoGlobal; - infoGlobal.m_timeStep = timeStep; - m_constraintSolver->prepareSolve(0,numManifolds); - m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc,m_dispatcher1); - m_constraintSolver->allSolved(infoGlobal,m_debugDrawer, m_stackAlloc); - } - - ///integrate transforms - integrateTransforms(timeStep); - - updateAabbs(); - - synchronizeMotionStates(); - - return 1; - -} - - -void btSimpleDynamicsWorld::setGravity(const btVector3& gravity) -{ - m_gravity = gravity; - for ( int i=0;isetGravity(gravity); - } - } -} - -void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body) -{ - removeCollisionObject(body); -} - -void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body) -{ - body->setGravity(m_gravity); - - if (body->getCollisionShape()) - { - addCollisionObject(body); - } -} - -void btSimpleDynamicsWorld::updateAabbs() -{ - btTransform predictedTrans; - for ( int i=0;iisActive() && (!body->isStaticObject())) - { - btPoint3 minAabb,maxAabb; - colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); - btBroadphaseInterface* bp = getBroadphase(); - bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); - } - } - } -} - -void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep) -{ - btTransform predictedTrans; - for ( int i=0;iisActive() && (!body->isStaticObject())) - { - body->predictIntegratedTransform(timeStep, predictedTrans); - body->proceedToTransform( predictedTrans); - } - } - } -} - - - -void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) -{ - for ( int i=0;iisStaticObject()) - { - if (body->isActive()) - { - body->applyForces( timeStep); - body->integrateVelocities( timeStep); - body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); - } - } - } - } -} - - -void btSimpleDynamicsWorld::synchronizeMotionStates() -{ - //todo: iterate over awake simulation islands! - for ( int i=0;igetMotionState()) - { - if (body->getActivationState() != ISLAND_SLEEPING) - { - body->getMotionState()->setWorldTransform(body->getWorldTransform()); - } - } - } - -} - - -void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) -{ - if (m_ownsConstraintSolver) - { - btAlignedFree(m_constraintSolver); - } - m_ownsConstraintSolver = false; - m_constraintSolver = solver; -} - -btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver() -{ - return m_constraintSolver; -} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h deleted file mode 100644 index 4e38f74a731..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -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. -*/ - -#ifndef BT_SIMPLE_DYNAMICS_WORLD_H -#define BT_SIMPLE_DYNAMICS_WORLD_H - -#include "btDynamicsWorld.h" - -class btDispatcher; -class btOverlappingPairCache; -class btConstraintSolver; - -///btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds. -///Please use btDiscreteDynamicsWorld instead (or btContinuousDynamicsWorld once it is finished). -class btSimpleDynamicsWorld : public btDynamicsWorld -{ -protected: - - btConstraintSolver* m_constraintSolver; - - bool m_ownsConstraintSolver; - - btIDebugDraw* m_debugDrawer; - - void predictUnconstraintMotion(btScalar timeStep); - - void integrateTransforms(btScalar timeStep); - - btVector3 m_gravity; - -public: - - - - ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver - btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); - - virtual ~btSimpleDynamicsWorld(); - - ///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead - virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); - - virtual void setDebugDrawer(btIDebugDraw* debugDrawer) - { - m_debugDrawer = debugDrawer; - }; - - virtual btIDebugDraw* getDebugDrawer() - { - return m_debugDrawer; - } - - virtual void setGravity(const btVector3& gravity); - - virtual void addRigidBody(btRigidBody* body); - - virtual void removeRigidBody(btRigidBody* body); - - virtual void updateAabbs(); - - void synchronizeMotionStates(); - - virtual void setConstraintSolver(btConstraintSolver* solver); - - virtual btConstraintSolver* getConstraintSolver(); - - virtual btDynamicsWorldType getWorldType() const - { - return BT_SIMPLE_DYNAMICS_WORLD; - } - -}; - -#endif //BT_SIMPLE_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp deleted file mode 100644 index 8dcd6d895e4..00000000000 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp +++ /dev/null @@ -1,738 +0,0 @@ -/* - * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies. - * Erwin Coumans makes no representations about the suitability - * of this software for any purpose. - * It is provided "as is" without express or implied warranty. -*/ - -#include "LinearMath/btVector3.h" -#include "btRaycastVehicle.h" - -#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h" -#include "BulletDynamics/ConstraintSolver/btJacobianEntry.h" -#include "LinearMath/btQuaternion.h" -#include "BulletDynamics/Dynamics/btDynamicsWorld.h" -#include "btVehicleRaycaster.h" -#include "btWheelInfo.h" -#include "LinearMath/btMinMax.h" - - -#include "BulletDynamics/ConstraintSolver/btContactConstraint.h" - - - -static btRigidBody s_fixedObject( 0,0,0); - -btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ) -: btTypedConstraint(VEHICLE_CONSTRAINT_TYPE), -m_vehicleRaycaster(raycaster), -m_pitchControl(btScalar(0.)) -{ - m_chassisBody = chassis; - m_indexRightAxis = 0; - m_indexUpAxis = 2; - m_indexForwardAxis = 1; - defaultInit(tuning); -} - - -void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning) -{ - (void)tuning; - m_currentVehicleSpeedKmHour = btScalar(0.); - m_steeringValue = btScalar(0.); - -} - - - -btRaycastVehicle::~btRaycastVehicle() -{ -} - - -// -// basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed -// -btWheelInfo& btRaycastVehicle::addWheel( const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel) -{ - - btWheelInfoConstructionInfo ci; - - ci.m_chassisConnectionCS = connectionPointCS; - ci.m_wheelDirectionCS = wheelDirectionCS0; - ci.m_wheelAxleCS = wheelAxleCS; - ci.m_suspensionRestLength = suspensionRestLength; - ci.m_wheelRadius = wheelRadius; - ci.m_suspensionStiffness = tuning.m_suspensionStiffness; - ci.m_wheelsDampingCompression = tuning.m_suspensionCompression; - ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping; - ci.m_frictionSlip = tuning.m_frictionSlip; - ci.m_bIsFrontWheel = isFrontWheel; - ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm; - - m_wheelInfo.push_back( btWheelInfo(ci)); - - btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1]; - - updateWheelTransformsWS( wheel , false ); - updateWheelTransform(getNumWheels()-1,false); - return wheel; -} - - - - -const btTransform& btRaycastVehicle::getWheelTransformWS( int wheelIndex ) const -{ - assert(wheelIndex < getNumWheels()); - const btWheelInfo& wheel = m_wheelInfo[wheelIndex]; - return wheel.m_worldTransform; - -} - -void btRaycastVehicle::updateWheelTransform( int wheelIndex , bool interpolatedTransform) -{ - - btWheelInfo& wheel = m_wheelInfo[ wheelIndex ]; - updateWheelTransformsWS(wheel,interpolatedTransform); - btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS; - const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS; - btVector3 fwd = up.cross(right); - fwd = fwd.normalize(); -// up = right.cross(fwd); -// up.normalize(); - - //rotate around steering over de wheelAxleWS - btScalar steering = wheel.m_steering; - - btQuaternion steeringOrn(up,steering);//wheel.m_steering); - btMatrix3x3 steeringMat(steeringOrn); - - btQuaternion rotatingOrn(right,-wheel.m_rotation); - btMatrix3x3 rotatingMat(rotatingOrn); - - btMatrix3x3 basis2( - right[0],fwd[0],up[0], - right[1],fwd[1],up[1], - right[2],fwd[2],up[2] - ); - - wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2); - wheel.m_worldTransform.setOrigin( - wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength - ); -} - -void btRaycastVehicle::resetSuspension() -{ - - int i; - for (i=0;igetMotionState())) - { - getRigidBody()->getMotionState()->getWorldTransform(chassisTrans); - } - - wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS ); - wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() * wheel.m_wheelDirectionCS ; - wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS; -} - -btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel) -{ - updateWheelTransformsWS( wheel,false); - - - btScalar depth = -1; - - btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius; - - btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen); - const btVector3& source = wheel.m_raycastInfo.m_hardPointWS; - wheel.m_raycastInfo.m_contactPointWS = source + rayvector; - const btVector3& target = wheel.m_raycastInfo.m_contactPointWS; - - btScalar param = btScalar(0.); - - btVehicleRaycaster::btVehicleRaycasterResult rayResults; - - assert(m_vehicleRaycaster); - - void* object = m_vehicleRaycaster->castRay(source,target,rayResults); - - wheel.m_raycastInfo.m_groundObject = 0; - - if (object) - { - param = rayResults.m_distFraction; - depth = raylen * rayResults.m_distFraction; - wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld; - wheel.m_raycastInfo.m_isInContact = true; - - wheel.m_raycastInfo.m_groundObject = &s_fixedObject;//todo for driving on dynamic/movable objects!; - //wheel.m_raycastInfo.m_groundObject = object; - - - btScalar hitDistance = param*raylen; - wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius; - //clamp on max suspension travel - - btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01); - btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01); - if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength) - { - wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength; - } - if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength) - { - wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength; - } - - wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld; - - btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS ); - - btVector3 chassis_velocity_at_contactPoint; - btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition(); - - chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos); - - btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); - - if ( denominator >= btScalar(-0.1)) - { - wheel.m_suspensionRelativeVelocity = btScalar(0.0); - wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1); - } - else - { - btScalar inv = btScalar(-1.) / denominator; - wheel.m_suspensionRelativeVelocity = projVel * inv; - wheel.m_clippedInvContactDotSuspension = inv; - } - - } else - { - //put wheel info as in rest position - wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength(); - wheel.m_suspensionRelativeVelocity = btScalar(0.0); - wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS; - wheel.m_clippedInvContactDotSuspension = btScalar(1.0); - } - - return depth; -} - - -const btTransform& btRaycastVehicle::getChassisWorldTransform() const -{ - /*if (getRigidBody()->getMotionState()) - { - btTransform chassisWorldTrans; - getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans); - return chassisWorldTrans; - } - */ - - - return getRigidBody()->getCenterOfMassTransform(); -} - - -void btRaycastVehicle::updateVehicle( btScalar step ) -{ - { - for (int i=0;igetLinearVelocity().length(); - - const btTransform& chassisTrans = getChassisWorldTransform(); - - btVector3 forwardW ( - chassisTrans.getBasis()[0][m_indexForwardAxis], - chassisTrans.getBasis()[1][m_indexForwardAxis], - chassisTrans.getBasis()[2][m_indexForwardAxis]); - - if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.)) - { - m_currentVehicleSpeedKmHour *= btScalar(-1.); - } - - // - // simulate suspension - // - - int i=0; - for (i=0;i gMaxSuspensionForce) - { - suspensionForce = gMaxSuspensionForce; - } - btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step; - btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition(); - - getRigidBody()->applyImpulse(impulse, relpos); - - } - - - - updateFriction( step); - - - for (i=0;igetCenterOfMassPosition(); - btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos ); - - if (wheel.m_raycastInfo.m_isInContact) - { - const btTransform& chassisWorldTransform = getChassisWorldTransform(); - - btVector3 fwd ( - chassisWorldTransform.getBasis()[0][m_indexForwardAxis], - chassisWorldTransform.getBasis()[1][m_indexForwardAxis], - chassisWorldTransform.getBasis()[2][m_indexForwardAxis]); - - btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS); - fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj; - - btScalar proj2 = fwd.dot(vel); - - wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius); - wheel.m_rotation += wheel.m_deltaRotation; - - } else - { - wheel.m_rotation += wheel.m_deltaRotation; - } - - wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact - - } - - - -} - - -void btRaycastVehicle::setSteeringValue(btScalar steering,int wheel) -{ - assert(wheel>=0 && wheel < getNumWheels()); - - btWheelInfo& wheelInfo = getWheelInfo(wheel); - wheelInfo.m_steering = steering; -} - - - -btScalar btRaycastVehicle::getSteeringValue(int wheel) const -{ - return getWheelInfo(wheel).m_steering; -} - - -void btRaycastVehicle::applyEngineForce(btScalar force, int wheel) -{ - assert(wheel>=0 && wheel < getNumWheels()); - btWheelInfo& wheelInfo = getWheelInfo(wheel); - wheelInfo.m_engineForce = force; -} - - -const btWheelInfo& btRaycastVehicle::getWheelInfo(int index) const -{ - btAssert((index >= 0) && (index < getNumWheels())); - - return m_wheelInfo[index]; -} - -btWheelInfo& btRaycastVehicle::getWheelInfo(int index) -{ - btAssert((index >= 0) && (index < getNumWheels())); - - return m_wheelInfo[index]; -} - -void btRaycastVehicle::setBrake(btScalar brake,int wheelIndex) -{ - btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels())); - getWheelInfo(wheelIndex).m_brake = brake; -} - - -void btRaycastVehicle::updateSuspension(btScalar deltaTime) -{ - (void)deltaTime; - - btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass(); - - for (int w_it=0; w_itcomputeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); - btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); - btScalar relaxation = 1.f; - m_jacDiagABInv = relaxation/(denom0+denom1); - } - - - -}; - -btScalar calcRollingFriction(btWheelContactPoint& contactPoint) -{ - - btScalar j1=0.f; - - const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld; - - btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition(); - btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition(); - - btScalar maxImpulse = contactPoint.m_maxImpulse; - - btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel); - - // calculate j that moves us to zero relative velocity - j1 = -vrel * contactPoint.m_jacDiagABInv; - btSetMin(j1, maxImpulse); - btSetMax(j1, -maxImpulse); - - return j1; -} - - - - -btScalar sideFrictionStiffness2 = btScalar(1.0); -void btRaycastVehicle::updateFriction(btScalar timeStep) -{ - - //calculate the impulse, so that the wheels don't move sidewards - int numWheel = getNumWheels(); - if (!numWheel) - return; - - - void* mem = btAlignedAlloc(numWheel*sizeof(btVector3),16); - btVector3* forwardWS = new (mem)btVector3[numWheel]; - mem = btAlignedAlloc(numWheel*sizeof(btVector3),16); - btVector3* axle = new (mem)btVector3[numWheel]; - mem = btAlignedAlloc(numWheel*sizeof(btScalar),16); - btScalar* forwardImpulse = new (mem)btScalar[numWheel]; - mem = btAlignedAlloc(numWheel*sizeof(btScalar),16); - btScalar* sideImpulse = new(mem) btScalar[numWheel]; - - int numWheelsOnGround = 0; - - - //collapse all those loops into one! - for (int i=0;i maximpSquared) - { - sliding = true; - - btScalar factor = maximp / btSqrt(impulseSquared); - - m_wheelInfo[wheel].m_skidInfo *= factor; - } - } - - } - } - - - - - if (sliding) - { - for (int wheel = 0;wheel < getNumWheels(); wheel++) - { - if (sideImpulse[wheel] != btScalar(0.)) - { - if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.)) - { - forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; - sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; - } - } - } - } - - // apply the impulses - { - for (int wheel = 0;wheelgetCenterOfMassPosition(); - - if (forwardImpulse[wheel] != btScalar(0.)) - { - m_chassisBody->applyImpulse(forwardWS[wheel]*(forwardImpulse[wheel]),rel_pos); - } - if (sideImpulse[wheel] != btScalar(0.)) - { - class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; - - btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - - groundObject->getCenterOfMassPosition(); - - - btVector3 sideImp = axle[wheel] * sideImpulse[wheel]; - - rel_pos[2] *= wheelInfo.m_rollInfluence; - m_chassisBody->applyImpulse(sideImp,rel_pos); - - //apply friction impulse on the ground - groundObject->applyImpulse(-sideImp,rel_pos2); - } - } - } - - btAlignedFree(forwardWS); - btAlignedFree(axle); - btAlignedFree(forwardImpulse); - btAlignedFree(sideImpulse); -} - - -void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) -{ -// RayResultCallback& resultCallback; - - btCollisionWorld::ClosestRayResultCallback rayCallback(from,to); - - m_dynamicsWorld->rayTest(from, to, rayCallback); - - if (rayCallback.HasHit()) - { - - btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); - if (body) - { - result.m_hitPointInWorld = rayCallback.m_hitPointWorld; - result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld; - result.m_hitNormalInWorld.normalize(); - result.m_distFraction = rayCallback.m_closestHitFraction; - return body; - } - } - return 0; -} diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h deleted file mode 100644 index a84b185e947..00000000000 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies. - * Erwin Coumans makes no representations about the suitability - * of this software for any purpose. - * It is provided "as is" without express or implied warranty. -*/ -#ifndef RAYCASTVEHICLE_H -#define RAYCASTVEHICLE_H - -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" -#include "btVehicleRaycaster.h" -class btDynamicsWorld; -#include "LinearMath/btAlignedObjectArray.h" -#include "btWheelInfo.h" - -class btVehicleTuning; - -///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle. -class btRaycastVehicle : public btTypedConstraint -{ -public: - class btVehicleTuning - { - public: - - btVehicleTuning() - :m_suspensionStiffness(btScalar(5.88)), - m_suspensionCompression(btScalar(0.83)), - m_suspensionDamping(btScalar(0.88)), - m_maxSuspensionTravelCm(btScalar(500.)), - m_frictionSlip(btScalar(10.5)) - { - } - btScalar m_suspensionStiffness; - btScalar m_suspensionCompression; - btScalar m_suspensionDamping; - btScalar m_maxSuspensionTravelCm; - btScalar m_frictionSlip; - - }; -private: - - btScalar m_tau; - btScalar m_damping; - btVehicleRaycaster* m_vehicleRaycaster; - btScalar m_pitchControl; - btScalar m_steeringValue; - btScalar m_currentVehicleSpeedKmHour; - - btRigidBody* m_chassisBody; - - int m_indexRightAxis; - int m_indexUpAxis; - int m_indexForwardAxis; - - void defaultInit(const btVehicleTuning& tuning); - -public: - - //constructor to create a car from an existing rigidbody - btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ); - - virtual ~btRaycastVehicle() ; - - - const btTransform& getChassisWorldTransform() const; - - btScalar rayCast(btWheelInfo& wheel); - - virtual void updateVehicle(btScalar step); - - void resetSuspension(); - - btScalar getSteeringValue(int wheel) const; - - void setSteeringValue(btScalar steering,int wheel); - - - void applyEngineForce(btScalar force, int wheel); - - const btTransform& getWheelTransformWS( int wheelIndex ) const; - - void updateWheelTransform( int wheelIndex, bool interpolatedTransform = true ); - - void setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth); - - btWheelInfo& addWheel( const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS,btScalar suspensionRestLength,btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel); - - inline int getNumWheels() const { - return int (m_wheelInfo.size()); - } - - btAlignedObjectArray m_wheelInfo; - - - const btWheelInfo& getWheelInfo(int index) const; - - btWheelInfo& getWheelInfo(int index); - - void updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform = true); - - - void setBrake(btScalar brake,int wheelIndex); - - void setPitchControl(btScalar pitch) - { - m_pitchControl = pitch; - } - - void updateSuspension(btScalar deltaTime); - - void updateFriction(btScalar timeStep); - - - - inline btRigidBody* getRigidBody() - { - return m_chassisBody; - } - - const btRigidBody* getRigidBody() const - { - return m_chassisBody; - } - - inline int getRightAxis() const - { - return m_indexRightAxis; - } - inline int getUpAxis() const - { - return m_indexUpAxis; - } - - inline int getForwardAxis() const - { - return m_indexForwardAxis; - } - - - ///Worldspace forward vector - btVector3 getForwardVector() const - { - const btTransform& chassisTrans = getChassisWorldTransform(); - - btVector3 forwardW ( - chassisTrans.getBasis()[0][m_indexForwardAxis], - chassisTrans.getBasis()[1][m_indexForwardAxis], - chassisTrans.getBasis()[2][m_indexForwardAxis]); - - return forwardW; - } - - ///Velocity of vehicle (positive if velocity vector has same direction as foward vector) - btScalar getCurrentSpeedKmHour() const - { - return m_currentVehicleSpeedKmHour; - } - - virtual void setCoordinateSystem(int rightIndex,int upIndex,int forwardIndex) - { - m_indexRightAxis = rightIndex; - m_indexUpAxis = upIndex; - m_indexForwardAxis = forwardIndex; - } - - virtual void buildJacobian() - { - //not yet - } - - virtual void solveConstraint(btScalar timeStep) - { - (void)timeStep; - //not yet - } - - -}; - -class btDefaultVehicleRaycaster : public btVehicleRaycaster -{ - btDynamicsWorld* m_dynamicsWorld; -public: - btDefaultVehicleRaycaster(btDynamicsWorld* world) - :m_dynamicsWorld(world) - { - } - - virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result); - -}; - - -#endif //RAYCASTVEHICLE_H - diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h deleted file mode 100644 index 5112ce6d420..00000000000 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies. - * Erwin Coumans makes no representations about the suitability - * of this software for any purpose. - * It is provided "as is" without express or implied warranty. -*/ -#ifndef VEHICLE_RAYCASTER_H -#define VEHICLE_RAYCASTER_H - -#include "LinearMath/btVector3.h" - -/// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting -struct btVehicleRaycaster -{ -virtual ~btVehicleRaycaster() -{ -} - struct btVehicleRaycasterResult - { - btVehicleRaycasterResult() :m_distFraction(btScalar(-1.)){}; - btVector3 m_hitPointInWorld; - btVector3 m_hitNormalInWorld; - btScalar m_distFraction; - }; - - virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) = 0; - -}; - -#endif //VEHICLE_RAYCASTER_H - diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.cpp b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.cpp deleted file mode 100644 index ef93c16fffc..00000000000 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies. - * Erwin Coumans makes no representations about the suitability - * of this software for any purpose. - * It is provided "as is" without express or implied warranty. -*/ -#include "btWheelInfo.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" // for pointvelocity - - -btScalar btWheelInfo::getSuspensionRestLength() const -{ - - return m_suspensionRestLength1; - -} - -void btWheelInfo::updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo) -{ - (void)raycastInfo; - - - if (m_raycastInfo.m_isInContact) - - { - btScalar project= m_raycastInfo.m_contactNormalWS.dot( m_raycastInfo.m_wheelDirectionWS ); - btVector3 chassis_velocity_at_contactPoint; - btVector3 relpos = m_raycastInfo.m_contactPointWS - chassis.getCenterOfMassPosition(); - chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint( relpos ); - btScalar projVel = m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); - if ( project >= btScalar(-0.1)) - { - m_suspensionRelativeVelocity = btScalar(0.0); - m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1); - } - else - { - btScalar inv = btScalar(-1.) / project; - m_suspensionRelativeVelocity = projVel * inv; - m_clippedInvContactDotSuspension = inv; - } - - } - - else // Not in contact : position wheel in a nice (rest length) position - { - m_raycastInfo.m_suspensionLength = this->getSuspensionRestLength(); - m_suspensionRelativeVelocity = btScalar(0.0); - m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS; - m_clippedInvContactDotSuspension = btScalar(1.0); - } -} diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h deleted file mode 100644 index ac2729f4fd7..00000000000 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies. - * Erwin Coumans makes no representations about the suitability - * of this software for any purpose. - * It is provided "as is" without express or implied warranty. -*/ -#ifndef WHEEL_INFO_H -#define WHEEL_INFO_H - -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransform.h" - -class btRigidBody; - -struct btWheelInfoConstructionInfo -{ - btVector3 m_chassisConnectionCS; - btVector3 m_wheelDirectionCS; - btVector3 m_wheelAxleCS; - btScalar m_suspensionRestLength; - btScalar m_maxSuspensionTravelCm; - btScalar m_wheelRadius; - - btScalar m_suspensionStiffness; - btScalar m_wheelsDampingCompression; - btScalar m_wheelsDampingRelaxation; - btScalar m_frictionSlip; - bool m_bIsFrontWheel; - -}; - -/// btWheelInfo contains information per wheel about friction and suspension. -struct btWheelInfo -{ - struct RaycastInfo - { - //set by raycaster - btVector3 m_contactNormalWS;//contactnormal - btVector3 m_contactPointWS;//raycast hitpoint - btScalar m_suspensionLength; - btVector3 m_hardPointWS;//raycast starting point - btVector3 m_wheelDirectionWS; //direction in worldspace - btVector3 m_wheelAxleWS; // axle in worldspace - bool m_isInContact; - void* m_groundObject; //could be general void* ptr - }; - - RaycastInfo m_raycastInfo; - - btTransform m_worldTransform; - - btVector3 m_chassisConnectionPointCS; //const - btVector3 m_wheelDirectionCS;//const - btVector3 m_wheelAxleCS; // const or modified by steering - btScalar m_suspensionRestLength1;//const - btScalar m_maxSuspensionTravelCm; - btScalar getSuspensionRestLength() const; - btScalar m_wheelsRadius;//const - btScalar m_suspensionStiffness;//const - btScalar m_wheelsDampingCompression;//const - btScalar m_wheelsDampingRelaxation;//const - btScalar m_frictionSlip; - btScalar m_steering; - btScalar m_rotation; - btScalar m_deltaRotation; - btScalar m_rollInfluence; - - btScalar m_engineForce; - - btScalar m_brake; - - bool m_bIsFrontWheel; - - void* m_clientInfo;//can be used to store pointer to sync transforms... - - btWheelInfo(btWheelInfoConstructionInfo& ci) - - { - - m_suspensionRestLength1 = ci.m_suspensionRestLength; - m_maxSuspensionTravelCm = ci.m_maxSuspensionTravelCm; - - m_wheelsRadius = ci.m_wheelRadius; - m_suspensionStiffness = ci.m_suspensionStiffness; - m_wheelsDampingCompression = ci.m_wheelsDampingCompression; - m_wheelsDampingRelaxation = ci.m_wheelsDampingRelaxation; - m_chassisConnectionPointCS = ci.m_chassisConnectionCS; - m_wheelDirectionCS = ci.m_wheelDirectionCS; - m_wheelAxleCS = ci.m_wheelAxleCS; - m_frictionSlip = ci.m_frictionSlip; - m_steering = btScalar(0.); - m_engineForce = btScalar(0.); - m_rotation = btScalar(0.); - m_deltaRotation = btScalar(0.); - m_brake = btScalar(0.); - m_rollInfluence = btScalar(0.1); - m_bIsFrontWheel = ci.m_bIsFrontWheel; - - } - - void updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo); - - btScalar m_clippedInvContactDotSuspension; - btScalar m_suspensionRelativeVelocity; - //calculated by suspension - btScalar m_wheelsSuspensionForce; - btScalar m_skidInfo; - -}; - -#endif //WHEEL_INFO_H - diff --git a/extern/bullet2/src/BulletDynamics/ibmsdk/Makefile b/extern/bullet2/src/BulletDynamics/ibmsdk/Makefile deleted file mode 100644 index b599a0fd9a1..00000000000 --- a/extern/bullet2/src/BulletDynamics/ibmsdk/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -#### Source code Dirs -VPATH = \ -../ConstraintSolver \ -../Dynamics \ -../Vehicle - -ROOT = ../../.. - -#### Library -LIBRARY_ppu = bulletdynamics.a - -#### Compiler flags -CPPFLAGS = \ --DUSE_LIBSPE2 \ --I../ConstraintSolver \ --I../Dynamics \ --I../Vehicle \ --I$(ROOT)/src \ --I$(SDKINC) - -#### Optimization level flags -#CC_OPT_LEVEL = $(CC_OPT_LEVEL_DEBUG) -CC_OPT_LEVEL = -O3 - -##### Objects to be archived in lib - -OBJS = \ -btContactConstraint.o \ -btGeneric6DofConstraint.o \ -btHingeConstraint.o \ -btPoint2PointConstraint.o \ -btSequentialImpulseConstraintSolver.o \ -btSolve2LinearConstraint.o \ -btTypedConstraint.o \ -btDiscreteDynamicsWorld.o \ -btRigidBody.o \ -btSimpleDynamicsWorld.o \ -btRaycastVehicle.o \ -btWheelInfo.o -#### Install directories -INSTALL_DIR = $(ROOT)/lib/ibmsdk -INSTALL_FILES = $(LIBRARY_ppu) -CELL_TOP ?= /opt/ibm/cell-sdk/prototype - -include $(CELL_TOP)/make.footer diff --git a/extern/bullet2/src/CMakeLists.txt b/extern/bullet2/src/CMakeLists.txt deleted file mode 100644 index 0ae1a7ab6ab..00000000000 --- a/extern/bullet2/src/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS( BulletCollision BulletDynamics LinearMath ) diff --git a/extern/bullet2/src/LinearMath/CMakeLists.txt b/extern/bullet2/src/LinearMath/CMakeLists.txt deleted file mode 100644 index 82393547bfb..00000000000 --- a/extern/bullet2/src/LinearMath/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ - -INCLUDE_DIRECTORIES( -${BULLET_PHYSICS_SOURCE_DIR}/src } -) - -ADD_LIBRARY(LibLinearMath -btQuickprof.cpp -btGeometryUtil.cpp -btAlignedAllocator.cpp -) - diff --git a/extern/bullet2/src/LinearMath/btAabbUtil2.h b/extern/bullet2/src/LinearMath/btAabbUtil2.h deleted file mode 100644 index 9b320961ba1..00000000000 --- a/extern/bullet2/src/LinearMath/btAabbUtil2.h +++ /dev/null @@ -1,125 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - - -#ifndef AABB_UTIL2 -#define AABB_UTIL2 - -#include "btVector3.h" -#include "btMinMax.h" - - - - -/// conservative test for overlap between two aabbs -SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1, - const btVector3 &aabbMin2, const btVector3 &aabbMax2) -{ - bool overlap = true; - overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; - overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; - overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; - return overlap; -} - -/// conservative test for overlap between triangle and aabb -SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3 *vertices, - const btVector3 &aabbMin, const btVector3 &aabbMax) -{ - const btVector3 &p1 = vertices[0]; - const btVector3 &p2 = vertices[1]; - const btVector3 &p3 = vertices[2]; - - if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false; - if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false; - - if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false; - if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false; - - if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false; - if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false; - return true; -} - - -SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent) -{ - return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) | - (p.getX() > halfExtent.getX() ? 0x08 : 0x0) | - (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) | - (p.getY() > halfExtent.getY() ? 0x10 : 0x0) | - (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) | - (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0); -} - - -SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, - const btVector3& rayTo, - const btVector3& aabbMin, - const btVector3& aabbMax, - btScalar& param, btVector3& normal) -{ - btVector3 aabbHalfExtent = (aabbMax-aabbMin)* btScalar(0.5); - btVector3 aabbCenter = (aabbMax+aabbMin)* btScalar(0.5); - btVector3 source = rayFrom - aabbCenter; - btVector3 target = rayTo - aabbCenter; - int sourceOutcode = btOutcode(source,aabbHalfExtent); - int targetOutcode = btOutcode(target,aabbHalfExtent); - if ((sourceOutcode & targetOutcode) == 0x0) - { - btScalar lambda_enter = btScalar(0.0); - btScalar lambda_exit = param; - btVector3 r = target - source; - int i; - btScalar normSign = 1; - btVector3 hitNormal(0,0,0); - int bit=1; - - for (int j=0;j<2;j++) - { - for (i = 0; i != 3; ++i) - { - if (sourceOutcode & bit) - { - btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i]; - if (lambda_enter <= lambda) - { - lambda_enter = lambda; - hitNormal.setValue(0,0,0); - hitNormal[i] = normSign; - } - } - else if (targetOutcode & bit) - { - btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i]; - btSetMin(lambda_exit, lambda); - } - bit<<=1; - } - normSign = btScalar(-1.); - } - if (lambda_enter <= lambda_exit) - { - param = lambda_enter; - normal = hitNormal; - return true; - } - } - return false; -} - - -#endif - diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp deleted file mode 100644 index 6b33ddbb8cf..00000000000 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* -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. -*/ - -#include "btAlignedAllocator.h" - -int gNumAlignedAllocs = 0; -int gNumAlignedFree = 0; -int gTotalBytesAlignedAllocs = 0;//detect memory leaks - -#ifdef BT_DEBUG_MEMORY_ALLOCATIONS -//this generic allocator provides the total allocated number of bytes -#include - -void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename) -{ - void *ret; - char *real; - unsigned long offset; - - gTotalBytesAlignedAllocs += size; - gNumAlignedAllocs++; - - printf("allocation#%d from %s,line %d, size %d\n",gNumAlignedAllocs,filename,line,size); - real = (char *)malloc(size + 2*sizeof(void *) + (alignment-1)); - if (real) { - offset = (alignment - (unsigned long)(real + 2*sizeof(void *))) & -(alignment-1); - ret = (void *)((real + 2*sizeof(void *)) + offset); - *((void **)(ret)-1) = (void *)(real); - *((int*)(ret)-2) = size; - - } else { - ret = (void *)(real);//?? - } - int* ptr = (int*)ret; - *ptr = 12; - return (ret); -} -#include -void btAlignedFreeInternal (void* ptr,int line,char* filename) -{ - - void* real; - gNumAlignedFree++; - - if (ptr) { - real = *((void **)(ptr)-1); - int size = *((int*)(ptr)-2); - gTotalBytesAlignedAllocs -= size; - - printf("free #%d from %s,line %d, size %d\n",gNumAlignedFree,filename,line,size); - - free(real); - } else - { - printf("NULL ptr\n"); - } -} - -#else //BT_DEBUG_MEMORY_ALLOCATIONS - - -#if defined (BT_HAS_ALIGNED_ALLOCATOR) - - - - - -#include -void* btAlignedAllocInternal (size_t size, int alignment) -{ - gNumAlignedAllocs++; - - void* ptr = _aligned_malloc(size,alignment); -// printf("btAlignedAllocInternal %d, %x\n",size,ptr); - return ptr; -} - -void btAlignedFreeInternal (void* ptr) -{ - gNumAlignedFree++; -// printf("btAlignedFreeInternal %x\n",ptr); - _aligned_free(ptr); -} - -#else - -#ifdef __CELLOS_LV2__ - -#include - - - -void* btAlignedAllocInternal (size_t size, int alignment) -{ - gNumAlignedAllocs++; - return memalign(alignment, size); -} - -void btAlignedFreeInternal (void* ptr) -{ - gNumAlignedFree++; - free(ptr); -} - -#else - -void* btAlignedAllocInternal (size_t size, int alignment) -{ - void *ret; - char *real; - unsigned long offset; - - gNumAlignedAllocs++; - - real = (char *)malloc(size + sizeof(void *) + (alignment-1)); - if (real) { - offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); - ret = (void *)((real + sizeof(void *)) + offset); - *((void **)(ret)-1) = (void *)(real); - } else { - ret = (void *)(real); - } - return (ret); -} - -void btAlignedFreeInternal (void* ptr) -{ - - void* real; - gNumAlignedFree++; - - if (ptr) { - real = *((void **)(ptr)-1); - free(real); - } -} -#endif // - -#endif - -#endif //BT_DEBUG_MEMORY_ALLOCATIONS - diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.h b/extern/bullet2/src/LinearMath/btAlignedAllocator.h deleted file mode 100644 index 2b48e79e497..00000000000 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -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. -*/ - -#ifndef BT_ALIGNED_ALLOCATOR -#define BT_ALIGNED_ALLOCATOR - -///we probably replace this with our own aligned memory allocator -///so we replace _aligned_malloc and _aligned_free with our own -///that is better portable and more predictable - -#include "btScalar.h" -//#define BT_DEBUG_MEMORY_ALLOCATIONS 1 -#ifdef BT_DEBUG_MEMORY_ALLOCATIONS - -#define btAlignedAlloc(a,b) \ - btAlignedAllocInternal(a,b,__LINE__,__FILE__) - -#define btAlignedFree(ptr) \ - btAlignedFreeInternal(ptr,__LINE__,__FILE__) - -void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename); - -void btAlignedFreeInternal (void* ptr,int line,char* filename); - -#else - void* btAlignedAllocInternal (size_t size, int alignment); - void btAlignedFreeInternal (void* ptr); - - #define btAlignedAlloc(a,b) btAlignedAllocInternal(a,b) - #define btAlignedFree(ptr) btAlignedFreeInternal(ptr) -#endif -typedef int size_type; - - -template < typename T , unsigned Alignment > -class btAlignedAllocator { - - typedef btAlignedAllocator< T , Alignment > self_type; - -public: - - //just going down a list: - btAlignedAllocator() {} - /* - btAlignedAllocator( const self_type & ) {} - */ - - template < typename Other > - btAlignedAllocator( const btAlignedAllocator< Other , Alignment > & ) {} - - typedef const T* const_pointer; - typedef const T& const_reference; - typedef T* pointer; - typedef T& reference; - typedef T value_type; - - pointer address ( reference ref ) const { return &ref; } - const_pointer address ( const_reference ref ) const { return &ref; } - pointer allocate ( size_type n , const_pointer * hint = 0 ) { - (void)hint; - return reinterpret_cast< pointer >(btAlignedAlloc( sizeof(value_type) * n , Alignment )); - } - void construct ( pointer ptr , const value_type & value ) { new (ptr) value_type( value ); } - void deallocate( pointer ptr ) { - btAlignedFree( reinterpret_cast< void * >( ptr ) ); - } - void destroy ( pointer ptr ) { ptr->~value_type(); } - - - template < typename O > struct rebind { - typedef btAlignedAllocator< O , Alignment > other; - }; - template < typename O > - self_type & operator=( const btAlignedAllocator< O , Alignment > & ) { return *this; } - - friend bool operator==( const self_type & , const self_type & ) { return true; } -}; - - - -#endif //BT_ALIGNED_ALLOCATOR - diff --git a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h deleted file mode 100644 index 66911316fbb..00000000000 --- a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h +++ /dev/null @@ -1,386 +0,0 @@ -/* -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. -*/ - - -#ifndef BT_OBJECT_ARRAY__ -#define BT_OBJECT_ARRAY__ - -#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE -#include "btAlignedAllocator.h" - -///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW -///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors -///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator= -///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and -///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240 - -#define BT_USE_PLACEMENT_NEW 1 -//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in or or otherwise... - -#ifdef BT_USE_MEMCPY -#include -#include -#endif //BT_USE_MEMCPY - -#ifdef BT_USE_PLACEMENT_NEW -#include //for placement new -#endif //BT_USE_PLACEMENT_NEW - - -///btAlignedObjectArray uses a subset of the stl::vector interface for its methods -///It is developed to replace stl::vector to avoid STL alignment issues to add SIMD/SSE data -template -//template -class btAlignedObjectArray -{ - btAlignedAllocator m_allocator; - - int m_size; - int m_capacity; - T* m_data; - //PCK: added this line - bool m_ownsMemory; - - protected: - SIMD_FORCE_INLINE int allocSize(int size) - { - return (size ? size*2 : 1); - } - SIMD_FORCE_INLINE void copy(int start,int end, T* dest) - { - int i; - for (i=start;i size()) - { - reserve(newsize); - } -#ifdef BT_USE_PLACEMENT_NEW - for (int i=curSize;i - void downHeap(T *pArr, int k, int n,L CompareFunc) - { - /* PRE: a[k+1..N] is a heap */ - /* POST: a[k..N] is a heap */ - - T temp = pArr[k - 1]; - /* k has child(s) */ - while (k <= n/2) - { - int child = 2*k; - - if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child])) - { - child++; - } - /* pick larger child */ - if (CompareFunc(temp , pArr[child - 1])) - { - /* move child up */ - pArr[k - 1] = pArr[child - 1]; - k = child; - } - else - { - break; - } - } - pArr[k - 1] = temp; - } /*downHeap*/ - - void swap(int index0,int index1) - { -#ifdef BT_USE_MEMCPY - char temp[sizeof(T)]; - memcpy(temp,&m_data[index0],sizeof(T)); - memcpy(&m_data[index0],&m_data[index1],sizeof(T)); - memcpy(&m_data[index1],temp,sizeof(T)); -#else - T temp = m_data[index0]; - m_data[index0] = m_data[index1]; - m_data[index1] = temp; -#endif //BT_USE_PLACEMENT_NEW - - } - - template - void heapSort(L CompareFunc) - { - /* sort a[0..N-1], N.B. 0 to N-1 */ - int k; - int n = m_size; - for (k = n/2; k > 0; k--) - { - downHeap(m_data, k, n, CompareFunc); - } - - /* a[1..N] is now a heap */ - while ( n>=1 ) - { - swap(0,n-1); /* largest of a[0..n-1] */ - - - n = n - 1; - /* restore a[1..i-1] heap */ - downHeap(m_data, 1, n, CompareFunc); - } - } - - ///non-recursive binary search, assumes sorted array - int findBinarySearch(const T& key) const - { - int first = 0; - int last = size(); - - //assume sorted array - while (first <= last) { - int mid = (first + last) / 2; // compute mid point. - if (key > m_data[mid]) - first = mid + 1; // repeat search in top half. - else if (key < m_data[mid]) - last = mid - 1; // repeat search in bottom half. - else - return mid; // found it. return position ///// - } - return size(); // failed to find key - } - - - int findLinearSearch(const T& key) const - { - int index=size(); - int i; - - for (i=0;i& planeEquations, const btVector3& point, btScalar margin) -{ - int numbrushes = planeEquations.size(); - for (int i=0;ibtScalar(0.)) - { - return false; - } - } - return true; - -} - - -bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray& vertices, btScalar margin) -{ - int numvertices = vertices.size(); - for (int i=0;ibtScalar(0.)) - { - return false; - } - } - return true; -} - -bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations) -{ - int numbrushes = planeEquations.size(); - for (int i=0;i btScalar(0.999)) - { - return false; - } - } - return true; -} - -void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray& vertices, btAlignedObjectArray& planeEquationsOut ) -{ - const int numvertices = vertices.size(); - // brute force: - for (int i=0;i btScalar(0.0001)) - { - planeEquation.normalize(); - if (notExist(planeEquation,planeEquationsOut)) - { - planeEquation[3] = -planeEquation.dot(N1); - - //check if inside, and replace supportingVertexOut if needed - if (areVerticesBehindPlane(planeEquation,vertices,btScalar(0.01))) - { - planeEquationsOut.push_back(planeEquation); - } - } - } - normalSign = btScalar(-1.); - } - - } - } - } - -} - -void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray& planeEquations , btAlignedObjectArray& verticesOut ) -{ - const int numbrushes = planeEquations.size(); - // brute force: - for (int i=0;i btScalar(0.0001) ) && - ( n3n1.length2() > btScalar(0.0001) ) && - ( n1n2.length2() > btScalar(0.0001) ) ) - { - //point P out of 3 plane equations: - - // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 ) - //P = ------------------------------------------------------------------------- - // N1 . ( N2 * N3 ) - - - btScalar quotient = (N1.dot(n2n3)); - if (btFabs(quotient) > btScalar(0.000001)) - { - quotient = btScalar(-1.) / quotient; - n2n3 *= N1[3]; - n3n1 *= N2[3]; - n1n2 *= N3[3]; - btVector3 potentialVertex = n2n3; - potentialVertex += n3n1; - potentialVertex += n1n2; - potentialVertex *= quotient; - - //check if inside, and replace supportingVertexOut if needed - if (isPointInsidePlanes(planeEquations,potentialVertex,btScalar(0.01))) - { - verticesOut.push_back(potentialVertex); - } - } - } - } - } - } -} - diff --git a/extern/bullet2/src/LinearMath/btGeometryUtil.h b/extern/bullet2/src/LinearMath/btGeometryUtil.h deleted file mode 100644 index 766cd75c383..00000000000 --- a/extern/bullet2/src/LinearMath/btGeometryUtil.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - -#ifndef BT_GEOMETRY_UTIL_H -#define BT_GEOMETRY_UTIL_H - -#include "btVector3.h" -#include "btAlignedObjectArray.h" - -class btGeometryUtil -{ - public: - - - static void getPlaneEquationsFromVertices(btAlignedObjectArray& vertices, btAlignedObjectArray& planeEquationsOut ); - - static void getVerticesFromPlaneEquations(const btAlignedObjectArray& planeEquations , btAlignedObjectArray& verticesOut ); - - static bool isInside(const btAlignedObjectArray& vertices, const btVector3& planeNormal, btScalar margin); - - static bool isPointInsidePlanes(const btAlignedObjectArray& planeEquations, const btVector3& point, btScalar margin); - - static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray& vertices, btScalar margin); - -}; - - -#endif //BT_GEOMETRY_UTIL_H - diff --git a/extern/bullet2/src/LinearMath/btIDebugDraw.h b/extern/bullet2/src/LinearMath/btIDebugDraw.h deleted file mode 100644 index 2d96cff5055..00000000000 --- a/extern/bullet2/src/LinearMath/btIDebugDraw.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -Copyright (c) 2005 Gino van den Bergen / Erwin Coumans http://continuousphysics.com - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef IDEBUG_DRAW__H -#define IDEBUG_DRAW__H - -#include "btVector3.h" - - -class btIDebugDraw -{ - public: - - enum DebugDrawModes - { - DBG_NoDebug=0, - DBG_DrawWireframe = 1, - DBG_DrawAabb=2, - DBG_DrawFeaturesText=4, - DBG_DrawContactPoints=8, - DBG_NoDeactivation=16, - DBG_NoHelpText = 32, - DBG_DrawText=64, - DBG_ProfileTimings = 128, - DBG_EnableSatComparison = 256, - DBG_DisableBulletLCP = 512, - DBG_EnableCCD = 1024, - DBG_MAX_DEBUG_DRAW_MODE - }; - - virtual ~btIDebugDraw() {}; - - virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0; - - virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0; - - virtual void reportErrorWarning(const char* warningString) = 0; - - virtual void draw3dText(const btVector3& location,const char* textString) = 0; - - virtual void setDebugMode(int debugMode) =0; - - virtual int getDebugMode() const = 0; - - inline void drawAabb(const btVector3& from,const btVector3& to,const btVector3& color) - { - - btVector3 halfExtents = (to-from)* 0.5f; - btVector3 center = (to+from) *0.5f; - int i,j; - - btVector3 edgecoord(1.f,1.f,1.f),pa,pb; - for (i=0;i<4;i++) - { - for (j=0;j<3;j++) - { - pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], - edgecoord[2]*halfExtents[2]); - pa+=center; - - int othercoord = j%3; - edgecoord[othercoord]*=-1.f; - pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], - edgecoord[2]*halfExtents[2]); - pb+=center; - - drawLine(pa,pb,color); - } - edgecoord = btVector3(-1.f,-1.f,-1.f); - if (i<3) - edgecoord[i]*=-1.f; - } - } -}; - - -#endif //IDEBUG_DRAW__H - diff --git a/extern/bullet2/src/LinearMath/btList.h b/extern/bullet2/src/LinearMath/btList.h deleted file mode 100644 index c87b47faf2b..00000000000 --- a/extern/bullet2/src/LinearMath/btList.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - - -#ifndef GEN_LIST_H -#define GEN_LIST_H - -class btGEN_Link { -public: - btGEN_Link() : m_next(0), m_prev(0) {} - btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {} - - btGEN_Link *getNext() const { return m_next; } - btGEN_Link *getPrev() const { return m_prev; } - - bool isHead() const { return m_prev == 0; } - bool isTail() const { return m_next == 0; } - - void insertBefore(btGEN_Link *link) { - m_next = link; - m_prev = link->m_prev; - m_next->m_prev = this; - m_prev->m_next = this; - } - - void insertAfter(btGEN_Link *link) { - m_next = link->m_next; - m_prev = link; - m_next->m_prev = this; - m_prev->m_next = this; - } - - void remove() { - m_next->m_prev = m_prev; - m_prev->m_next = m_next; - } - -private: - btGEN_Link *m_next; - btGEN_Link *m_prev; -}; - -class btGEN_List { -public: - btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {} - - btGEN_Link *getHead() const { return m_head.getNext(); } - btGEN_Link *getTail() const { return m_tail.getPrev(); } - - void addHead(btGEN_Link *link) { link->insertAfter(&m_head); } - void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); } - -private: - btGEN_Link m_head; - btGEN_Link m_tail; -}; - -#endif - - - diff --git a/extern/bullet2/src/LinearMath/btMatrix3x3.h b/extern/bullet2/src/LinearMath/btMatrix3x3.h deleted file mode 100644 index 59680ff460d..00000000000 --- a/extern/bullet2/src/LinearMath/btMatrix3x3.h +++ /dev/null @@ -1,410 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - -#ifndef btMatrix3x3_H -#define btMatrix3x3_H - -#include "btScalar.h" - -#include "btVector3.h" -#include "btQuaternion.h" - - -class btMatrix3x3 { - public: - btMatrix3x3 () {} - -// explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); } - - explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); } - /* - template - Matrix3x3(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) - { - setEulerYPR(yaw, pitch, roll); - } - */ - btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz, - const btScalar& yx, const btScalar& yy, const btScalar& yz, - const btScalar& zx, const btScalar& zy, const btScalar& zz) - { - setValue(xx, xy, xz, - yx, yy, yz, - zx, zy, zz); - } - - SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other) - { - m_el[0] = other.m_el[0]; - m_el[1] = other.m_el[1]; - m_el[2] = other.m_el[2]; - } - - SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other) - { - m_el[0] = other.m_el[0]; - m_el[1] = other.m_el[1]; - m_el[2] = other.m_el[2]; - return *this; - } - - SIMD_FORCE_INLINE btVector3 getColumn(int i) const - { - return btVector3(m_el[0][i],m_el[1][i],m_el[2][i]); - } - - - - SIMD_FORCE_INLINE const btVector3& getRow(int i) const - { - return m_el[i]; - } - - - SIMD_FORCE_INLINE btVector3& operator[](int i) - { - btFullAssert(0 <= i && i < 3); - return m_el[i]; - } - - SIMD_FORCE_INLINE const btVector3& operator[](int i) const - { - btFullAssert(0 <= i && i < 3); - return m_el[i]; - } - - btMatrix3x3& operator*=(const btMatrix3x3& m); - - - void setFromOpenGLSubMatrix(const btScalar *m) - { - m_el[0].setValue(m[0],m[4],m[8]); - m_el[1].setValue(m[1],m[5],m[9]); - m_el[2].setValue(m[2],m[6],m[10]); - - } - - void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz, - const btScalar& yx, const btScalar& yy, const btScalar& yz, - const btScalar& zx, const btScalar& zy, const btScalar& zz) - { - m_el[0].setValue(xx,xy,xz); - m_el[1].setValue(yx,yy,yz); - m_el[2].setValue(zx,zy,zz); - } - - void setRotation(const btQuaternion& q) - { - btScalar d = q.length2(); - btFullAssert(d != btScalar(0.0)); - btScalar s = btScalar(2.0) / d; - btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s; - btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs; - btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs; - btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs; - setValue(btScalar(1.0) - (yy + zz), xy - wz, xz + wy, - xy + wz, btScalar(1.0) - (xx + zz), yz - wx, - xz - wy, yz + wx, btScalar(1.0) - (xx + yy)); - } - - - - void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) - { - - btScalar cy(btCos(yaw)); - btScalar sy(btSin(yaw)); - btScalar cp(btCos(pitch)); - btScalar sp(btSin(pitch)); - btScalar cr(btCos(roll)); - btScalar sr(btSin(roll)); - btScalar cc = cy * cr; - btScalar cs = cy * sr; - btScalar sc = sy * cr; - btScalar ss = sy * sr; - setValue(cc - sp * ss, -cs - sp * sc, -sy * cp, - cp * sr, cp * cr, -sp, - sc + sp * cs, -ss + sp * cc, cy * cp); - - } - - /** - * setEulerZYX - * @param euler a const reference to a btVector3 of euler angles - * These angles are used to produce a rotation matrix. The euler - * angles are applied in ZYX order. I.e a vector is first rotated - * about X then Y and then Z - **/ - - void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) { - btScalar ci ( btCos(eulerX)); - btScalar cj ( btCos(eulerY)); - btScalar ch ( btCos(eulerZ)); - btScalar si ( btSin(eulerX)); - btScalar sj ( btSin(eulerY)); - btScalar sh ( btSin(eulerZ)); - btScalar cc = ci * ch; - btScalar cs = ci * sh; - btScalar sc = si * ch; - btScalar ss = si * sh; - - setValue(cj * ch, sj * sc - cs, sj * cc + ss, - cj * sh, sj * ss + cc, sj * cs - sc, - -sj, cj * si, cj * ci); - } - - void setIdentity() - { - setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0), - btScalar(0.0), btScalar(1.0), btScalar(0.0), - btScalar(0.0), btScalar(0.0), btScalar(1.0)); - } - - void getOpenGLSubMatrix(btScalar *m) const - { - m[0] = btScalar(m_el[0].x()); - m[1] = btScalar(m_el[1].x()); - m[2] = btScalar(m_el[2].x()); - m[3] = btScalar(0.0); - m[4] = btScalar(m_el[0].y()); - m[5] = btScalar(m_el[1].y()); - m[6] = btScalar(m_el[2].y()); - m[7] = btScalar(0.0); - m[8] = btScalar(m_el[0].z()); - m[9] = btScalar(m_el[1].z()); - m[10] = btScalar(m_el[2].z()); - m[11] = btScalar(0.0); - } - - void getRotation(btQuaternion& q) const - { - btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z(); - btScalar temp[4]; - - if (trace > btScalar(0.0)) - { - btScalar s = btSqrt(trace + btScalar(1.0)); - temp[3]=(s * btScalar(0.5)); - s = btScalar(0.5) / s; - - temp[0]=((m_el[2].y() - m_el[1].z()) * s); - temp[1]=((m_el[0].z() - m_el[2].x()) * s); - temp[2]=((m_el[1].x() - m_el[0].y()) * s); - } - else - { - int i = m_el[0].x() < m_el[1].y() ? - (m_el[1].y() < m_el[2].z() ? 2 : 1) : - (m_el[0].x() < m_el[2].z() ? 2 : 0); - int j = (i + 1) % 3; - int k = (i + 2) % 3; - - btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0)); - temp[i] = s * btScalar(0.5); - s = btScalar(0.5) / s; - - temp[3] = (m_el[k][j] - m_el[j][k]) * s; - temp[j] = (m_el[j][i] + m_el[i][j]) * s; - temp[k] = (m_el[k][i] + m_el[i][k]) * s; - } - q.setValue(temp[0],temp[1],temp[2],temp[3]); - } - - void getEuler(btScalar& yaw, btScalar& pitch, btScalar& roll) const - { - - if (btScalar(m_el[1].z()) < btScalar(1)) - { - if (btScalar(m_el[1].z()) > -btScalar(1)) - { - yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x())); - pitch = btScalar(btAsin(-m_el[1].y())); - roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z())); - } - else - { - yaw = btScalar(-btAtan2(-m_el[0].y(), m_el[0].z())); - pitch = SIMD_HALF_PI; - roll = btScalar(0.0); - } - } - else - { - yaw = btScalar(btAtan2(-m_el[0].y(), m_el[0].z())); - pitch = -SIMD_HALF_PI; - roll = btScalar(0.0); - } - } - - - - - btMatrix3x3 scaled(const btVector3& s) const - { - return btMatrix3x3(m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(), - m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(), - m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z()); - } - - btScalar determinant() const; - btMatrix3x3 adjoint() const; - btMatrix3x3 absolute() const; - btMatrix3x3 transpose() const; - btMatrix3x3 inverse() const; - - btMatrix3x3 transposeTimes(const btMatrix3x3& m) const; - btMatrix3x3 timesTranspose(const btMatrix3x3& m) const; - - SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const - { - return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z(); - } - SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const - { - return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z(); - } - SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const - { - return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z(); - } - - - - protected: - btScalar cofac(int r1, int c1, int r2, int c2) const - { - return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1]; - } - - btVector3 m_el[3]; - }; - - SIMD_FORCE_INLINE btMatrix3x3& - btMatrix3x3::operator*=(const btMatrix3x3& m) - { - setValue(m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]), - m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]), - m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2])); - return *this; - } - - SIMD_FORCE_INLINE btScalar - btMatrix3x3::determinant() const - { - return triple((*this)[0], (*this)[1], (*this)[2]); - } - - - SIMD_FORCE_INLINE btMatrix3x3 - btMatrix3x3::absolute() const - { - return btMatrix3x3( - btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()), - btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()), - btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z())); - } - - SIMD_FORCE_INLINE btMatrix3x3 - btMatrix3x3::transpose() const - { - return btMatrix3x3(m_el[0].x(), m_el[1].x(), m_el[2].x(), - m_el[0].y(), m_el[1].y(), m_el[2].y(), - m_el[0].z(), m_el[1].z(), m_el[2].z()); - } - - SIMD_FORCE_INLINE btMatrix3x3 - btMatrix3x3::adjoint() const - { - return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2), - cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0), - cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1)); - } - - SIMD_FORCE_INLINE btMatrix3x3 - btMatrix3x3::inverse() const - { - btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)); - btScalar det = (*this)[0].dot(co); - btFullAssert(det != btScalar(0.0)); - btScalar s = btScalar(1.0) / det; - return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s, - co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s, - co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s); - } - - SIMD_FORCE_INLINE btMatrix3x3 - btMatrix3x3::transposeTimes(const btMatrix3x3& m) const - { - return btMatrix3x3( - m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(), - m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(), - m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(), - m_el[0].y() * m[0].x() + m_el[1].y() * m[1].x() + m_el[2].y() * m[2].x(), - m_el[0].y() * m[0].y() + m_el[1].y() * m[1].y() + m_el[2].y() * m[2].y(), - m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(), - m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(), - m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(), - m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z()); - } - - SIMD_FORCE_INLINE btMatrix3x3 - btMatrix3x3::timesTranspose(const btMatrix3x3& m) const - { - return btMatrix3x3( - m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]), - m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]), - m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2])); - - } - - SIMD_FORCE_INLINE btVector3 - operator*(const btMatrix3x3& m, const btVector3& v) - { - return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v)); - } - - - SIMD_FORCE_INLINE btVector3 - operator*(const btVector3& v, const btMatrix3x3& m) - { - return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v)); - } - - SIMD_FORCE_INLINE btMatrix3x3 - operator*(const btMatrix3x3& m1, const btMatrix3x3& m2) - { - return btMatrix3x3( - m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]), - m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]), - m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2])); - } - -/* - SIMD_FORCE_INLINE btMatrix3x3 btMultTransposeLeft(const btMatrix3x3& m1, const btMatrix3x3& m2) { - return btMatrix3x3( - m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0], - m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1], - m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2], - m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0], - m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1], - m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2], - m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0], - m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1], - m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]); -} -*/ - - -#endif diff --git a/extern/bullet2/src/LinearMath/btMinMax.h b/extern/bullet2/src/LinearMath/btMinMax.h deleted file mode 100644 index 5e27d62a4a4..00000000000 --- a/extern/bullet2/src/LinearMath/btMinMax.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - - -#ifndef GEN_MINMAX_H -#define GEN_MINMAX_H - -template -SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) -{ - return a < b ? a : b ; -} - -template -SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) -{ - return a > b ? a : b; -} - -template -SIMD_FORCE_INLINE const T& GEN_clamped(const T& a, const T& lb, const T& ub) -{ - return a < lb ? lb : (ub < a ? ub : a); -} - -template -SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) -{ - if (b < a) - { - a = b; - } -} - -template -SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) -{ - if (a < b) - { - a = b; - } -} - -template -SIMD_FORCE_INLINE void GEN_clamp(T& a, const T& lb, const T& ub) -{ - if (a < lb) - { - a = lb; - } - else if (ub < a) - { - a = ub; - } -} - -#endif diff --git a/extern/bullet2/src/LinearMath/btMotionState.h b/extern/bullet2/src/LinearMath/btMotionState.h deleted file mode 100644 index 1975e5ff900..00000000000 --- a/extern/bullet2/src/LinearMath/btMotionState.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -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. -*/ - -#ifndef BT_MOTIONSTATE_H -#define BT_MOTIONSTATE_H - -#include "btTransform.h" - -///btMotionState allows the dynamics world to synchronize the updated world transforms with graphics -///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation) -class btMotionState -{ - public: - - virtual ~btMotionState() - { - - } - - virtual void getWorldTransform(btTransform& worldTrans ) const =0; - - //Bullet only calls the update of worldtransform for active objects - virtual void setWorldTransform(const btTransform& worldTrans)=0; - - -}; - -#endif //BT_MOTIONSTATE_H diff --git a/extern/bullet2/src/LinearMath/btPoint3.h b/extern/bullet2/src/LinearMath/btPoint3.h deleted file mode 100644 index a2020e26d12..00000000000 --- a/extern/bullet2/src/LinearMath/btPoint3.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - - -#ifndef btPoint3_H -#define btPoint3_H - -#include "btVector3.h" - -typedef btVector3 btPoint3; - -#endif diff --git a/extern/bullet2/src/LinearMath/btPoolAllocator.h b/extern/bullet2/src/LinearMath/btPoolAllocator.h deleted file mode 100755 index ad772ae123f..00000000000 --- a/extern/bullet2/src/LinearMath/btPoolAllocator.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - -#ifndef _BT_POOL_ALLOCATOR_H -#define _BT_POOL_ALLOCATOR_H - -#include "btScalar.h" -#include "btAlignedAllocator.h" - -class btPoolAllocator -{ - int m_elemSize; - int m_maxElements; - int m_freeCount; - void* m_firstFree; - unsigned char* m_pool; - -public: - - btPoolAllocator(int elemSize, int maxElements) - :m_elemSize(elemSize), - m_maxElements(maxElements) - { - m_pool = (unsigned char*) btAlignedAlloc(m_elemSize*m_maxElements,16); - - unsigned char* p = m_pool; - m_firstFree = p; - m_freeCount = m_maxElements; - int count = m_maxElements; - while (--count) { - *(void**)p = (p + m_elemSize); - p += m_elemSize; - } - *(void**)p = 0; - } - - ~btPoolAllocator() - { - btAlignedFree( m_pool); - } - - int getFreeCount() const - { - return m_freeCount; - } - - void* allocate(int size) - { - btAssert(!size || size<=m_elemSize); - btAssert(m_freeCount>0); - void* result = m_firstFree; - m_firstFree = *(void**)m_firstFree; - --m_freeCount; - return result; - } - - bool validPtr(void* ptr) - { - if (ptr) { - if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize)) - { - return true; - } - } - return false; - } - - void free(void* ptr) - { - if (ptr) { - btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize); - - *(void**)ptr = m_firstFree; - m_firstFree = ptr; - ++m_freeCount; - } - } - - -}; - -#endif //_BT_POOL_ALLOCATOR_H diff --git a/extern/bullet2/src/LinearMath/btQuadWord.h b/extern/bullet2/src/LinearMath/btQuadWord.h deleted file mode 100644 index 2e5950ebd5d..00000000000 --- a/extern/bullet2/src/LinearMath/btQuadWord.h +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - -#ifndef SIMD_QUADWORD_H -#define SIMD_QUADWORD_H - -#include "btScalar.h" -#include "btMinMax.h" - -//ATTRIBUTE_ALIGNED16(class) btQuadWordStorage -//some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword. todo: look into this - -class btQuadWordStorage -{ -protected: - btScalar m_x; - btScalar m_y; - btScalar m_z; - btScalar m_unusedW; -}; - - -///btQuadWord is base-class for vectors, points -class btQuadWord : public btQuadWordStorage -{ - public: - -// SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_x)[i]; } -// SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_x)[i]; } - - SIMD_FORCE_INLINE const btScalar& getX() const { return m_x; } - - SIMD_FORCE_INLINE const btScalar& getY() const { return m_y; } - - SIMD_FORCE_INLINE const btScalar& getZ() const { return m_z; } - - SIMD_FORCE_INLINE void setX(btScalar x) { m_x = x;}; - - SIMD_FORCE_INLINE void setY(btScalar y) { m_y = y;}; - - SIMD_FORCE_INLINE void setZ(btScalar z) { m_z = z;}; - - SIMD_FORCE_INLINE void setW(btScalar w) { m_unusedW = w;}; - - SIMD_FORCE_INLINE const btScalar& x() const { return m_x; } - - SIMD_FORCE_INLINE const btScalar& y() const { return m_y; } - - SIMD_FORCE_INLINE const btScalar& z() const { return m_z; } - - SIMD_FORCE_INLINE const btScalar& w() const { return m_unusedW; } - - - SIMD_FORCE_INLINE operator btScalar *() { return &m_x; } - SIMD_FORCE_INLINE operator const btScalar *() const { return &m_x; } - - - - SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) - { - m_x=x; - m_y=y; - m_z=z; - m_unusedW = 0.f; - } - -/* void getValue(btScalar *m) const - { - m[0] = m_x; - m[1] = m_y; - m[2] = m_z; - } -*/ - SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) - { - m_x=x; - m_y=y; - m_z=z; - m_unusedW=w; - } - - SIMD_FORCE_INLINE btQuadWord() - // :m_x(btScalar(0.)),m_y(btScalar(0.)),m_z(btScalar(0.)),m_unusedW(btScalar(0.)) - { - } - - SIMD_FORCE_INLINE btQuadWord(const btQuadWordStorage& q) - { - *((btQuadWordStorage*)this) = q; - } - - SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z) - { - m_x = x, m_y = y, m_z = z, m_unusedW = 0.0f; - } - - SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) - { - m_x = x, m_y = y, m_z = z, m_unusedW = w; - } - - - SIMD_FORCE_INLINE void setMax(const btQuadWord& other) - { - btSetMax(m_x, other.m_x); - btSetMax(m_y, other.m_y); - btSetMax(m_z, other.m_z); - btSetMax(m_unusedW, other.m_unusedW); - } - - SIMD_FORCE_INLINE void setMin(const btQuadWord& other) - { - btSetMin(m_x, other.m_x); - btSetMin(m_y, other.m_y); - btSetMin(m_z, other.m_z); - btSetMin(m_unusedW, other.m_unusedW); - } - - - -}; - -#endif //SIMD_QUADWORD_H diff --git a/extern/bullet2/src/LinearMath/btQuaternion.h b/extern/bullet2/src/LinearMath/btQuaternion.h deleted file mode 100644 index 27ab1fcd2c3..00000000000 --- a/extern/bullet2/src/LinearMath/btQuaternion.h +++ /dev/null @@ -1,321 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - - -#ifndef SIMD__QUATERNION_H_ -#define SIMD__QUATERNION_H_ - -#include "btVector3.h" - -class btQuaternion : public btQuadWord { -public: - btQuaternion() {} - - // template - // explicit Quaternion(const btScalar *v) : Tuple4(v) {} - - btQuaternion(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w) - : btQuadWord(x, y, z, w) - {} - - btQuaternion(const btVector3& axis, const btScalar& angle) - { - setRotation(axis, angle); - } - - btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) - { - setEuler(yaw, pitch, roll); - } - - void setRotation(const btVector3& axis, const btScalar& angle) - { - btScalar d = axis.length(); - assert(d != btScalar(0.0)); - btScalar s = btSin(angle * btScalar(0.5)) / d; - setValue(axis.x() * s, axis.y() * s, axis.z() * s, - btCos(angle * btScalar(0.5))); - } - - void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) - { - btScalar halfYaw = btScalar(yaw) * btScalar(0.5); - btScalar halfPitch = btScalar(pitch) * btScalar(0.5); - btScalar halfRoll = btScalar(roll) * btScalar(0.5); - btScalar cosYaw = btCos(halfYaw); - btScalar sinYaw = btSin(halfYaw); - btScalar cosPitch = btCos(halfPitch); - btScalar sinPitch = btSin(halfPitch); - btScalar cosRoll = btCos(halfRoll); - btScalar sinRoll = btSin(halfRoll); - setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, - cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, - sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, - cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); - } - - btQuaternion& operator+=(const btQuaternion& q) - { - m_x += q.x(); m_y += q.y(); m_z += q.z(); m_unusedW += q.m_unusedW; - return *this; - } - - btQuaternion& operator-=(const btQuaternion& q) - { - m_x -= q.x(); m_y -= q.y(); m_z -= q.z(); m_unusedW -= q.m_unusedW; - return *this; - } - - btQuaternion& operator*=(const btScalar& s) - { - m_x *= s; m_y *= s; m_z *= s; m_unusedW *= s; - return *this; - } - - - btQuaternion& operator*=(const btQuaternion& q) - { - setValue(m_unusedW * q.x() + m_x * q.m_unusedW + m_y * q.z() - m_z * q.y(), - m_unusedW * q.y() + m_y * q.m_unusedW + m_z * q.x() - m_x * q.z(), - m_unusedW * q.z() + m_z * q.m_unusedW + m_x * q.y() - m_y * q.x(), - m_unusedW * q.m_unusedW - m_x * q.x() - m_y * q.y() - m_z * q.z()); - return *this; - } - - btScalar dot(const btQuaternion& q) const - { - return m_x * q.x() + m_y * q.y() + m_z * q.z() + m_unusedW * q.m_unusedW; - } - - btScalar length2() const - { - return dot(*this); - } - - btScalar length() const - { - return btSqrt(length2()); - } - - btQuaternion& normalize() - { - return *this /= length(); - } - - SIMD_FORCE_INLINE btQuaternion - operator*(const btScalar& s) const - { - return btQuaternion(x() * s, y() * s, z() * s, m_unusedW * s); - } - - - - btQuaternion operator/(const btScalar& s) const - { - assert(s != btScalar(0.0)); - return *this * (btScalar(1.0) / s); - } - - - btQuaternion& operator/=(const btScalar& s) - { - assert(s != btScalar(0.0)); - return *this *= btScalar(1.0) / s; - } - - - btQuaternion normalized() const - { - return *this / length(); - } - - btScalar angle(const btQuaternion& q) const - { - btScalar s = btSqrt(length2() * q.length2()); - assert(s != btScalar(0.0)); - return btAcos(dot(q) / s); - } - - btScalar getAngle() const - { - btScalar s = btScalar(2.) * btAcos(m_unusedW); - return s; - } - - - - btQuaternion inverse() const - { - return btQuaternion(m_x, m_y, m_z, -m_unusedW); - } - - SIMD_FORCE_INLINE btQuaternion - operator+(const btQuaternion& q2) const - { - const btQuaternion& q1 = *this; - return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_unusedW + q2.m_unusedW); - } - - SIMD_FORCE_INLINE btQuaternion - operator-(const btQuaternion& q2) const - { - const btQuaternion& q1 = *this; - return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_unusedW - q2.m_unusedW); - } - - SIMD_FORCE_INLINE btQuaternion operator-() const - { - const btQuaternion& q2 = *this; - return btQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_unusedW); - } - - SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const - { - btQuaternion diff,sum; - diff = *this - qd; - sum = *this + qd; - if( diff.dot(diff) > sum.dot(sum) ) - return qd; - return (-qd); - } - - btQuaternion slerp(const btQuaternion& q, const btScalar& t) const - { - btScalar theta = angle(q); - if (theta != btScalar(0.0)) - { - btScalar d = btScalar(1.0) / btSin(theta); - btScalar s0 = btSin((btScalar(1.0) - t) * theta); - btScalar s1 = btSin(t * theta); - return btQuaternion((m_x * s0 + q.x() * s1) * d, - (m_y * s0 + q.y() * s1) * d, - (m_z * s0 + q.z() * s1) * d, - (m_unusedW * s0 + q.m_unusedW * s1) * d); - } - else - { - return *this; - } - } - - SIMD_FORCE_INLINE const btScalar& getW() const { return m_unusedW; } - - -}; - - - -SIMD_FORCE_INLINE btQuaternion -operator-(const btQuaternion& q) -{ - return btQuaternion(-q.x(), -q.y(), -q.z(), -q.w()); -} - - - - -SIMD_FORCE_INLINE btQuaternion -operator*(const btQuaternion& q1, const btQuaternion& q2) { - return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(), - q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(), - q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(), - q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z()); -} - -SIMD_FORCE_INLINE btQuaternion -operator*(const btQuaternion& q, const btVector3& w) -{ - return btQuaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(), - q.w() * w.y() + q.z() * w.x() - q.x() * w.z(), - q.w() * w.z() + q.x() * w.y() - q.y() * w.x(), - -q.x() * w.x() - q.y() * w.y() - q.z() * w.z()); -} - -SIMD_FORCE_INLINE btQuaternion -operator*(const btVector3& w, const btQuaternion& q) -{ - return btQuaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(), - w.y() * q.w() + w.z() * q.x() - w.x() * q.z(), - w.z() * q.w() + w.x() * q.y() - w.y() * q.x(), - -w.x() * q.x() - w.y() * q.y() - w.z() * q.z()); -} - -SIMD_FORCE_INLINE btScalar -dot(const btQuaternion& q1, const btQuaternion& q2) -{ - return q1.dot(q2); -} - - -SIMD_FORCE_INLINE btScalar -length(const btQuaternion& q) -{ - return q.length(); -} - -SIMD_FORCE_INLINE btScalar -angle(const btQuaternion& q1, const btQuaternion& q2) -{ - return q1.angle(q2); -} - - -SIMD_FORCE_INLINE btQuaternion -inverse(const btQuaternion& q) -{ - return q.inverse(); -} - -SIMD_FORCE_INLINE btQuaternion -slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) -{ - return q1.slerp(q2, t); -} - -SIMD_FORCE_INLINE btVector3 -quatRotate(const btQuaternion& rotation, const btVector3& v) -{ - btQuaternion q = rotation * v; - q *= rotation.inverse(); - return btVector3(q.getX(),q.getY(),q.getZ()); -} - -SIMD_FORCE_INLINE btQuaternion -shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized -{ - btVector3 c = v0.cross(v1); - btScalar d = v0.dot(v1); - - if (d < -1.0 + SIMD_EPSILON) - return btQuaternion(0.0f,1.0f,0.0f,0.0f); // just pick any vector - - btScalar s = btSqrt((1.0f + d) * 2.0f); - btScalar rs = 1.0f / s; - - return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f); -} - -SIMD_FORCE_INLINE btQuaternion -shortestArcQuatNormalize2(btVector3& v0,btVector3& v1) -{ - v0.normalize(); - v1.normalize(); - return shortestArcQuat(v0,v1); -} - -#endif - - - diff --git a/extern/bullet2/src/LinearMath/btQuickprof.cpp b/extern/bullet2/src/LinearMath/btQuickprof.cpp deleted file mode 100644 index 37a0c8c3be5..00000000000 --- a/extern/bullet2/src/LinearMath/btQuickprof.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright (c) 2006 Tyler Streeter - -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. - -*/ - - -// Please visit the project website (http://quickprof.sourceforge.net) -// for usage instructions. - -// Credits: The Clock class was inspired by the Timer classes in -// Ogre (www.ogre3d.org). - -#include "LinearMath/btQuickprof.h" - -#ifdef USE_QUICKPROF - -// Note: We must declare these private static variables again here to -// avoid link errors. -bool btProfiler::mEnabled = false; -btClock btProfiler::mClock; -unsigned long int btProfiler::mCurrentCycleStartMicroseconds = 0; -unsigned long int btProfiler::mLastCycleDurationMicroseconds = 0; -std::map btProfiler::mProfileBlocks; -std::ofstream btProfiler::mOutputFile; -bool btProfiler::mFirstFileOutput = true; -btProfiler::BlockTimingMethod btProfiler::mFileOutputMethod; -unsigned long int btProfiler::mCycleNumber = 0; -#endif //USE_QUICKPROF diff --git a/extern/bullet2/src/LinearMath/btQuickprof.h b/extern/bullet2/src/LinearMath/btQuickprof.h deleted file mode 100644 index a885967c5fa..00000000000 --- a/extern/bullet2/src/LinearMath/btQuickprof.h +++ /dev/null @@ -1,712 +0,0 @@ -/* -Copyright (c) 2006 Tyler Streeter - -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. - -*/ - -// Please visit the project website (http://quickprof.sourceforge.net) -// for usage instructions. - -// Credits: The Clock class was inspired by the Timer classes in -// Ogre (www.ogre3d.org). - -#ifndef QUICK_PROF_H -#define QUICK_PROF_H - -#include "btScalar.h" - -//#define USE_QUICKPROF 1 -//Don't use quickprof for now, because it contains STL. TODO: replace STL by Bullet container classes. - - -//if you don't need btClock, you can comment next line -#define USE_BT_CLOCK 1 - -#ifdef USE_BT_CLOCK -#ifdef __CELLOS_LV2__ -#include -#include -typedef uint64_t __int64; -#endif - -#if defined (SUNOS) || defined (__SUNOS__) - #include -#endif - -#if defined(WIN32) || defined(_WIN32) - - #define USE_WINDOWS_TIMERS - #define WIN32_LEAN_AND_MEAN - #define NOWINRES - #define NOMCX - #define NOIME -#ifdef _XBOX - #include -#else - #include -#endif - #include - -#else - #include -#endif - -#define mymin(a,b) (a > b ? a : b) - -/// basic clock -class btClock - { - public: - btClock() - { -#ifdef USE_WINDOWS_TIMERS - QueryPerformanceFrequency(&mClockFrequency); -#endif - reset(); - } - - ~btClock() - { - } - - /// Resets the initial reference time. - void reset() - { -#ifdef USE_WINDOWS_TIMERS - QueryPerformanceCounter(&mStartTime); - mStartTick = GetTickCount(); - mPrevElapsedTime = 0; -#else -#ifdef __CELLOS_LV2__ - - typedef uint64_t __int64; - typedef __int64 ClockSize; - ClockSize newTime; - __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - mStartTime = newTime; -#else - gettimeofday(&mStartTime, 0); -#endif - -#endif - } - - /// Returns the time in ms since the last call to reset or since - /// the btClock was created. - unsigned long int getTimeMilliseconds() - { -#ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER currentTime; - QueryPerformanceCounter(¤tTime); - LONGLONG elapsedTime = currentTime.QuadPart - - mStartTime.QuadPart; - - // Compute the number of millisecond ticks elapsed. - unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / - mClockFrequency.QuadPart); - - // Check for unexpected leaps in the Win32 performance counter. - // (This is caused by unexpected data across the PCI to ISA - // bridge, aka south bridge. See Microsoft KB274323.) - unsigned long elapsedTicks = GetTickCount() - mStartTick; - signed long msecOff = (signed long)(msecTicks - elapsedTicks); - if (msecOff < -100 || msecOff > 100) - { - // Adjust the starting time forwards. - LONGLONG msecAdjustment = mymin(msecOff * - mClockFrequency.QuadPart / 1000, elapsedTime - - mPrevElapsedTime); - mStartTime.QuadPart += msecAdjustment; - elapsedTime -= msecAdjustment; - - // Recompute the number of millisecond ticks elapsed. - msecTicks = (unsigned long)(1000 * elapsedTime / - mClockFrequency.QuadPart); - } - - // Store the current elapsed time for adjustments next time. - mPrevElapsedTime = elapsedTime; - - return msecTicks; -#else - -#ifdef __CELLOS_LV2__ - __int64 freq=sys_time_get_timebase_frequency(); - double dFreq=((double) freq) / 1000.0; - typedef uint64_t __int64; - typedef __int64 ClockSize; - ClockSize newTime; - __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - - return (newTime-mStartTime) / dFreq; -#else - - struct timeval currentTime; - gettimeofday(¤tTime, 0); - return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 + - (currentTime.tv_usec - mStartTime.tv_usec) / 1000; -#endif //__CELLOS_LV2__ -#endif - } - - /// Returns the time in us since the last call to reset or since - /// the Clock was created. - unsigned long int getTimeMicroseconds() - { -#ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER currentTime; - QueryPerformanceCounter(¤tTime); - LONGLONG elapsedTime = currentTime.QuadPart - - mStartTime.QuadPart; - - // Compute the number of millisecond ticks elapsed. - unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / - mClockFrequency.QuadPart); - - // Check for unexpected leaps in the Win32 performance counter. - // (This is caused by unexpected data across the PCI to ISA - // bridge, aka south bridge. See Microsoft KB274323.) - unsigned long elapsedTicks = GetTickCount() - mStartTick; - signed long msecOff = (signed long)(msecTicks - elapsedTicks); - if (msecOff < -100 || msecOff > 100) - { - // Adjust the starting time forwards. - LONGLONG msecAdjustment = mymin(msecOff * - mClockFrequency.QuadPart / 1000, elapsedTime - - mPrevElapsedTime); - mStartTime.QuadPart += msecAdjustment; - elapsedTime -= msecAdjustment; - } - - // Store the current elapsed time for adjustments next time. - mPrevElapsedTime = elapsedTime; - - // Convert to microseconds. - unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / - mClockFrequency.QuadPart); - - return usecTicks; -#else - -#ifdef __CELLOS_LV2__ - __int64 freq=sys_time_get_timebase_frequency(); - double dFreq=((double) freq)/ 1000000.0; - typedef uint64_t __int64; - typedef __int64 ClockSize; - ClockSize newTime; - __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - - return (newTime-mStartTime) / dFreq; -#else - - struct timeval currentTime; - gettimeofday(¤tTime, 0); - return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 + - (currentTime.tv_usec - mStartTime.tv_usec); -#endif//__CELLOS_LV2__ -#endif - } - - private: -#ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER mClockFrequency; - DWORD mStartTick; - LONGLONG mPrevElapsedTime; - LARGE_INTEGER mStartTime; -#else -#ifdef __CELLOS_LV2__ - uint64_t mStartTime; -#else - struct timeval mStartTime; -#endif -#endif //__CELLOS_LV2__ - - }; - -#endif //USE_BT_CLOCK - - -#ifdef USE_QUICKPROF - - -#include -#include -#include -#include - - - - -namespace hidden -{ - /// A simple data structure representing a single timed block - /// of code. - struct ProfileBlock - { - ProfileBlock() - { - currentBlockStartMicroseconds = 0; - currentCycleTotalMicroseconds = 0; - lastCycleTotalMicroseconds = 0; - totalMicroseconds = 0; - } - - /// The starting time (in us) of the current block update. - unsigned long int currentBlockStartMicroseconds; - - /// The accumulated time (in us) spent in this block during the - /// current profiling cycle. - unsigned long int currentCycleTotalMicroseconds; - - /// The accumulated time (in us) spent in this block during the - /// past profiling cycle. - unsigned long int lastCycleTotalMicroseconds; - - /// The total accumulated time (in us) spent in this block. - unsigned long int totalMicroseconds; - }; - -}; - -/// A static class that manages timing for a set of profiling blocks. -class btProfiler -{ -public: - /// A set of ways to retrieve block timing data. - enum BlockTimingMethod - { - /// The total time spent in the block (in seconds) since the - /// profiler was initialized. - BLOCK_TOTAL_SECONDS, - - /// The total time spent in the block (in ms) since the - /// profiler was initialized. - BLOCK_TOTAL_MILLISECONDS, - - /// The total time spent in the block (in us) since the - /// profiler was initialized. - BLOCK_TOTAL_MICROSECONDS, - - /// The total time spent in the block, as a % of the total - /// elapsed time since the profiler was initialized. - BLOCK_TOTAL_PERCENT, - - /// The time spent in the block (in seconds) in the most recent - /// profiling cycle. - BLOCK_CYCLE_SECONDS, - - /// The time spent in the block (in ms) in the most recent - /// profiling cycle. - BLOCK_CYCLE_MILLISECONDS, - - /// The time spent in the block (in us) in the most recent - /// profiling cycle. - BLOCK_CYCLE_MICROSECONDS, - - /// The time spent in the block (in seconds) in the most recent - /// profiling cycle, as a % of the total cycle time. - BLOCK_CYCLE_PERCENT - }; - - /// Initializes the profiler. This must be called first. If this is - /// never called, the profiler is effectively disabled; all other - /// functions will return immediately. The first parameter - /// is the name of an output data file; if this string is not empty, - /// data will be saved on every profiling cycle; if this string is - /// empty, no data will be saved to a file. The second parameter - /// determines which timing method is used when printing data to the - /// output file. - inline static void init(const std::string outputFilename="", - BlockTimingMethod outputMethod=BLOCK_CYCLE_MILLISECONDS); - - /// Cleans up allocated memory. - inline static void destroy(); - - /// Begins timing the named block of code. - inline static void beginBlock(const std::string& name); - - /// Updates the accumulated time spent in the named block by adding - /// the elapsed time since the last call to startBlock for this block - /// name. - inline static void endBlock(const std::string& name); - - /// Returns the time spent in the named block according to the - /// given timing method. See comments on BlockTimingMethod for details. - inline static double getBlockTime(const std::string& name, - BlockTimingMethod method=BLOCK_CYCLE_MILLISECONDS); - - /// Defines the end of a profiling cycle. Use this regularly if you - /// want to generate detailed timing information. This must not be - /// called within a timing block. - inline static void endProfilingCycle(); - - /// A helper function that creates a string of statistics for - /// each timing block. This is mainly for printing an overall - /// summary to the command line. - inline static std::string createStatsString( - BlockTimingMethod method=BLOCK_TOTAL_PERCENT); - -//private: - inline btProfiler(); - - inline ~btProfiler(); - - /// Prints an error message to standard output. - inline static void printError(const std::string& msg) - { - //btAssert(0); - std::cout << "[QuickProf error] " << msg << std::endl; - } - - /// Determines whether the profiler is enabled. - static bool mEnabled; - - /// The clock used to time profile blocks. - static btClock mClock; - - /// The starting time (in us) of the current profiling cycle. - static unsigned long int mCurrentCycleStartMicroseconds; - - /// The duration (in us) of the most recent profiling cycle. - static unsigned long int mLastCycleDurationMicroseconds; - - /// Internal map of named profile blocks. - static std::map mProfileBlocks; - - /// The data file used if this feature is enabled in 'init.' - static std::ofstream mOutputFile; - - /// Tracks whether we have begun print data to the output file. - static bool mFirstFileOutput; - - /// The method used when printing timing data to an output file. - static BlockTimingMethod mFileOutputMethod; - - /// The number of the current profiling cycle. - static unsigned long int mCycleNumber; -}; - - -btProfiler::btProfiler() -{ - // This never gets called because a btProfiler instance is never - // created. -} - -btProfiler::~btProfiler() -{ - // This never gets called because a btProfiler instance is never - // created. -} - -void btProfiler::init(const std::string outputFilename, - BlockTimingMethod outputMethod) -{ - mEnabled = true; - - if (!outputFilename.empty()) - { - mOutputFile.open(outputFilename.c_str()); - } - - mFileOutputMethod = outputMethod; - - mClock.reset(); - - // Set the start time for the first cycle. - mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); -} - -void btProfiler::destroy() -{ - if (!mEnabled) - { - return; - } - - if (mOutputFile.is_open()) - { - mOutputFile.close(); - } - - // Destroy all ProfileBlocks. - while (!mProfileBlocks.empty()) - { - delete (*mProfileBlocks.begin()).second; - mProfileBlocks.erase(mProfileBlocks.begin()); - } -} - -void btProfiler::beginBlock(const std::string& name) -{ - if (!mEnabled) - { - return; - } - - if (name.empty()) - { - printError("Cannot allow unnamed profile blocks."); - return; - } - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // Create a new ProfileBlock. - mProfileBlocks[name] = new hidden::ProfileBlock(); - block = mProfileBlocks[name]; - } - - // We do this at the end to get more accurate results. - block->currentBlockStartMicroseconds = mClock.getTimeMicroseconds(); -} - -void btProfiler::endBlock(const std::string& name) -{ - if (!mEnabled) - { - return; - } - - // We do this at the beginning to get more accurate results. - unsigned long int endTick = mClock.getTimeMicroseconds(); - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // The named block does not exist. Print an error. - printError("The profile block named '" + name + - "' does not exist."); - return; - } - - unsigned long int blockDuration = endTick - - block->currentBlockStartMicroseconds; - block->currentCycleTotalMicroseconds += blockDuration; - block->totalMicroseconds += blockDuration; -} - -double btProfiler::getBlockTime(const std::string& name, - BlockTimingMethod method) -{ - if (!mEnabled) - { - return 0; - } - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // The named block does not exist. Print an error. - printError("The profile block named '" + name + - "' does not exist."); - return 0; - } - - double result = 0; - - switch(method) - { - case BLOCK_TOTAL_SECONDS: - result = (double)block->totalMicroseconds * (double)0.000001; - break; - case BLOCK_TOTAL_MILLISECONDS: - result = (double)block->totalMicroseconds * (double)0.001; - break; - case BLOCK_TOTAL_MICROSECONDS: - result = (double)block->totalMicroseconds; - break; - case BLOCK_TOTAL_PERCENT: - { - double timeSinceInit = (double)mClock.getTimeMicroseconds(); - if (timeSinceInit <= 0) - { - result = 0; - } - else - { - result = 100.0 * (double)block->totalMicroseconds / - timeSinceInit; - } - break; - } - case BLOCK_CYCLE_SECONDS: - result = (double)block->lastCycleTotalMicroseconds * - (double)0.000001; - break; - case BLOCK_CYCLE_MILLISECONDS: - result = (double)block->lastCycleTotalMicroseconds * - (double)0.001; - break; - case BLOCK_CYCLE_MICROSECONDS: - result = (double)block->lastCycleTotalMicroseconds; - break; - case BLOCK_CYCLE_PERCENT: - { - if (0 == mLastCycleDurationMicroseconds) - { - // We have not yet finished a cycle, so just return zero - // percent to avoid a divide by zero error. - result = 0; - } - else - { - result = 100.0 * (double)block->lastCycleTotalMicroseconds / - mLastCycleDurationMicroseconds; - } - break; - } - default: - break; - } - - return result; -} - -void btProfiler::endProfilingCycle() -{ - if (!mEnabled) - { - return; - } - - // Store the duration of the cycle that just finished. - mLastCycleDurationMicroseconds = mClock.getTimeMicroseconds() - - mCurrentCycleStartMicroseconds; - - // For each block, update data for the cycle that just finished. - std::map::iterator iter; - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) - { - hidden::ProfileBlock* block = (*iter).second; - block->lastCycleTotalMicroseconds = - block->currentCycleTotalMicroseconds; - block->currentCycleTotalMicroseconds = 0; - } - - if (mOutputFile.is_open()) - { - // Print data to the output file. - if (mFirstFileOutput) - { - // On the first iteration, print a header line that shows the - // names of each profiling block. - mOutputFile << "#cycle, "; - - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); - ++iter) - { - mOutputFile << (*iter).first << ", "; - } - - mOutputFile << std::endl; - mFirstFileOutput = false; - } - - mOutputFile << mCycleNumber << ", "; - - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); - ++iter) - { - mOutputFile << getBlockTime((*iter).first, mFileOutputMethod) - << ", "; - } - - mOutputFile << std::endl; - } - - ++mCycleNumber; - mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); -} - -std::string btProfiler::createStatsString(BlockTimingMethod method) -{ - if (!mEnabled) - { - return ""; - } - - std::string s; - std::string suffix; - - switch(method) - { - case BLOCK_TOTAL_SECONDS: - suffix = "s"; - break; - case BLOCK_TOTAL_MILLISECONDS: - suffix = "ms"; - break; - case BLOCK_TOTAL_MICROSECONDS: - suffix = "us"; - break; - case BLOCK_TOTAL_PERCENT: - { - suffix = "%"; - break; - } - case BLOCK_CYCLE_SECONDS: - suffix = "s"; - break; - case BLOCK_CYCLE_MILLISECONDS: - suffix = "ms"; - break; - case BLOCK_CYCLE_MICROSECONDS: - suffix = "us"; - break; - case BLOCK_CYCLE_PERCENT: - { - suffix = "%"; - break; - } - default: - break; - } - - std::map::iterator iter; - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) - { - if (iter != mProfileBlocks.begin()) - { - s += "\n"; - } - - char blockTime[64]; - sprintf(blockTime, "%lf", getBlockTime((*iter).first, method)); - - s += (*iter).first; - s += ": "; - s += blockTime; - s += " "; - s += suffix; - } - - return s; -} - - -#define BEGIN_PROFILE(a) btProfiler::beginBlock(a) -#define END_PROFILE(a) btProfiler::endBlock(a) - -#else //USE_QUICKPROF -#define BEGIN_PROFILE(a) -#define END_PROFILE(a) - -#endif //USE_QUICKPROF - -#endif //QUICK_PROF_H - - diff --git a/extern/bullet2/src/LinearMath/btRandom.h b/extern/bullet2/src/LinearMath/btRandom.h deleted file mode 100644 index fdf65e01caf..00000000000 --- a/extern/bullet2/src/LinearMath/btRandom.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - - -#ifndef GEN_RANDOM_H -#define GEN_RANDOM_H - -#ifdef MT19937 - -#include -#include - -#define GEN_RAND_MAX UINT_MAX - -SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); } -SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); } - -#else - -#include - -#define GEN_RAND_MAX RAND_MAX - -SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); } -SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); } - -#endif - -#endif - diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h deleted file mode 100644 index 85dfaf3eb83..00000000000 --- a/extern/bullet2/src/LinearMath/btScalar.h +++ /dev/null @@ -1,394 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - - -#ifndef SIMD___SCALAR_H -#define SIMD___SCALAR_H - -#include - -#include -#include -#include - - -inline int btGetVersion() -{ - return 264; -} - -#ifdef WIN32 - - #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) - - #define SIMD_FORCE_INLINE inline - #define ATTRIBUTE_ALIGNED16(a) a - #define ATTRIBUTE_ALIGNED128(a) a - #else - #define BT_HAS_ALIGNED_ALLOCATOR - #pragma warning(disable:4530) - #pragma warning(disable:4996) - #pragma warning(disable:4786) - #define SIMD_FORCE_INLINE __forceinline - #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a - #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a - #ifdef _XBOX - #define BT_USE_VMX128 - - #include - #define BT_HAVE_NATIVE_FSEL - #define btFsel(a,b,c) __fsel((a),(b),(c)) - #else - #define BT_USE_SSE - #endif - #endif //__MINGW32__ - - #include - #define btAssert assert - //btFullAssert is optional, slows down a lot - #define btFullAssert(x) - - #define btLikely(_c) _c - #define btUnlikely(_c) _c - -#else - -#if defined (__CELLOS_LV2__) - #define SIMD_FORCE_INLINE inline - #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) - #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) - #ifndef assert - #include - #endif - #define btAssert assert - //btFullAssert is optional, slows down a lot - #define btFullAssert(x) - - #define btLikely(_c) _c - #define btUnlikely(_c) _c - -#else - -#ifdef USE_LIBSPE2 - - #define SIMD_FORCE_INLINE __inline - #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) - #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) - #ifndef assert - #include - #endif - #define btAssert assert - //btFullAssert is optional, slows down a lot - #define btFullAssert(x) - - - #define btLikely(_c) __builtin_expect((_c), 1) - #define btUnlikely(_c) __builtin_expect((_c), 0) - - -#else - //non-windows systems - - #define SIMD_FORCE_INLINE inline - #define ATTRIBUTE_ALIGNED16(a) a - #define ATTRIBUTE_ALIGNED128(a) a - #ifndef assert - #include - #endif - #define btAssert assert - //btFullAssert is optional, slows down a lot - #define btFullAssert(x) - - -#endif // LIBSPE2 - -#endif //__CELLOS_LV2__ -#endif - -/// older compilers (gcc 3.x) and Sun needs double version of sqrt etc. -/// exclude Apple Intel (i's assumed to be a Macbook or new Intel Dual Core Processor) -#if defined (__sun) || defined (__sun__) || defined (__sparc) || (defined (__APPLE__) && ! defined (__i386__)) -//use slow double float precision operation on those platforms -#ifndef BT_USE_DOUBLE_PRECISION -#define BT_FORCE_DOUBLE_FUNCTIONS -#endif -#endif - -#if defined(BT_USE_DOUBLE_PRECISION) -typedef double btScalar; -#else -typedef float btScalar; -#endif - - -#define BT_DECLARE_ALIGNED_ALLOCATOR() \ - SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ - SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ - SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ - SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ - - - -#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS) - -SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); } -SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); } -SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); } -SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); } -SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); } -SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acos(x); } -SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asin(x); } -SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); } -SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); } -SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); } -SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); } -SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } - -#else - -SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) -{ -#ifdef USE_APPROXIMATION - double x, z, tempf; - unsigned long *tfptr = ((unsigned long *)&tempf) + 1; - - tempf = y; - *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ - x = tempf; - z = y*btScalar(0.5); /* hoist out the “/2” */ - x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */ - x = (btScalar(1.5)*x)-(x*x)*(x*z); - x = (btScalar(1.5)*x)-(x*x)*(x*z); - x = (btScalar(1.5)*x)-(x*x)*(x*z); - x = (btScalar(1.5)*x)-(x*x)*(x*z); - return x*y; -#else - return sqrtf(y); -#endif -} -SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); } -SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } -SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } -SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } -SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { - btAssert(x <= btScalar(1.)); - return acosf(x); -} -SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); } -SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } -SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } -SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); } -SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); } -SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); } - -#endif - -#define SIMD_2_PI btScalar(6.283185307179586232) -#define SIMD_PI (SIMD_2_PI * btScalar(0.5)) -#define SIMD_HALF_PI (SIMD_2_PI * btScalar(0.25)) -#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0)) -#define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI) - -#ifdef BT_USE_DOUBLE_PRECISION -#define SIMD_EPSILON DBL_EPSILON -#define SIMD_INFINITY DBL_MAX -#else -#define SIMD_EPSILON FLT_EPSILON -#define SIMD_INFINITY FLT_MAX -#endif - -SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x) -{ - btScalar coeff_1 = SIMD_PI / 4.0f; - btScalar coeff_2 = 3.0f * coeff_1; - btScalar abs_y = btFabs(y); - btScalar angle; - if (x >= 0.0f) { - btScalar r = (x - abs_y) / (x + abs_y); - angle = coeff_1 - coeff_1 * r; - } else { - btScalar r = (x + abs_y) / (abs_y - x); - angle = coeff_2 - coeff_1 * r; - } - return (y < 0.0f) ? -angle : angle; -} - -SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; } - -SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps) { - return (((a) <= eps) && !((a) < -eps)); -} -SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) { - return (!((a) <= eps)); -} - - -SIMD_FORCE_INLINE int btIsNegative(btScalar x) { - return x < btScalar(0.0) ? 1 : 0; -} - -SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; } -SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; } - -#define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name - -#ifndef btFsel -SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c) -{ - return a >= 0 ? b : c; -} -#endif -#define btFsels(a,b,c) (btScalar)btFsel(a,b,c) - - -SIMD_FORCE_INLINE bool btMachineIsLittleEndian() -{ - long int i = 1; - const char *p = (const char *) &i; - if (p[0] == 1) // Lowest address contains the least significant byte - return true; - else - return false; -} - - - -///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360 -///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html -SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) -{ - // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero - // Rely on positive value or'ed with its negative having sign bit on - // and zero value or'ed with its negative (which is still zero) having sign bit off - // Use arithmetic shift right, shifting the sign bit through all 32 bits - unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); - unsigned testEqz = ~testNz; - return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); -} -SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero) -{ - unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); - unsigned testEqz = ~testNz; - return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); -} -SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero) -{ -#ifdef BT_HAVE_NATIVE_FSEL - return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero); -#else - return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; -#endif -} - -template SIMD_FORCE_INLINE void btSwap(T& a, T& b) -{ - T tmp = a; - a = b; - b = tmp; -} - - -//PCK: endian swapping functions -SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val) -{ - return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); -} - -SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val) -{ - return (((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)); -} - -SIMD_FORCE_INLINE unsigned btSwapEndian(int val) -{ - return btSwapEndian((unsigned)val); -} - -SIMD_FORCE_INLINE unsigned short btSwapEndian(short val) -{ - return btSwapEndian((unsigned short) val); -} - -///btSwapFloat uses using char pointers to swap the endianness -////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values -///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754. -///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception. -///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you. -///so instead of returning a float/double, we return integer/long long integer -SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d) -{ - unsigned int a; - unsigned char *dst = (unsigned char *)&a; - unsigned char *src = (unsigned char *)&d; - - dst[0] = src[3]; - dst[1] = src[2]; - dst[2] = src[1]; - dst[3] = src[0]; - return a; -} - -// unswap using char pointers -SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) -{ - float d; - unsigned char *src = (unsigned char *)&a; - unsigned char *dst = (unsigned char *)&d; - - dst[0] = src[3]; - dst[1] = src[2]; - dst[2] = src[1]; - dst[3] = src[0]; - - return d; -} - - -// swap using char pointers -SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst) -{ - unsigned char *src = (unsigned char *)&d; - - dst[0] = src[7]; - dst[1] = src[6]; - dst[2] = src[5]; - dst[3] = src[4]; - dst[4] = src[3]; - dst[5] = src[2]; - dst[6] = src[1]; - dst[7] = src[0]; - -} - -// unswap using char pointers -SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) -{ - double d; - unsigned char *dst = (unsigned char *)&d; - - dst[0] = src[7]; - dst[1] = src[6]; - dst[2] = src[5]; - dst[3] = src[4]; - dst[4] = src[3]; - dst[5] = src[2]; - dst[6] = src[1]; - dst[7] = src[0]; - - return d; -} - - -#endif //SIMD___SCALAR_H diff --git a/extern/bullet2/src/LinearMath/btSimdMinMax.h b/extern/bullet2/src/LinearMath/btSimdMinMax.h deleted file mode 100644 index 75e83f3c53f..00000000000 --- a/extern/bullet2/src/LinearMath/btSimdMinMax.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - - -#ifndef SIMD_MINMAX_H -#define SIMD_MINMAX_H -#include "btScalar.h" - -template -SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) { - return b < a ? b : a; -} - -template -SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) { - return a < b ? b : a; -} - -template -SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) { - if (a > b) a = b; -} - -template -SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) { - if (a < b) a = b; -} - -#endif diff --git a/extern/bullet2/src/LinearMath/btStackAlloc.h b/extern/bullet2/src/LinearMath/btStackAlloc.h deleted file mode 100644 index ac940cd2edd..00000000000 --- a/extern/bullet2/src/LinearMath/btStackAlloc.h +++ /dev/null @@ -1,115 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - -/* -StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson -Nov.2006 -*/ - -#ifndef BT_STACK_ALLOC -#define BT_STACK_ALLOC - -#include "btScalar.h" //for btAssert -#include "btAlignedAllocator.h" - -struct btBlock -{ - btBlock* previous; - unsigned char* address; -}; - -///StackAlloc provides some fast stack-based memory allocator (LIFO last-in first-out) -class btStackAlloc -{ -public: - - btStackAlloc(unsigned int size) { ctor();create(size); } - ~btStackAlloc() { destroy(); } - - inline void create(unsigned int size) - { - destroy(); - data = (unsigned char*) btAlignedAlloc(size,16); - totalsize = size; - } - inline void destroy() - { - btAssert(usedsize==0); - //Raise(L"StackAlloc is still in use"); - - if(usedsize==0) - { - if(!ischild && data) - btAlignedFree(data); - - data = 0; - usedsize = 0; - } - - } - - int getAvailableMemory() const - { - return totalsize - usedsize; - } - - unsigned char* allocate(unsigned int size) - { - const unsigned int nus(usedsize+size); - if(nusprevious = current; - pb->address = data+usedsize; - current = pb; - return(pb); - } - SIMD_FORCE_INLINE void endBlock(btBlock* block) - { - btAssert(block==current); - //Raise(L"Unmatched blocks"); - if(block==current) - { - current = block->previous; - usedsize = (unsigned int)((block->address-data)-sizeof(btBlock)); - } - } - -private: - void ctor() - { - data = 0; - totalsize = 0; - usedsize = 0; - current = 0; - ischild = false; - } - unsigned char* data; - unsigned int totalsize; - unsigned int usedsize; - btBlock* current; - bool ischild; -}; - -#endif //BT_STACK_ALLOC diff --git a/extern/bullet2/src/LinearMath/btTransform.h b/extern/bullet2/src/LinearMath/btTransform.h deleted file mode 100644 index 883b3a5d2b7..00000000000 --- a/extern/bullet2/src/LinearMath/btTransform.h +++ /dev/null @@ -1,200 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - - -#ifndef btTransform_H -#define btTransform_H - -#include "btVector3.h" -#include "btMatrix3x3.h" - - -///btTransform supports rigid transforms (only translation and rotation, no scaling/shear) -class btTransform { - - -public: - - - btTransform() {} - - explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q, - const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) - : m_basis(q), - m_origin(c) - {} - - explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b, - const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) - : m_basis(b), - m_origin(c) - {} - - SIMD_FORCE_INLINE btTransform (const btTransform& other) - : m_basis(other.m_basis), - m_origin(other.m_origin) - { - } - - SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other) - { - m_basis = other.m_basis; - m_origin = other.m_origin; - return *this; - } - - - SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2) { - m_basis = t1.m_basis * t2.m_basis; - m_origin = t1(t2.m_origin); - } - -/* void multInverseLeft(const btTransform& t1, const btTransform& t2) { - btVector3 v = t2.m_origin - t1.m_origin; - m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis); - m_origin = v * t1.m_basis; - } - */ - - - SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const - { - return btVector3(m_basis[0].dot(x) + m_origin.x(), - m_basis[1].dot(x) + m_origin.y(), - m_basis[2].dot(x) + m_origin.z()); - } - - SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const - { - return (*this)(x); - } - - SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; } - SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; } - - SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; } - SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; } - - btQuaternion getRotation() const { - btQuaternion q; - m_basis.getRotation(q); - return q; - } - - - void setFromOpenGLMatrix(const btScalar *m) - { - m_basis.setFromOpenGLSubMatrix(m); - m_origin.setValue(m[12],m[13],m[14]); - } - - void getOpenGLMatrix(btScalar *m) const - { - m_basis.getOpenGLSubMatrix(m); - m[12] = m_origin.x(); - m[13] = m_origin.y(); - m[14] = m_origin.z(); - m[15] = btScalar(1.0); - } - - SIMD_FORCE_INLINE void setOrigin(const btVector3& origin) - { - m_origin = origin; - } - - SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const; - - - - SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis) - { - m_basis = basis; - } - - SIMD_FORCE_INLINE void setRotation(const btQuaternion& q) - { - m_basis.setRotation(q); - } - - - - void setIdentity() - { - m_basis.setIdentity(); - m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); - } - - - btTransform& operator*=(const btTransform& t) - { - m_origin += m_basis * t.m_origin; - m_basis *= t.m_basis; - return *this; - } - - btTransform inverse() const - { - btMatrix3x3 inv = m_basis.transpose(); - return btTransform(inv, inv * -m_origin); - } - - btTransform inverseTimes(const btTransform& t) const; - - btTransform operator*(const btTransform& t) const; - - static btTransform getIdentity() - { - btTransform tr; - tr.setIdentity(); - return tr; - } - -private: - - btMatrix3x3 m_basis; - btVector3 m_origin; -}; - - -SIMD_FORCE_INLINE btVector3 -btTransform::invXform(const btVector3& inVec) const -{ - btVector3 v = inVec - m_origin; - return (m_basis.transpose() * v); -} - -SIMD_FORCE_INLINE btTransform -btTransform::inverseTimes(const btTransform& t) const -{ - btVector3 v = t.getOrigin() - m_origin; - return btTransform(m_basis.transposeTimes(t.m_basis), - v * m_basis); -} - -SIMD_FORCE_INLINE btTransform -btTransform::operator*(const btTransform& t) const -{ - return btTransform(m_basis * t.m_basis, - (*this)(t.m_origin)); -} - - - -#endif - - - - - diff --git a/extern/bullet2/src/LinearMath/btTransformUtil.h b/extern/bullet2/src/LinearMath/btTransformUtil.h deleted file mode 100644 index d39e2e10074..00000000000 --- a/extern/bullet2/src/LinearMath/btTransformUtil.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - -#ifndef SIMD_TRANSFORM_UTIL_H -#define SIMD_TRANSFORM_UTIL_H - -#include "btTransform.h" -#define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI - - - -#define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490) - -#define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */ - -SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) -{ - return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), - supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), - supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); -} - - -SIMD_FORCE_INLINE void btPlaneSpace1 (const btVector3& n, btVector3& p, btVector3& q) -{ - if (btFabs(n.z()) > SIMDSQRT12) { - // choose p in y-z plane - btScalar a = n[1]*n[1] + n[2]*n[2]; - btScalar k = btRecipSqrt (a); - p.setValue(0,-n[2]*k,n[1]*k); - // set q = n x p - q.setValue(a*k,-n[0]*p[2],n[0]*p[1]); - } - else { - // choose p in x-y plane - btScalar a = n.x()*n.x() + n.y()*n.y(); - btScalar k = btRecipSqrt (a); - p.setValue(-n.y()*k,n.x()*k,0); - // set q = n x p - q.setValue(-n.z()*p.y(),n.z()*p.x(),a*k); - } -} - - - -/// Utils related to temporal transforms -class btTransformUtil -{ - -public: - - static void integrateTransform(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep,btTransform& predictedTransform) - { - predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep); -// #define QUATERNION_DERIVATIVE - #ifdef QUATERNION_DERIVATIVE - btQuaternion predictedOrn = curTrans.getRotation(); - predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5)); - predictedOrn.normalize(); - #else - //exponential map - btVector3 axis; - btScalar fAngle = angvel.length(); - //limit the angular motion - if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD) - { - fAngle = ANGULAR_MOTION_THRESHOLD / timeStep; - } - - if ( fAngle < btScalar(0.001) ) - { - // use Taylor's expansions of sync function - axis = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle ); - } - else - { - // sync(fAngle) = sin(c*fAngle)/t - axis = angvel*( btSin(btScalar(0.5)*fAngle*timeStep)/fAngle ); - } - btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*timeStep*btScalar(0.5) )); - btQuaternion orn0 = curTrans.getRotation(); - - btQuaternion predictedOrn = dorn * orn0; - predictedOrn.normalize(); - #endif - predictedTransform.setRotation(predictedOrn); - } - - static void calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel) - { - linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep; - btVector3 axis; - btScalar angle; - calculateDiffAxisAngle(transform0,transform1,axis,angle); - angVel = axis * angle / timeStep; - } - - static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle) - { - - #ifdef USE_QUATERNION_DIFF - btQuaternion orn0 = transform0.getRotation(); - btQuaternion orn1a = transform1.getRotation(); - btQuaternion orn1 = orn0.farthest(orn1a); - btQuaternion dorn = orn1 * orn0.inverse(); -#else - btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse(); - btQuaternion dorn; - dmat.getRotation(dorn); -#endif//USE_QUATERNION_DIFF - - ///floating point inaccuracy can lead to w component > 1..., which breaks - - dorn.normalize(); - - angle = dorn.getAngle(); - axis = btVector3(dorn.x(),dorn.y(),dorn.z()); - axis[3] = btScalar(0.); - //check for axis length - btScalar len = axis.length2(); - if (len < SIMD_EPSILON*SIMD_EPSILON) - axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.)); - else - axis /= btSqrt(len); - } - -}; - -#endif //SIMD_TRANSFORM_UTIL_H - diff --git a/extern/bullet2/src/LinearMath/btVector3.h b/extern/bullet2/src/LinearMath/btVector3.h deleted file mode 100644 index 1e331272dd8..00000000000 --- a/extern/bullet2/src/LinearMath/btVector3.h +++ /dev/null @@ -1,452 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / 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. -*/ - - - -#ifndef SIMD__VECTOR3_H -#define SIMD__VECTOR3_H - -#include "btQuadWord.h" - -///btVector3 can be used to represent 3D points and vectors. -///It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user -///Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers -class btVector3 : public btQuadWord { - -public: - SIMD_FORCE_INLINE btVector3() {} - - SIMD_FORCE_INLINE btVector3(const btQuadWordStorage& q) - : btQuadWord(q) - { - } - - - SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z) - :btQuadWord(x,y,z,btScalar(0.)) - { - } - -// SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) -// : btQuadWord(x,y,z,w) -// { -// } - - - - SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v) - { - m_x += v.x(); m_y += v.y(); m_z += v.z(); - return *this; - } - - - - SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v) - { - m_x -= v.x(); m_y -= v.y(); m_z -= v.z(); - return *this; - } - - SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s) - { - m_x *= s; m_y *= s; m_z *= s; - return *this; - } - - SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s) - { - btFullAssert(s != btScalar(0.0)); - return *this *= btScalar(1.0) / s; - } - - SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const - { - return m_x * v.x() + m_y * v.y() + m_z * v.z(); - } - - SIMD_FORCE_INLINE btScalar length2() const - { - return dot(*this); - } - - SIMD_FORCE_INLINE btScalar length() const - { - return btSqrt(length2()); - } - - SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const; - - SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const; - - SIMD_FORCE_INLINE btVector3& normalize() - { - return *this /= length(); - } - - SIMD_FORCE_INLINE btVector3 normalized() const; - - SIMD_FORCE_INLINE btVector3 rotate( const btVector3& wAxis, const btScalar angle ); - - SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const - { - btScalar s = btSqrt(length2() * v.length2()); - btFullAssert(s != btScalar(0.0)); - return btAcos(dot(v) / s); - } - - SIMD_FORCE_INLINE btVector3 absolute() const - { - return btVector3( - btFabs(m_x), - btFabs(m_y), - btFabs(m_z)); - } - - SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const - { - return btVector3( - m_y * v.z() - m_z * v.y(), - m_z * v.x() - m_x * v.z(), - m_x * v.y() - m_y * v.x()); - } - - SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const - { - return m_x * (v1.y() * v2.z() - v1.z() * v2.y()) + - m_y * (v1.z() * v2.x() - v1.x() * v2.z()) + - m_z * (v1.x() * v2.y() - v1.y() * v2.x()); - } - - SIMD_FORCE_INLINE int minAxis() const - { - return m_x < m_y ? (m_x < m_z ? 0 : 2) : (m_y < m_z ? 1 : 2); - } - - SIMD_FORCE_INLINE int maxAxis() const - { - return m_x < m_y ? (m_y < m_z ? 2 : 1) : (m_x < m_z ? 2 : 0); - } - - SIMD_FORCE_INLINE int furthestAxis() const - { - return absolute().minAxis(); - } - - SIMD_FORCE_INLINE int closestAxis() const - { - return absolute().maxAxis(); - } - - SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt) - { - btScalar s = btScalar(1.0) - rt; - m_x = s * v0.x() + rt * v1.x(); - m_y = s * v0.y() + rt * v1.y(); - m_z = s * v0.z() + rt * v1.z(); - //don't do the unused w component - // m_co[3] = s * v0[3] + rt * v1[3]; - } - - SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const - { - return btVector3(m_x + (v.x() - m_x) * t, - m_y + (v.y() - m_y) * t, - m_z + (v.z() - m_z) * t); - } - - - SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v) - { - m_x *= v.x(); m_y *= v.y(); m_z *= v.z(); - return *this; - } - - - -}; - -SIMD_FORCE_INLINE btVector3 -operator+(const btVector3& v1, const btVector3& v2) -{ - return btVector3(v1.x() + v2.x(), v1.y() + v2.y(), v1.z() + v2.z()); -} - -SIMD_FORCE_INLINE btVector3 -operator*(const btVector3& v1, const btVector3& v2) -{ - return btVector3(v1.x() * v2.x(), v1.y() * v2.y(), v1.z() * v2.z()); -} - -SIMD_FORCE_INLINE btVector3 -operator-(const btVector3& v1, const btVector3& v2) -{ - return btVector3(v1.x() - v2.x(), v1.y() - v2.y(), v1.z() - v2.z()); -} - -SIMD_FORCE_INLINE btVector3 -operator-(const btVector3& v) -{ - return btVector3(-v.x(), -v.y(), -v.z()); -} - -SIMD_FORCE_INLINE btVector3 -operator*(const btVector3& v, const btScalar& s) -{ - return btVector3(v.x() * s, v.y() * s, v.z() * s); -} - -SIMD_FORCE_INLINE btVector3 -operator*(const btScalar& s, const btVector3& v) -{ - return v * s; -} - -SIMD_FORCE_INLINE btVector3 -operator/(const btVector3& v, const btScalar& s) -{ - btFullAssert(s != btScalar(0.0)); - return v * (btScalar(1.0) / s); -} - -SIMD_FORCE_INLINE btVector3 -operator/(const btVector3& v1, const btVector3& v2) -{ - return btVector3(v1.x() / v2.x(),v1.y() / v2.y(),v1.z() / v2.z()); -} - -SIMD_FORCE_INLINE btScalar -dot(const btVector3& v1, const btVector3& v2) -{ - return v1.dot(v2); -} - - - -SIMD_FORCE_INLINE btScalar -distance2(const btVector3& v1, const btVector3& v2) -{ - return v1.distance2(v2); -} - - -SIMD_FORCE_INLINE btScalar -distance(const btVector3& v1, const btVector3& v2) -{ - return v1.distance(v2); -} - -SIMD_FORCE_INLINE btScalar -angle(const btVector3& v1, const btVector3& v2) -{ - return v1.angle(v2); -} - -SIMD_FORCE_INLINE btVector3 -cross(const btVector3& v1, const btVector3& v2) -{ - return v1.cross(v2); -} - -SIMD_FORCE_INLINE btScalar -triple(const btVector3& v1, const btVector3& v2, const btVector3& v3) -{ - return v1.triple(v2, v3); -} - -SIMD_FORCE_INLINE btVector3 -lerp(const btVector3& v1, const btVector3& v2, const btScalar& t) -{ - return v1.lerp(v2, t); -} - - -SIMD_FORCE_INLINE bool operator==(const btVector3& p1, const btVector3& p2) -{ - return p1.x() == p2.x() && p1.y() == p2.y() && p1.z() == p2.z(); -} - -SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const -{ - return (v - *this).length2(); -} - -SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const -{ - return (v - *this).length(); -} - -SIMD_FORCE_INLINE btVector3 btVector3::normalized() const -{ - return *this / length(); -} - -SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar angle ) -{ - // wAxis must be a unit lenght vector - - btVector3 o = wAxis * wAxis.dot( *this ); - btVector3 x = *this - o; - btVector3 y; - - y = wAxis.cross( *this ); - - return ( o + x * btCos( angle ) + y * btSin( angle ) ); -} - -class btVector4 : public btVector3 -{ -public: - - SIMD_FORCE_INLINE btVector4() {} - - - SIMD_FORCE_INLINE btVector4(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) - : btVector3(x,y,z) - { - m_unusedW = w; - } - - - SIMD_FORCE_INLINE btVector4 absolute4() const - { - return btVector4( - btFabs(m_x), - btFabs(m_y), - btFabs(m_z), - btFabs(m_unusedW)); - } - - - - btScalar getW() const { return m_unusedW;} - - - SIMD_FORCE_INLINE int maxAxis4() const - { - int maxIndex = -1; - btScalar maxVal = btScalar(-1e30); - if (m_x > maxVal) - { - maxIndex = 0; - maxVal = m_x; - } - if (m_y > maxVal) - { - maxIndex = 1; - maxVal = m_y; - } - if (m_z > maxVal) - { - maxIndex = 2; - maxVal = m_z; - } - if (m_unusedW > maxVal) - { - maxIndex = 3; - maxVal = m_unusedW; - } - - - - - return maxIndex; - - } - - - SIMD_FORCE_INLINE int minAxis4() const - { - int minIndex = -1; - btScalar minVal = btScalar(1e30); - if (m_x < minVal) - { - minIndex = 0; - minVal = m_x; - } - if (m_y < minVal) - { - minIndex = 1; - minVal = m_y; - } - if (m_z < minVal) - { - minIndex = 2; - minVal = m_z; - } - if (m_unusedW < minVal) - { - minIndex = 3; - minVal = m_unusedW; - } - - return minIndex; - - } - - - SIMD_FORCE_INLINE int closestAxis4() const - { - return absolute4().maxAxis4(); - } - -}; - - -///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization -SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal) -{ - #ifdef BT_USE_DOUBLE_PRECISION - unsigned char* dest = (unsigned char*) &destVal; - unsigned char* src = (unsigned char*) &sourceVal; - dest[0] = src[7]; - dest[1] = src[6]; - dest[2] = src[5]; - dest[3] = src[4]; - dest[4] = src[3]; - dest[5] = src[2]; - dest[6] = src[1]; - dest[7] = src[0]; -#else - unsigned char* dest = (unsigned char*) &destVal; - unsigned char* src = (unsigned char*) &sourceVal; - dest[0] = src[3]; - dest[1] = src[2]; - dest[2] = src[1]; - dest[3] = src[0]; -#endif //BT_USE_DOUBLE_PRECISION -} -///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization -SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec) -{ - for (int i=0;i<4;i++) - { - btSwapScalarEndian(sourceVec[i],destVec[i]); - } - -} - -///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization -SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector) -{ - - btVector3 swappedVec; - for (int i=0;i<4;i++) - { - btSwapScalarEndian(vector[i],swappedVec[i]); - } - vector = swappedVec; -} - -#endif //SIMD__VECTOR3_H diff --git a/extern/bullet2/src/LinearMath/ibmsdk/Makefile b/extern/bullet2/src/LinearMath/ibmsdk/Makefile deleted file mode 100644 index 2ad26576241..00000000000 --- a/extern/bullet2/src/LinearMath/ibmsdk/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -#### Source code Dirs -VPATH = ../ - -ROOT = ../../.. - -#### Library -LIBRARY_ppu = bulletmath.a - -#### Compiler flags -CPPFLAGS = \ --DUSE_LIBSPE2 \ --I$(ROOT)/src \ --I$(SDKINC) - -#### Optimization level flags -#CC_OPT_LEVEL = $(CC_OPT_LEVEL_DEBUG) -CC_OPT_LEVEL = -O3 - -##### Objects to be archived in lib - -OBJS = \ -btAlignedAllocator.o \ -btGeometryUtil.o \ -btQuickprof.o - -#### Install directories -INSTALL_DIR = $(ROOT)/lib/ibmsdk -INSTALL_FILES = $(LIBRARY_ppu) -CELL_TOP ?= /opt/ibm/cell-sdk/prototype -include $(CELL_TOP)/make.footer diff --git a/extern/bullet2/src/Makefile b/extern/bullet2/src/Makefile deleted file mode 100644 index 567811bae28..00000000000 --- a/extern/bullet2/src/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -# -# $Id$ -# -# ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. The Blender -# Foundation also sells licenses for use in proprietary software under -# the Blender License. See http://www.blender.org/BL/ for information -# about this. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. -# All rights reserved. -# -# The Original Code is: all of this file. -# -# Contributor(s): none yet. -# -# ***** END GPL/BL DUAL LICENSE BLOCK ***** -# - -LIBNAME = bullet2 -DIR = $(OCGDIR)/extern/$(LIBNAME) - -BULLETDIRS = \ -LinearMath \ -BulletCollision/BroadphaseCollision \ -BulletCollision/CollisionShapes \ -BulletCollision/NarrowPhaseCollision \ -BulletCollision/CollisionDispatch \ -BulletDynamics/ConstraintSolver \ -BulletDynamics/Vehicle \ -BulletDynamics/Dynamics - -CCSRCS = $(wildcard \ -LinearMath/*.cpp \ -BulletCollision/BroadphaseCollision/*.cpp \ -BulletCollision/CollisionShapes/*.cpp \ -BulletCollision/NarrowPhaseCollision/*.cpp \ -BulletCollision/CollisionDispatch/*.cpp \ -BulletDynamics/ConstraintSolver/*.cpp \ -BulletDynamics/Vehicle/*.cpp \ -BulletDynamics/Dynamics/*.cpp) - -CPPFLAGS += -D_LIB -I. -IBulletCollision -IBulletDynamics -ILinearMath - -all debug:: objdirs - -include nan_compile.mk - -.PHONY: objdirs clean -objdirs: - @for i in $(BULLETDIRS); do \ - [ -d $(DIR)/$(DEBUG_DIR)$$i ] || mkdir -p $(DIR)/$(DEBUG_DIR)$$i; \ - done - -clean:: - rm -rf $(DIR) - rm -rf $(NAN_BULLET2)/lib/libbullet2.a - rm -rf $(NAN_BULLET2)/include diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript deleted file mode 100644 index 19702782b0d..00000000000 --- a/extern/bullet2/src/SConscript +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/python -import sys -import os - -Import('env') - -defs = 'USE_DOUBLES QHULL _LIB' -cflags = [] - -if env['OURPLATFORM']=='win32-vc': - defs += ' WIN32 NDEBUG _WINDOWS _LIB' - #cflags += ['/MT', '/W3', '/GX', '/O2', '/Op'] - cflags += ['/MT', '/W3', '/GX', '/Og', '/Ot', '/Ob1', '/Op', '/G6'] -elif env['OURPLATFORM']=='win32-mingw': - defs += ' NDEBUG' - cflags += ['-O2'] -elif sys.platform=='linux2' or sys.platform=='linux-i386' or sys.platform=='freebsd4' or sys.platform=='freebsd5': - defs += ' NDEBUG' - cflags += ['-O2'] -elif sys.platform=='darwin': - defs += ' NDEBUG' - cflags += ['-O2','-pipe', '-fPIC', '-funsigned-char', '-ffast-math'] - -linearmath_src = env.Glob("LinearMath/*.cpp") -bulletdyn_src = ["BulletDynamics/ConstraintSolver/btContactConstraint.cpp", - "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp", - "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp", - "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp", - "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp", - "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp", - "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp", - "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp", - "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.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", - "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp", - "BulletCollision/BroadphaseCollision/btDispatcher.cpp", - "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", - "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", - "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp", - "BulletCollision/CollisionDispatch/btCollisionObject.cpp", - "BulletCollision/CollisionDispatch/btCollisionWorld.cpp", - "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btManifoldResult.cpp", - "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp", - "BulletCollision/CollisionDispatch/btUnionFind.cpp", - "BulletCollision/CollisionShapes/btBoxShape.cpp", - "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btCollisionShape.cpp", - "BulletCollision/CollisionShapes/btCompoundShape.cpp", - "BulletCollision/CollisionShapes/btConcaveShape.cpp", - "BulletCollision/CollisionShapes/btConeShape.cpp", - "BulletCollision/CollisionShapes/btConvexHullShape.cpp", - "BulletCollision/CollisionShapes/btConvexShape.cpp", - "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btCylinderShape.cpp", - "BulletCollision/CollisionShapes/btEmptyShape.cpp", - "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp", - "BulletCollision/CollisionShapes/btMultiSphereShape.cpp", - "BulletCollision/CollisionShapes/btOptimizedBvh.cpp", - "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp", - "BulletCollision/CollisionShapes/btTetrahedronShape.cpp", - "BulletCollision/CollisionShapes/btSphereShape.cpp", - "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp", - "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp", - "BulletCollision/CollisionShapes/btTriangleCallback.cpp", - "BulletCollision/CollisionShapes/btTriangleBuffer.cpp", - "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp", - "BulletCollision/CollisionShapes/btTriangleMesh.cpp", - "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp", - "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp", - "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp", - "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp", - "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp", - "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp", - "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp"] - -incs = '. BulletCollision BulletDynamics LinearMath' - -env.BlenderLib ( libname = 'extern_bullet2linmath', sources=linearmath_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) -env.BlenderLib ( libname = 'extern_bullet2dynamics', sources=bulletdyn_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[19, 169], compileflags=cflags ) -env.BlenderLib ( libname = 'extern_bullet2collision', sources=collision_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) diff --git a/extern/bullet2/src/btBulletCollisionCommon.h b/extern/bullet2/src/btBulletCollisionCommon.h deleted file mode 100644 index a309f7d76d2..00000000000 --- a/extern/bullet2/src/btBulletCollisionCommon.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -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. -*/ - -#ifndef BULLET_COLLISION_COMMON_H -#define BULLET_COLLISION_COMMON_H - -///Common headerfile includes for Bullet Collision Detection - -///Bullet's btCollisionWorld and btCollisionObject definitions -#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" - -///Collision Shapes -#include "BulletCollision/CollisionShapes/btBoxShape.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionShapes/btCapsuleShape.h" -#include "BulletCollision/CollisionShapes/btCylinderShape.h" -#include "BulletCollision/CollisionShapes/btConeShape.h" -#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" -#include "BulletCollision/CollisionShapes/btConvexHullShape.h" -#include "BulletCollision/CollisionShapes/btTriangleMesh.h" -#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" -#include "BulletCollision/CollisionShapes/btCompoundShape.h" -#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" -#include "BulletCollision/CollisionShapes/btEmptyShape.h" -#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" -#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" - -///Narrowphase Collision Detector -#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" - -///Dispatching and generation of collision pairs (broadphase) -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" -#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" - - -///Math library & Utils -#include "LinearMath/btQuaternion.h" -#include "LinearMath/btTransform.h" -#include "LinearMath/btDefaultMotionState.h" -#include "LinearMath/btQuickprof.h" -#include "LinearMath/btIDebugDraw.h" - -#endif //BULLET_COLLISION_COMMON_H - diff --git a/extern/bullet2/src/btBulletDynamicsCommon.h b/extern/bullet2/src/btBulletDynamicsCommon.h deleted file mode 100644 index 5d08dac0c0d..00000000000 --- a/extern/bullet2/src/btBulletDynamicsCommon.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -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. -*/ - -#ifndef BULLET_DYNAMICS_COMMON_H -#define BULLET_DYNAMICS_COMMON_H - -///Common headerfile includes for Bullet Dynamics, including Collision Detection -#include "btBulletCollisionCommon.h" - -#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" -#include "BulletDynamics/Dynamics/btContinuousDynamicsWorld.h" - -#include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" - -#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" -#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" -#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" -#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" - - -#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" -///Vehicle simulation, with wheel contact simulated by raycasts -#include "BulletDynamics/Vehicle/btRaycastVehicle.h" - - - - - - -#endif //BULLET_DYNAMICS_COMMON_H - diff --git a/extern/bullet2/src/ibmsdk/Makefile b/extern/bullet2/src/ibmsdk/Makefile deleted file mode 100644 index 768fffd35a4..00000000000 --- a/extern/bullet2/src/ibmsdk/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -#### Visit Bullet library ibmsdk dirs and build code -CELL_TOP ?= /opt/ibm/cell-sdk/prototype - -DIRS := \ -../BulletCollision/ibmsdk \ -../BulletDynamics/ibmsdk \ -../LinearMath/ibmsdk - - -include $(CELL_TOP)/make.footer diff --git a/source/blender/include/BIF_imasel.h b/source/blender/include/BIF_imasel.h index a3a3b7531d6..cbd547602e1 100644 --- a/source/blender/include/BIF_imasel.h +++ b/source/blender/include/BIF_imasel.h @@ -34,6 +34,7 @@ struct ScrArea; struct ID; void free_imasel(struct SpaceImaSel *simasel); +void reset_imaselspace(struct ScrArea *sa); void clever_numbuts_imasel(void); diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h index 09ce87015d9..be1f5581be7 100644 --- a/source/blender/include/BSE_drawview.h +++ b/source/blender/include/BSE_drawview.h @@ -46,7 +46,7 @@ void do_viewbuts(unsigned short event); /* View3DAfter->type */ #define V3D_XRAY 1 #define V3D_TRANSP 2 -void add_view3d_after(struct View3D *v3d, struct Base *base, int type); +void add_view3d_after(struct View3D *v3d, struct Base *base, int type, int flag); void backdrawview3d(int test); void check_backbuf(void); diff --git a/source/blender/include/BSE_filesel.h b/source/blender/include/BSE_filesel.h index 13e38d50c47..b46b2328ea4 100644 --- a/source/blender/include/BSE_filesel.h +++ b/source/blender/include/BSE_filesel.h @@ -54,6 +54,7 @@ void activate_databrowse(struct ID *id, int idcode, int fromcode, int retval, sh void activate_databrowse_args(struct ID *id, int idcode, int fromcode, short *menup, void (*func)(char *, void *, void *), void *arg1, void *arg2); void filesel_prevspace(void); +void reset_filespace(struct ScrArea *sa); void free_filesel_spec(char *dir); void winqreadfilespace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt); void main_to_filelist(struct SpaceFile *sfile); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index c45571cb583..acc1651e9fa 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -224,7 +224,7 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_DUPLILINK (1 << 6) #define USER_FSCOLLUM (1 << 7) #define USER_MAT_ON_OB (1 << 8) -#define USER_NO_CAPSLOCK (1 << 9) +/*#define USER_NO_CAPSLOCK (1 << 9)*/ /* not used anywhere */ #define USER_VIEWMOVE (1 << 10) #define USER_TOOLTIPS (1 << 11) #define USER_TWOBUTTONMOUSE (1 << 12) @@ -236,7 +236,8 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_ADD_EDITMODE (1 << 18) #define USER_ADD_VIEWALIGNED (1 << 19) #define USER_RELPATHS (1 << 20) -#define USER_DRAGIMMEDIATE (1 << 21) +#define USER_DRAGIMMEDIATE (1 << 21) +#define USER_DONT_DOSCRIPTLINKS (1 << 22) /* viewzom */ #define USER_ZOOM_CONT 0 From 96408da81a8c8cd5cb737ed4236fc1386ce70c6e Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 7 May 2008 20:22:28 +0000 Subject: [PATCH 087/101] Added bullet back to branch, compiling works again --- extern/bullet2/CMakeLists.txt | 43 + extern/bullet2/Makefile | 61 + .../bullet2/make/msvc_7_0/Bullet_vc7.vcproj | 927 +++++++++++++ extern/bullet2/readme.txt | 12 + extern/bullet2/src/Bullet-C-Api.h | 37 + .../BroadphaseCollision/btAxisSweep3.cpp | 660 ++++++++++ .../BroadphaseCollision/btAxisSweep3.h | 138 ++ .../btBroadphaseInterface.h | 40 + .../BroadphaseCollision/btBroadphaseProxy.cpp | 17 + .../BroadphaseCollision/btBroadphaseProxy.h | 204 +++ .../btCollisionAlgorithm.cpp | 23 + .../btCollisionAlgorithm.h | 77 ++ .../BroadphaseCollision/btDispatcher.cpp | 22 + .../BroadphaseCollision/btDispatcher.h | 93 ++ .../btOverlappingPairCache.cpp | 196 +++ .../btOverlappingPairCache.h | 120 ++ .../btSimpleBroadphase.cpp | 222 ++++ .../BroadphaseCollision/btSimpleBroadphase.h | 95 ++ .../src/BulletCollision/CMakeLists.txt | 60 + .../SphereTriangleDetector.cpp | 200 +++ .../SphereTriangleDetector.h | 49 + .../CollisionDispatch/btCollisionCreateFunc.h | 46 + .../btCollisionDispatcher.cpp | 367 ++++++ .../CollisionDispatch/btCollisionDispatcher.h | 135 ++ .../CollisionDispatch/btCollisionObject.cpp | 57 + .../CollisionDispatch/btCollisionObject.h | 346 +++++ .../CollisionDispatch/btCollisionWorld.cpp | 362 ++++++ .../CollisionDispatch/btCollisionWorld.h | 255 ++++ .../btCompoundCollisionAlgorithm.cpp | 140 ++ .../btCompoundCollisionAlgorithm.h | 64 + .../btConvexConcaveCollisionAlgorithm.cpp | 312 +++++ .../btConvexConcaveCollisionAlgorithm.h | 111 ++ .../btConvexConvexAlgorithm.cpp | 254 ++++ .../btConvexConvexAlgorithm.h | 76 ++ .../btEmptyCollisionAlgorithm.cpp | 34 + .../btEmptyCollisionAlgorithm.h | 48 + .../CollisionDispatch/btManifoldResult.cpp | 109 ++ .../CollisionDispatch/btManifoldResult.h | 77 ++ .../btSimulationIslandManager.cpp | 357 +++++ .../btSimulationIslandManager.h | 61 + .../btSphereBoxCollisionAlgorithm.cpp | 249 ++++ .../btSphereBoxCollisionAlgorithm.h | 64 + .../btSphereSphereCollisionAlgorithm.cpp | 85 ++ .../btSphereSphereCollisionAlgorithm.h | 56 + .../btSphereTriangleCollisionAlgorithm.cpp | 76 ++ .../btSphereTriangleCollisionAlgorithm.h | 59 + .../CollisionDispatch/btUnionFind.cpp | 83 ++ .../CollisionDispatch/btUnionFind.h | 124 ++ .../CollisionShapes/btBoxShape.cpp | 57 + .../CollisionShapes/btBoxShape.h | 293 +++++ .../btBvhTriangleMeshShape.cpp | 173 +++ .../CollisionShapes/btBvhTriangleMeshShape.h | 75 ++ .../CollisionShapes/btCapsuleShape.cpp | 146 +++ .../CollisionShapes/btCapsuleShape.h | 60 + .../CollisionShapes/btCollisionMargin.h | 26 + .../CollisionShapes/btCollisionShape.cpp | 85 ++ .../CollisionShapes/btCollisionShape.h | 94 ++ .../CollisionShapes/btCompoundShape.cpp | 100 ++ .../CollisionShapes/btCompoundShape.h | 117 ++ .../CollisionShapes/btConcaveShape.cpp | 28 + .../CollisionShapes/btConcaveShape.h | 50 + .../CollisionShapes/btConeShape.cpp | 133 ++ .../CollisionShapes/btConeShape.h | 103 ++ .../CollisionShapes/btConvexHullShape.cpp | 179 +++ .../CollisionShapes/btConvexHullShape.h | 76 ++ .../CollisionShapes/btConvexShape.cpp | 77 ++ .../CollisionShapes/btConvexShape.h | 127 ++ .../btConvexTriangleMeshShape.cpp | 205 +++ .../btConvexTriangleMeshShape.h | 51 + .../CollisionShapes/btCylinderShape.cpp | 206 +++ .../CollisionShapes/btCylinderShape.h | 138 ++ .../CollisionShapes/btEmptyShape.cpp | 49 + .../CollisionShapes/btEmptyShape.h | 70 + .../btHeightfieldTerrainShape.cpp | 339 +++++ .../btHeightfieldTerrainShape.h | 88 ++ .../CollisionShapes/btMinkowskiSumShape.cpp | 57 + .../CollisionShapes/btMinkowskiSumShape.h | 62 + .../CollisionShapes/btMultiSphereShape.cpp | 148 +++ .../CollisionShapes/btMultiSphereShape.h | 74 ++ .../CollisionShapes/btOptimizedBvh.cpp | 845 ++++++++++++ .../CollisionShapes/btOptimizedBvh.h | 330 +++++ .../btPolyhedralConvexShape.cpp | 148 +++ .../CollisionShapes/btPolyhedralConvexShape.h | 93 ++ .../CollisionShapes/btSphereShape.cpp | 77 ++ .../CollisionShapes/btSphereShape.h | 63 + .../CollisionShapes/btStaticPlaneShape.cpp | 105 ++ .../CollisionShapes/btStaticPlaneShape.h | 61 + .../btStridingMeshInterface.cpp | 124 ++ .../CollisionShapes/btStridingMeshInterface.h | 89 ++ .../CollisionShapes/btTetrahedronShape.cpp | 195 +++ .../CollisionShapes/btTetrahedronShape.h | 75 ++ .../CollisionShapes/btTriangleBuffer.cpp | 42 + .../CollisionShapes/btTriangleBuffer.h | 61 + .../CollisionShapes/btTriangleCallback.cpp | 28 + .../CollisionShapes/btTriangleCallback.h | 40 + .../btTriangleIndexVertexArray.cpp | 65 + .../btTriangleIndexVertexArray.h | 97 ++ .../CollisionShapes/btTriangleMesh.cpp | 60 + .../CollisionShapes/btTriangleMesh.h | 75 ++ .../CollisionShapes/btTriangleMeshShape.cpp | 203 +++ .../CollisionShapes/btTriangleMeshShape.h | 78 ++ .../CollisionShapes/btTriangleShape.h | 179 +++ extern/bullet2/src/BulletCollision/Doxyfile | 746 +++++++++++ .../btContinuousConvexCollision.cpp | 200 +++ .../btContinuousConvexCollision.h | 52 + .../NarrowPhaseCollision/btConvexCast.cpp | 20 + .../NarrowPhaseCollision/btConvexCast.h | 71 + .../btConvexPenetrationDepthSolver.h | 43 + .../btDiscreteCollisionDetectorInterface.h | 88 ++ .../NarrowPhaseCollision/btGjkConvexCast.cpp | 174 +++ .../NarrowPhaseCollision/btGjkConvexCast.h | 50 + .../NarrowPhaseCollision/btGjkEpa.cpp | 628 +++++++++ .../NarrowPhaseCollision/btGjkEpa.h | 53 + .../btGjkEpaPenetrationDepthSolver.cpp | 50 + .../btGjkEpaPenetrationDepthSolver.h | 39 + .../btGjkPairDetector.cpp | 299 +++++ .../NarrowPhaseCollision/btGjkPairDetector.h | 85 ++ .../NarrowPhaseCollision/btManifoldPoint.h | 99 ++ .../btMinkowskiPenetrationDepthSolver.cpp | 334 +++++ .../btMinkowskiPenetrationDepthSolver.h | 37 + .../btPersistentManifold.cpp | 246 ++++ .../btPersistentManifold.h | 161 +++ .../NarrowPhaseCollision/btPointCollector.h | 61 + .../btRaycastCallback.cpp | 101 ++ .../NarrowPhaseCollision/btRaycastCallback.h | 42 + .../btSimplexSolverInterface.h | 64 + .../btSubSimplexConvexCast.cpp | 139 ++ .../btSubSimplexConvexCast.h | 50 + .../btVoronoiSimplexSolver.cpp | 607 +++++++++ .../btVoronoiSimplexSolver.h | 157 +++ .../bullet2/src/BulletDynamics/CMakeLists.txt | 20 + .../btConeTwistConstraint.cpp | 285 ++++ .../ConstraintSolver/btConeTwistConstraint.h | 123 ++ .../ConstraintSolver/btConstraintSolver.h | 45 + .../ConstraintSolver/btContactConstraint.cpp | 417 ++++++ .../ConstraintSolver/btContactConstraint.h | 122 ++ .../ConstraintSolver/btContactSolverInfo.h | 47 + .../btGeneric6DofConstraint.cpp | 389 ++++++ .../btGeneric6DofConstraint.h | 120 ++ .../ConstraintSolver/btHingeConstraint.cpp | 229 ++++ .../ConstraintSolver/btHingeConstraint.h | 81 ++ .../ConstraintSolver/btJacobianEntry.h | 156 +++ .../btPoint2PointConstraint.cpp | 116 ++ .../btPoint2PointConstraint.h | 77 ++ .../btSequentialImpulseConstraintSolver.cpp | 1158 +++++++++++++++++ .../btSequentialImpulseConstraintSolver.h | 109 ++ .../btSolve2LinearConstraint.cpp | 255 ++++ .../btSolve2LinearConstraint.h | 107 ++ .../ConstraintSolver/btSolverBody.h | 71 + .../ConstraintSolver/btSolverConstraint.h | 63 + .../ConstraintSolver/btTypedConstraint.cpp | 53 + .../ConstraintSolver/btTypedConstraint.h | 96 ++ .../BulletDynamics/Dynamics/Bullet-C-API.cpp | 120 ++ .../Dynamics/btDiscreteDynamicsWorld.cpp | 954 ++++++++++++++ .../Dynamics/btDiscreteDynamicsWorld.h | 157 +++ .../BulletDynamics/Dynamics/btDynamicsWorld.h | 78 ++ .../BulletDynamics/Dynamics/btRigidBody.cpp | 345 +++++ .../src/BulletDynamics/Dynamics/btRigidBody.h | 357 +++++ .../Dynamics/btSimpleDynamicsWorld.cpp | 211 +++ .../Dynamics/btSimpleDynamicsWorld.h | 82 ++ .../Vehicle/btRaycastVehicle.cpp | 733 +++++++++++ .../BulletDynamics/Vehicle/btRaycastVehicle.h | 201 +++ .../Vehicle/btVehicleRaycaster.h | 35 + .../BulletDynamics/Vehicle/btWheelInfo.cpp | 56 + .../src/BulletDynamics/Vehicle/btWheelInfo.h | 116 ++ extern/bullet2/src/CMakeLists.txt | 1 + extern/bullet2/src/LinearMath/CMakeLists.txt | 10 + extern/bullet2/src/LinearMath/btAabbUtil2.h | 127 ++ .../src/LinearMath/btAlignedAllocator.cpp | 70 + .../src/LinearMath/btAlignedAllocator.h | 80 ++ .../src/LinearMath/btAlignedObjectArray.h | 367 ++++++ .../src/LinearMath/btDefaultMotionState.h | 38 + .../bullet2/src/LinearMath/btGeometryUtil.cpp | 178 +++ .../bullet2/src/LinearMath/btGeometryUtil.h | 41 + extern/bullet2/src/LinearMath/btIDebugDraw.h | 100 ++ extern/bullet2/src/LinearMath/btList.h | 73 ++ extern/bullet2/src/LinearMath/btMatrix3x3.h | 410 ++++++ extern/bullet2/src/LinearMath/btMinMax.h | 69 + extern/bullet2/src/LinearMath/btMotionState.h | 40 + extern/bullet2/src/LinearMath/btPoint3.h | 24 + extern/bullet2/src/LinearMath/btQuadWord.h | 139 ++ extern/bullet2/src/LinearMath/btQuaternion.h | 321 +++++ extern/bullet2/src/LinearMath/btQuickprof.cpp | 38 + extern/bullet2/src/LinearMath/btQuickprof.h | 712 ++++++++++ extern/bullet2/src/LinearMath/btRandom.h | 42 + extern/bullet2/src/LinearMath/btScalar.h | 181 +++ extern/bullet2/src/LinearMath/btSimdMinMax.h | 41 + extern/bullet2/src/LinearMath/btStackAlloc.h | 106 ++ extern/bullet2/src/LinearMath/btTransform.h | 206 +++ .../bullet2/src/LinearMath/btTransformUtil.h | 138 ++ extern/bullet2/src/LinearMath/btVector3.h | 402 ++++++ extern/bullet2/src/Makefile | 68 + extern/bullet2/src/SConscript | 98 ++ extern/bullet2/src/btBulletCollisionCommon.h | 61 + extern/bullet2/src/btBulletDynamicsCommon.h | 42 + 195 files changed, 30425 insertions(+) create mode 100644 extern/bullet2/CMakeLists.txt create mode 100644 extern/bullet2/Makefile create mode 100644 extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj create mode 100644 extern/bullet2/readme.txt create mode 100644 extern/bullet2/src/Bullet-C-Api.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h create mode 100644 extern/bullet2/src/BulletCollision/CMakeLists.txt create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h create mode 100644 extern/bullet2/src/BulletCollision/Doxyfile create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h create mode 100644 extern/bullet2/src/BulletDynamics/CMakeLists.txt create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h create mode 100644 extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp create mode 100644 extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h create mode 100644 extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h create mode 100644 extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.cpp create mode 100644 extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h create mode 100644 extern/bullet2/src/CMakeLists.txt create mode 100644 extern/bullet2/src/LinearMath/CMakeLists.txt create mode 100644 extern/bullet2/src/LinearMath/btAabbUtil2.h create mode 100644 extern/bullet2/src/LinearMath/btAlignedAllocator.cpp create mode 100644 extern/bullet2/src/LinearMath/btAlignedAllocator.h create mode 100644 extern/bullet2/src/LinearMath/btAlignedObjectArray.h create mode 100644 extern/bullet2/src/LinearMath/btDefaultMotionState.h create mode 100644 extern/bullet2/src/LinearMath/btGeometryUtil.cpp create mode 100644 extern/bullet2/src/LinearMath/btGeometryUtil.h create mode 100644 extern/bullet2/src/LinearMath/btIDebugDraw.h create mode 100644 extern/bullet2/src/LinearMath/btList.h create mode 100644 extern/bullet2/src/LinearMath/btMatrix3x3.h create mode 100644 extern/bullet2/src/LinearMath/btMinMax.h create mode 100644 extern/bullet2/src/LinearMath/btMotionState.h create mode 100644 extern/bullet2/src/LinearMath/btPoint3.h create mode 100644 extern/bullet2/src/LinearMath/btQuadWord.h create mode 100644 extern/bullet2/src/LinearMath/btQuaternion.h create mode 100644 extern/bullet2/src/LinearMath/btQuickprof.cpp create mode 100644 extern/bullet2/src/LinearMath/btQuickprof.h create mode 100644 extern/bullet2/src/LinearMath/btRandom.h create mode 100644 extern/bullet2/src/LinearMath/btScalar.h create mode 100644 extern/bullet2/src/LinearMath/btSimdMinMax.h create mode 100644 extern/bullet2/src/LinearMath/btStackAlloc.h create mode 100644 extern/bullet2/src/LinearMath/btTransform.h create mode 100644 extern/bullet2/src/LinearMath/btTransformUtil.h create mode 100644 extern/bullet2/src/LinearMath/btVector3.h create mode 100644 extern/bullet2/src/Makefile create mode 100644 extern/bullet2/src/SConscript create mode 100644 extern/bullet2/src/btBulletCollisionCommon.h create mode 100644 extern/bullet2/src/btBulletDynamicsCommon.h diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt new file mode 100644 index 00000000000..b5ae20253cc --- /dev/null +++ b/extern/bullet2/CMakeLists.txt @@ -0,0 +1,43 @@ +# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $ +# ***** BEGIN GPL 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. +# +# 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, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Jacques Beaurai, Erwin Coumans +# +# ***** END GPL LICENSE BLOCK ***** + +SET(INC . src) + +FILE(GLOB SRC + src/LinearMath/*.cpp + src/BulletCollision/BroadphaseCollision/*.cpp + src/BulletCollision/CollisionShapes/*.cpp + src/BulletCollision/NarrowPhaseCollision/*.cpp + src/BulletCollision//CollisionDispatch/*.cpp + src/BulletDynamics/ConstraintSolver/*.cpp + src/BulletDynamics/Vehicle/*.cpp + src/BulletDynamics/Dynamics/*.cpp +) + +ADD_DEFINITIONS(-D_LIB) + +BLENDERLIB(extern_bullet "${SRC}" "${INC}") +#, libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) diff --git a/extern/bullet2/Makefile b/extern/bullet2/Makefile new file mode 100644 index 00000000000..2da1a5bcf85 --- /dev/null +++ b/extern/bullet2/Makefile @@ -0,0 +1,61 @@ +# +# $Id: Makefile 14444 2008-04-16 22:40:48Z hos $ +# +# ***** BEGIN GPL 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. +# +# 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) 2002 by Hans Lambermont +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): +# +# ***** END GPL LICENSE BLOCK ***** +LIBNAME = bullet2 +include nan_definitions.mk +SOURCEDIR = extern/$(LIBNAME) +DIR = $(OCGDIR)/extern/$(LIBNAME) +DIRS = src +DISTDIR = src + +BULLETDIRS = \ +LinearMath \ +BulletCollision/BroadphaseCollision \ +BulletCollision/CollisionShapes \ +BulletCollision/NarrowPhaseCollision \ +BulletCollision//CollisionDispatch \ +BulletDynamics/ConstraintSolver \ +BulletDynamics/Vehicle \ +BulletDynamics/Dynamics + +include nan_subdirs.mk + +CP = $(NANBLENDERHOME)/intern/tools/cpifdiff.sh + +install: all debug + @[ -d $(NAN_BULLET2) ] || mkdir -p $(NAN_BULLET2) + @[ -d $(NAN_BULLET2)/include ] || mkdir -p $(NAN_BULLET2)/include + @for i in $(BULLETDIRS); do \ + [ -d $(NAN_BULLET2)/include/$$i ] || mkdir -p $(NAN_BULLET2)/include/$$i; \ + $(CP) $(DISTDIR)/$$i/*.h $(NAN_BULLET2)/include/$$i; \ + done + @[ -d $(NAN_BULLET2)/lib ] || mkdir -p $(NAN_BULLET2)/lib + @$(CP) $(DISTDIR)/*.h $(NAN_BULLET2)/include + @$(CP) $(OCGDIR)/extern/bullet2/libbullet2.a $(NAN_BULLET2)/lib +ifeq ($(OS),darwin) + ranlib $(NAN_BULLET2)/lib/libbullet2.a +endif diff --git a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj new file mode 100644 index 00000000000..6de2fd3a2bd --- /dev/null +++ b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj @@ -0,0 +1,927 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extern/bullet2/readme.txt b/extern/bullet2/readme.txt new file mode 100644 index 00000000000..4d1a4c11706 --- /dev/null +++ b/extern/bullet2/readme.txt @@ -0,0 +1,12 @@ + +*** These files in extern/bullet2 are NOT part of the Blender build yet *** + +This is the new refactored version of Bullet physics library version 2.x + +Soon this will replace the old Bullet version in extern/bullet. +First the integration in Blender Game Engine needs to be updated. +Once that is done all build systems can be updated to use/build extern/bullet2 files. + +Questions? mail blender at erwincoumans.com, or check the bf-blender mailing list. +Thanks, +Erwin diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h new file mode 100644 index 00000000000..078dcae63bb --- /dev/null +++ b/extern/bullet2/src/Bullet-C-Api.h @@ -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 + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp new file mode 100644 index 00000000000..be4a11506df --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp @@ -0,0 +1,660 @@ + +//Bullet Continuous Collision Detection and Physics Library +//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + + +// +// btAxisSweep3 +// +// Copyright (c) 2006 Simon Hobbs +// +// 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. +#include "btAxisSweep3.h" + +#include + +#ifdef DEBUG_BROADPHASE +#include +void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) +{ + int numEdges = m_pHandles[0].m_maxEdges[axis]; + printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); + + int i; + for (i=0;im_handle); + int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; + char beginOrEnd; + beginOrEnd=pEdge->IsMax()?'E':'B'; + printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); + } + + if (checkCardinality) + assert(numEdges == m_numHandles*2+1); +} +#endif //DEBUG_BROADPHASE + + +btBroadphaseProxy* btAxisSweep3::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask) +{ + (void)shapeType; + BP_FP_INT_TYPE handleId = addHandle(min,max, userPtr,collisionFilterGroup,collisionFilterMask); + + Handle* handle = getHandle(handleId); + + return handle; +} + +void btAxisSweep3::destroyProxy(btBroadphaseProxy* proxy) +{ + Handle* handle = static_cast(proxy); + removeHandle(handle->m_handleId); +} + +void btAxisSweep3::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax) +{ + Handle* handle = static_cast(proxy); + updateHandle(handle->m_handleId,aabbMin,aabbMax); + +} + + + + + + +btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles) +:btOverlappingPairCache() +{ + m_invalidPair = 0; + //assert(bounds.HasVolume()); + + // 1 handle is reserved as sentinel + btAssert(maxHandles > 1 && maxHandles < BP_MAX_HANDLES); + + // init bounds + m_worldAabbMin = worldAabbMin; + m_worldAabbMax = worldAabbMax; + + btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; + + BP_FP_INT_TYPE maxInt = BP_HANDLE_SENTINEL; + + m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; + + // allocate handles buffer and put all handles on free list + m_pHandles = new Handle[maxHandles]; + m_maxHandles = maxHandles; + m_numHandles = 0; + + // handle 0 is reserved as the null index, and is also used as the sentinel + m_firstFreeHandle = 1; + { + for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) + m_pHandles[i].SetNextFree(i + 1); + m_pHandles[maxHandles - 1].SetNextFree(0); + } + + { + // allocate edge buffers + for (int i = 0; i < 3; i++) + m_pEdges[i] = new Edge[maxHandles * 2]; + } + //removed overlap management + + // make boundary sentinels + + m_pHandles[0].m_clientObject = 0; + + for (int axis = 0; axis < 3; axis++) + { + m_pHandles[0].m_minEdges[axis] = 0; + m_pHandles[0].m_maxEdges[axis] = 1; + + m_pEdges[axis][0].m_pos = 0; + m_pEdges[axis][0].m_handle = 0; + m_pEdges[axis][1].m_pos = BP_HANDLE_SENTINEL; + m_pEdges[axis][1].m_handle = 0; +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + + } + +} + +btAxisSweep3::~btAxisSweep3() +{ + + for (int i = 2; i >= 0; i--) + delete[] m_pEdges[i]; + delete[] m_pHandles; +} + +void btAxisSweep3::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const +{ + btPoint3 clampedPoint(point); + + + + clampedPoint.setMax(m_worldAabbMin); + clampedPoint.setMin(m_worldAabbMax); + + btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; + out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & BP_HANDLE_MASK) | isMax); + out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & BP_HANDLE_MASK) | isMax); + out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & BP_HANDLE_MASK) | isMax); + +} + + + +BP_FP_INT_TYPE btAxisSweep3::allocHandle() +{ + assert(m_firstFreeHandle); + + BP_FP_INT_TYPE handle = m_firstFreeHandle; + m_firstFreeHandle = getHandle(handle)->GetNextFree(); + m_numHandles++; + + return handle; +} + +void btAxisSweep3::freeHandle(BP_FP_INT_TYPE handle) +{ + assert(handle > 0 && handle < m_maxHandles); + + getHandle(handle)->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + m_numHandles--; +} + + + +BP_FP_INT_TYPE btAxisSweep3::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask) +{ + // quantize the bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // allocate a handle + BP_FP_INT_TYPE handle = allocHandle(); + assert(handle!= 0xcdcd); + + Handle* pHandle = getHandle(handle); + + pHandle->m_handleId = handle; + //pHandle->m_pOverlaps = 0; + pHandle->m_clientObject = pOwner; + pHandle->m_collisionFilterGroup = collisionFilterGroup; + pHandle->m_collisionFilterMask = collisionFilterMask; + + // compute current limit of edge arrays + BP_FP_INT_TYPE limit = m_numHandles * 2; + + + // insert new edges just inside the max boundary edge + for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) + { + + m_pHandles[0].m_maxEdges[axis] += 2; + + m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; + + m_pEdges[axis][limit - 1].m_pos = min[axis]; + m_pEdges[axis][limit - 1].m_handle = handle; + + m_pEdges[axis][limit].m_pos = max[axis]; + m_pEdges[axis][limit].m_handle = handle; + + pHandle->m_minEdges[axis] = limit - 1; + pHandle->m_maxEdges[axis] = limit; + } + + // now sort the new edges to their correct position + sortMinDown(0, pHandle->m_minEdges[0], false); + sortMaxDown(0, pHandle->m_maxEdges[0], false); + sortMinDown(1, pHandle->m_minEdges[1], false); + sortMaxDown(1, pHandle->m_maxEdges[1], false); + sortMinDown(2, pHandle->m_minEdges[2], true); + sortMaxDown(2, pHandle->m_maxEdges[2], true); + + + return handle; +} + + +void btAxisSweep3::removeHandle(BP_FP_INT_TYPE handle) +{ + + Handle* pHandle = getHandle(handle); + + //explicitly remove the pairs containing the proxy + //we could do it also in the sortMinUp (passing true) + //todo: compare performance + removeOverlappingPairsContainingProxy(pHandle); + + + // compute current limit of edge arrays + int limit = m_numHandles * 2; + + int axis; + + for (axis = 0;axis<3;axis++) + { + m_pHandles[0].m_maxEdges[axis] -= 2; + } + + // remove the edges by sorting them up to the end of the list + for ( axis = 0; axis < 3; axis++) + { + Edge* pEdges = m_pEdges[axis]; + BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; + pEdges[max].m_pos = BP_HANDLE_SENTINEL; + + sortMaxUp(axis,max,false); + + + BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; + pEdges[i].m_pos = BP_HANDLE_SENTINEL; + + + sortMinUp(axis,i,false); + + pEdges[limit-1].m_handle = 0; + pEdges[limit-1].m_pos = BP_HANDLE_SENTINEL; + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis,false); +#endif //DEBUG_BROADPHASE + + + } + + + // free the handle + freeHandle(handle); + + +} + +extern int gOverlappingPairs; + + +void btAxisSweep3::refreshOverlappingPairs() +{ + +} +void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback) +{ + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + m_overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); + + //remove the 'invalid' ones +#ifdef USE_POPBACK_REMOVAL + while (m_invalidPair>0) + { + m_invalidPair--; + m_overlappingPairArray.pop_back(); + } +#else + m_overlappingPairArray.resize(m_overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; +#endif + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + cleanOverlappingPair(pair); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } +} + + +bool btAxisSweep3::testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + const Handle* pHandleA = static_cast(proxy0); + const Handle* pHandleB = static_cast(proxy1); + + //optimization 1: check the array index (memory address), instead of the m_pos + + for (int axis = 0; axis < 3; axis++) + { + if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || + pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) + { + return false; + } + } + return true; +} + +bool btAxisSweep3::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB) +{ + //optimization 1: check the array index (memory address), instead of the m_pos + + for (int axis = 0; axis < 3; axis++) + { + if (axis != ignoreAxis) + { + if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || + pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) + { + return false; + } + } + } + + //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization) + + /*for (int axis = 0; axis < 3; axis++) + { + if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos || + m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos) + { + return false; + } + } + */ + + return true; +} + +void btAxisSweep3::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax) +{ +// assert(bounds.IsFinite()); + //assert(bounds.HasVolume()); + + Handle* pHandle = getHandle(handle); + + // quantize the new bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // update changed edges + for (int axis = 0; axis < 3; axis++) + { + BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; + BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; + + int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; + int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; + + m_pEdges[axis][emin].m_pos = min[axis]; + m_pEdges[axis][emax].m_pos = max[axis]; + + // expand (only adds overlaps) + if (dmin < 0) + sortMinDown(axis, emin); + + if (dmax > 0) + sortMaxUp(axis, emax); + + // shrink (only removes overlaps) + if (dmin > 0) + sortMinUp(axis, emin); + + if (dmax < 0) + sortMaxDown(axis, emax); + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + } + + +} + + + + +// sorting a min edge downwards can only ever *add* overlaps +void btAxisSweep3::sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (pPrev->IsMax()) + { + // if previous edge is a maximum check the bounds and add an overlap if necessary + if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev)) + { + addOverlappingPair(pHandleEdge,pHandlePrev); + + //AddOverlap(pEdge->m_handle, pPrev->m_handle); + + } + + // update edge reference in other handle + pHandlePrev->m_maxEdges[axis]++; + } + else + pHandlePrev->m_minEdges[axis]++; + + pHandleEdge->m_minEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a min edge upwards can only ever *remove* overlaps +void btAxisSweep3::sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + if (pNext->IsMax()) + { + // if next edge is maximum remove any overlap between the two handles + if (updateOverlaps) + { + /* + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + btBroadphasePair tmpPair(*handle0,*handle1); + removeOverlappingPair(tmpPair); + */ + + } + + // update edge reference in other handle + pHandleNext->m_maxEdges[axis]--; + } + else + pHandleNext->m_minEdges[axis]--; + + pHandleEdge->m_minEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + + +} + +// sorting a max edge downwards can only ever *remove* overlaps +void btAxisSweep3::sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (!pPrev->IsMax()) + { + // if previous edge was a minimum remove any overlap between the two handles + if (updateOverlaps) + { + //this is done during the overlappingpairarray iteration/narrowphase collision + /* + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pPrev->m_handle); + btBroadphasePair* pair = findPair(handle0,handle1); + //assert(pair); + + if (pair) + { + removeOverlappingPair(*pair); + } + */ + + } + + // update edge reference in other handle + pHandlePrev->m_minEdges[axis]++;; + } + else + pHandlePrev->m_maxEdges[axis]++; + + pHandleEdge->m_maxEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a max edge upwards can only ever *add* overlaps +void btAxisSweep3::sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + if (!pNext->IsMax()) + { + // if next edge is a minimum check the bounds and add an overlap if necessary + if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext)) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + addOverlappingPair(handle0,handle1); + } + + // update edge reference in other handle + pHandleNext->m_minEdges[axis]--; + } + else + pHandleNext->m_maxEdges[axis]--; + + pHandleEdge->m_maxEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + +} diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h new file mode 100644 index 00000000000..57bbb368672 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h @@ -0,0 +1,138 @@ +//Bullet Continuous Collision Detection and Physics Library +//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +// +// btAxisSweep3.h +// +// Copyright (c) 2006 Simon Hobbs +// +// 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. + +#ifndef AXIS_SWEEP_3_H +#define AXIS_SWEEP_3_H + +#include "../../LinearMath/btPoint3.h" +#include "../../LinearMath/btVector3.h" +#include "btOverlappingPairCache.h" +#include "btBroadphaseProxy.h" + + +//Enable BP_USE_FIXEDPOINT_INT_32 if you need more then 32767 objects +//#define BP_USE_FIXEDPOINT_INT_32 1 + +#ifdef BP_USE_FIXEDPOINT_INT_32 + #define BP_FP_INT_TYPE unsigned int + #define BP_MAX_HANDLES 1500000 //arbitrary maximum number of handles + #define BP_HANDLE_SENTINEL 0x7fffffff + #define BP_HANDLE_MASK 0xfffffffe +#else + #define BP_FP_INT_TYPE unsigned short int + #define BP_MAX_HANDLES 32767 + #define BP_HANDLE_SENTINEL 0xffff + #define BP_HANDLE_MASK 0xfffe +#endif //BP_USE_FIXEDPOINT_INT_32 + +//#define DEBUG_BROADPHASE 1 + +/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. +/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using integer coordinates instead of floats. +/// The testOverlap check is optimized to check the array index, rather then the actual AABB coordinates/pos +class btAxisSweep3 : public btOverlappingPairCache +{ + +public: + + + class Edge + { + public: + BP_FP_INT_TYPE m_pos; // low bit is min/max + BP_FP_INT_TYPE m_handle; + + BP_FP_INT_TYPE IsMax() const {return m_pos & 1;} + }; + +public: + class Handle : public btBroadphaseProxy + { + public: + + // indexes into the edge arrays + BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12 + BP_FP_INT_TYPE m_handleId; + BP_FP_INT_TYPE m_pad; + + //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject + + inline void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} + inline BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} + }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry + + +private: + btPoint3 m_worldAabbMin; // overall system bounds + btPoint3 m_worldAabbMax; // overall system bounds + + btVector3 m_quantize; // scaling factor for quantization + + BP_FP_INT_TYPE m_numHandles; // number of active handles + int m_maxHandles; // max number of handles + Handle* m_pHandles; // handles pool + BP_FP_INT_TYPE m_firstFreeHandle; // free handles list + + Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries) + + int m_invalidPair; + + // allocation/deallocation + BP_FP_INT_TYPE allocHandle(); + void freeHandle(BP_FP_INT_TYPE handle); + + + bool testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB); + +#ifdef DEBUG_BROADPHASE + void debugPrintAxis(int axis,bool checkCardinality=true); +#endif //DEBUG_BROADPHASE + + //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB); + //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB); + + void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const; + + void sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); + void sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); + void sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); + void sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); + +public: + btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles = 16384); + virtual ~btAxisSweep3(); + + virtual void refreshOverlappingPairs(); + + BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask); + void removeHandle(BP_FP_INT_TYPE handle); + void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax); + inline Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} + + void processAllOverlappingPairs(btOverlapCallback* callback); + + //Broadphase Interface + virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask); + virtual void destroyProxy(btBroadphaseProxy* proxy); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); + bool testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + +}; + +#endif + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h new file mode 100644 index 00000000000..b6ace03c07a --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h @@ -0,0 +1,40 @@ +/* +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. +*/ + +#ifndef BROADPHASE_INTERFACE_H +#define BROADPHASE_INTERFACE_H + + + +struct btDispatcherInfo; +class btDispatcher; +struct btBroadphaseProxy; +#include "../../LinearMath/btVector3.h" + +///BroadphaseInterface for aabb-overlapping object pairs +class btBroadphaseInterface +{ +public: + virtual ~btBroadphaseInterface() {} + + virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) =0; + virtual void destroyProxy(btBroadphaseProxy* proxy)=0; + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)=0; + virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy)=0; + + +}; + +#endif //BROADPHASE_INTERFACE_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp new file mode 100644 index 00000000000..f4d7341f8dd --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp @@ -0,0 +1,17 @@ +/* +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. +*/ + +#include "btBroadphaseProxy.h" + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h new file mode 100644 index 00000000000..40d9748ffa9 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -0,0 +1,204 @@ +/* +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. +*/ + +#ifndef BROADPHASE_PROXY_H +#define BROADPHASE_PROXY_H + +#include "../../LinearMath/btScalar.h" //for SIMD_FORCE_INLINE + + +/// btDispatcher uses these types +/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave +/// to facilitate type checking +enum BroadphaseNativeTypes +{ +// polyhedral convex shapes + BOX_SHAPE_PROXYTYPE, + TRIANGLE_SHAPE_PROXYTYPE, + TETRAHEDRAL_SHAPE_PROXYTYPE, + CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE, + CONVEX_HULL_SHAPE_PROXYTYPE, +//implicit convex shapes +IMPLICIT_CONVEX_SHAPES_START_HERE, + SPHERE_SHAPE_PROXYTYPE, + MULTI_SPHERE_SHAPE_PROXYTYPE, + CAPSULE_SHAPE_PROXYTYPE, + CONE_SHAPE_PROXYTYPE, + CONVEX_SHAPE_PROXYTYPE, + CYLINDER_SHAPE_PROXYTYPE, + MINKOWSKI_SUM_SHAPE_PROXYTYPE, + MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, +//concave shapes +CONCAVE_SHAPES_START_HERE, + //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy! + TRIANGLE_MESH_SHAPE_PROXYTYPE, + ///used for demo integration FAST/Swift collision library and Bullet + FAST_CONCAVE_MESH_PROXYTYPE, + //terrain + TERRAIN_SHAPE_PROXYTYPE, +///Used for GIMPACT Trimesh integration + GIMPACT_SHAPE_PROXYTYPE, + + EMPTY_SHAPE_PROXYTYPE, + STATIC_PLANE_PROXYTYPE, +CONCAVE_SHAPES_END_HERE, + + COMPOUND_SHAPE_PROXYTYPE, + + MAX_BROADPHASE_COLLISION_TYPES +}; + + +///btBroadphaseProxy +struct btBroadphaseProxy +{ + + ///optional filtering to cull potential collisions + enum CollisionFilterGroups + { + DefaultFilter = 1, + StaticFilter = 2, + KinematicFilter = 4, + DebrisFilter = 8, + SensorTrigger = 16, + AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger + }; + + //Usually the client btCollisionObject or Rigidbody class + void* m_clientObject; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + + //used for memory pools + btBroadphaseProxy() :m_clientObject(0){} + + btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) + :m_clientObject(userPtr), + m_collisionFilterGroup(collisionFilterGroup), + m_collisionFilterMask(collisionFilterMask) + { + } + + static inline bool isPolyhedral(int proxyType) + { + return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE); + } + + static inline bool isConvex(int proxyType) + { + return (proxyType < CONCAVE_SHAPES_START_HERE); + } + + static inline bool isConcave(int proxyType) + { + return ((proxyType > CONCAVE_SHAPES_START_HERE) && + (proxyType < CONCAVE_SHAPES_END_HERE)); + } + static inline bool isCompound(int proxyType) + { + return (proxyType == COMPOUND_SHAPE_PROXYTYPE); + } + static inline bool isInfinite(int proxyType) + { + return (proxyType == STATIC_PLANE_PROXYTYPE); + } + +} +; + +class btCollisionAlgorithm; + +struct btBroadphaseProxy; + + + +/// contains a pair of aabb-overlapping objects +struct btBroadphasePair +{ + btBroadphasePair () + : + m_pProxy0(0), + m_pProxy1(0), + m_algorithm(0), + m_userInfo(0) + { + } + + btBroadphasePair(const btBroadphasePair& other) + : m_pProxy0(other.m_pProxy0), + m_pProxy1(other.m_pProxy1), + m_algorithm(other.m_algorithm), + m_userInfo(other.m_userInfo) + { + } + btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1) + { + + //keep them sorted, so the std::set operations work + if (&proxy0 < &proxy1) + { + m_pProxy0 = &proxy0; + m_pProxy1 = &proxy1; + } + else + { + m_pProxy0 = &proxy1; + m_pProxy1 = &proxy0; + } + + m_algorithm = 0; + m_userInfo = 0; + + } + + btBroadphaseProxy* m_pProxy0; + btBroadphaseProxy* m_pProxy1; + + mutable btCollisionAlgorithm* m_algorithm; + mutable void* m_userInfo; + +}; + +/* +//comparison for set operation, see Solid DT_Encounter +SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b) +{ + return a.m_pProxy0 < b.m_pProxy0 || + (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1); +} +*/ + + +class btBroadphasePairSortPredicate +{ + public: + + bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) + { + return a.m_pProxy0 > b.m_pProxy0 || + (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 > b.m_pProxy1) || + (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm); + } +}; + + +SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b) +{ + return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1); +} + + +#endif //BROADPHASE_PROXY_H + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp new file mode 100644 index 00000000000..2ad0c86d8a2 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp @@ -0,0 +1,23 @@ +/* +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. +*/ + +#include "btCollisionAlgorithm.h" +#include "btDispatcher.h" + +btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) +{ + m_dispatcher = ci.m_dispatcher; +} + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h new file mode 100644 index 00000000000..55cec386a7b --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h @@ -0,0 +1,77 @@ +/* +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. +*/ + +#ifndef COLLISION_ALGORITHM_H +#define COLLISION_ALGORITHM_H + +#include "../../LinearMath/btScalar.h" + +struct btBroadphaseProxy; +class btDispatcher; +class btManifoldResult; +class btCollisionObject; +struct btDispatcherInfo; +class btPersistentManifold; + + +struct btCollisionAlgorithmConstructionInfo +{ + btCollisionAlgorithmConstructionInfo() + :m_dispatcher(0), + m_manifold(0) + { + } + btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp) + :m_dispatcher(dispatcher) + { + (void)temp; + } + + btDispatcher* m_dispatcher; + btPersistentManifold* m_manifold; + + int getDispatcherId(); + +}; + + +///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher. +///It is persistent over frames +class btCollisionAlgorithm +{ + +protected: + + btDispatcher* m_dispatcher; + +protected: + int getDispatcherId(); + +public: + + btCollisionAlgorithm() {}; + + btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci); + + virtual ~btCollisionAlgorithm() {}; + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; + +}; + + +#endif //COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp new file mode 100644 index 00000000000..20768225b3a --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.cpp @@ -0,0 +1,22 @@ +/* +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. +*/ + +#include "btDispatcher.h" + +btDispatcher::~btDispatcher() +{ + +} + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h new file mode 100644 index 00000000000..3d958cc8fef --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h @@ -0,0 +1,93 @@ +/* +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. +*/ + +#ifndef _DISPATCHER_H +#define _DISPATCHER_H + +#include "../../LinearMath/btScalar.h" + +class btCollisionAlgorithm; +struct btBroadphaseProxy; +class btRigidBody; +class btCollisionObject; +class btOverlappingPairCache; + + +class btPersistentManifold; +class btStackAlloc; + +struct btDispatcherInfo +{ + enum DispatchFunc + { + DISPATCH_DISCRETE = 1, + DISPATCH_CONTINUOUS + }; + btDispatcherInfo() + :m_timeStep(btScalar(0.)), + m_stepCount(0), + m_dispatchFunc(DISPATCH_DISCRETE), + m_timeOfImpact(btScalar(1.)), + m_useContinuous(false), + m_debugDraw(0), + m_enableSatConvex(false), + m_enableSPU(false), + m_stackAllocator(0) + { + + } + btScalar m_timeStep; + int m_stepCount; + int m_dispatchFunc; + btScalar m_timeOfImpact; + bool m_useContinuous; + class btIDebugDraw* m_debugDraw; + bool m_enableSatConvex; + bool m_enableSPU; + btStackAlloc* m_stackAllocator; + +}; + +/// btDispatcher can be used in combination with broadphase to dispatch overlapping pairs. +/// For example for pairwise collision detection or user callbacks (game logic). +class btDispatcher +{ + + +public: + virtual ~btDispatcher() ; + + virtual btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold=0) = 0; + + virtual btPersistentManifold* getNewManifold(void* body0,void* body1)=0; + + virtual void releaseManifold(btPersistentManifold* manifold)=0; + + virtual void clearManifold(btPersistentManifold* manifold)=0; + + virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1) = 0; + + virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0; + + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)=0; + + virtual int getNumManifolds() const = 0; + + virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0; + +}; + + +#endif //_DISPATCHER_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp new file mode 100644 index 00000000000..60f0a41a9d7 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp @@ -0,0 +1,196 @@ + +/* +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. +*/ + + + +#include "btOverlappingPairCache.h" + +#include "btDispatcher.h" +#include "btCollisionAlgorithm.h" + +int gOverlappingPairs = 0; + +btOverlappingPairCache::btOverlappingPairCache(): +m_blockedForChanges(false), +m_overlapFilterCallback(0) +//m_NumOverlapBroadphasePair(0) +{ +} + + +btOverlappingPairCache::~btOverlappingPairCache() +{ + //todo/test: show we erase/delete data, or is it automatic +} + + +void btOverlappingPairCache::removeOverlappingPair(btBroadphasePair& findPair) +{ + + int findIndex = m_overlappingPairArray.findLinearSearch(findPair); + if (findIndex < m_overlappingPairArray.size()) + { + gOverlappingPairs--; + btBroadphasePair& pair = m_overlappingPairArray[findIndex]; + cleanOverlappingPair(pair); + + m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.size()-1); + m_overlappingPairArray.pop_back(); + } +} + + +void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair) +{ + if (pair.m_algorithm) + { + { + delete pair.m_algorithm;; + pair.m_algorithm=0; + } + } +} + + + + + +void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + //don't add overlap with own + assert(proxy0 != proxy1); + + if (!needsBroadphaseCollision(proxy0,proxy1)) + return; + + + btBroadphasePair pair(*proxy0,*proxy1); + + m_overlappingPairArray.push_back(pair); + gOverlappingPairs++; + +} + +///this findPair becomes really slow. Either sort the list to speedup the query, or +///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed. +///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address) +///Also we can use a 2D bitmap, which can be useful for a future GPU implementation + btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + btBroadphasePair tmpPair(*proxy0,*proxy1); + int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair); + + if (findIndex < m_overlappingPairArray.size()) + { + //assert(it != m_overlappingPairSet.end()); + btBroadphasePair* pair = &m_overlappingPairArray[findIndex]; + return pair; + } + return 0; +} + + + + + +void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy) +{ + + class CleanPairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_cleanProxy; + btOverlappingPairCache* m_pairCache; + + public: + CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache) + :m_cleanProxy(cleanProxy), + m_pairCache(pairCache) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + if ((pair.m_pProxy0 == m_cleanProxy) || + (pair.m_pProxy1 == m_cleanProxy)) + { + m_pairCache->cleanOverlappingPair(pair); + } + return false; + } + + }; + + CleanPairCallback cleanPairs(proxy,this); + + processAllOverlappingPairs(&cleanPairs); + +} + + + +void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy) +{ + + class RemovePairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_obsoleteProxy; + + public: + RemovePairCallback(btBroadphaseProxy* obsoleteProxy) + :m_obsoleteProxy(obsoleteProxy) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + return ((pair.m_pProxy0 == m_obsoleteProxy) || + (pair.m_pProxy1 == m_obsoleteProxy)); + } + + }; + + + RemovePairCallback removeCallback(proxy); + + processAllOverlappingPairs(&removeCallback); +} + + + +void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback) +{ + + int i; + + for (i=0;iprocessOverlap(*pair)) + { + cleanOverlappingPair(*pair); + + m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + m_overlappingPairArray.pop_back(); + gOverlappingPairs--; + } else + { + i++; + } + } +} + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h new file mode 100644 index 00000000000..a81fe3264df --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -0,0 +1,120 @@ + +/* +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. +*/ + +#ifndef OVERLAPPING_PAIR_CACHE_H +#define OVERLAPPING_PAIR_CACHE_H + + +#include "btBroadphaseInterface.h" +#include "btBroadphaseProxy.h" +#include "../../LinearMath/btPoint3.h" +#include "../../LinearMath/btAlignedObjectArray.h" + + +struct btOverlapCallback +{ + virtual ~btOverlapCallback() + {} + //return true for deletion of the pair + virtual bool processOverlap(btBroadphasePair& pair) = 0; +}; + +struct btOverlapFilterCallback +{ + virtual ~btOverlapFilterCallback() + {} + // return true when pairs need collision + virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; +}; + +///btOverlappingPairCache maintains the objects with overlapping AABB +///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase +class btOverlappingPairCache : public btBroadphaseInterface +{ + protected: + //avoid brute-force finding all the time + btAlignedObjectArray m_overlappingPairArray; + + //during the dispatch, check that user doesn't destroy/create proxy + bool m_blockedForChanges; + + //if set, use the callback instead of the built in filter in needBroadphaseCollision + btOverlapFilterCallback* m_overlapFilterCallback; + public: + + btOverlappingPairCache(); + virtual ~btOverlappingPairCache(); + + virtual void processAllOverlappingPairs(btOverlapCallback*); + + void removeOverlappingPair(btBroadphasePair& pair); + + void cleanOverlappingPair(btBroadphasePair& pair); + + void addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + + void cleanProxyFromPairs(btBroadphaseProxy* proxy); + + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy); + + + inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const + { + if (m_overlapFilterCallback) + return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); + + bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; + collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + + return collides; + } + + + + virtual void refreshOverlappingPairs() =0; + + btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + + int getNumOverlappingPairs() const + { + return m_overlappingPairArray.size(); + } + + btOverlapFilterCallback* getOverlapFilterCallback() + { + return m_overlapFilterCallback; + } + + void setOverlapFilterCallback(btOverlapFilterCallback* callback) + { + m_overlapFilterCallback = callback; + } + +}; +#endif //OVERLAPPING_PAIR_CACHE_H + + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp new file mode 100644 index 00000000000..30bcbe0c5f1 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp @@ -0,0 +1,222 @@ +/* +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. +*/ + +#include "btSimpleBroadphase.h" +#include +#include + +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include + + +void btSimpleBroadphase::validate() +{ + for (int i=0;i=0;i--) + { + BP_Proxy* proxy = m_pProxies[i]; + destroyProxy(proxy); + } + */ +} + + +btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask) +{ + if (m_numProxies >= m_maxProxies) + { + assert(0); + return 0; //should never happen, but don't let the game crash ;-) + } + assert(min[0]<= max[0] && min[1]<= max[1] && min[2]<= max[2]); + + int freeIndex= m_freeProxies[m_firstFreeProxy]; + btSimpleBroadphaseProxy* proxy = new (&m_proxies[freeIndex])btSimpleBroadphaseProxy(min,max,shapeType,userPtr,collisionFilterGroup,collisionFilterMask); + m_firstFreeProxy++; + + btSimpleBroadphaseProxy* proxy1 = &m_proxies[0]; + + int index = int(proxy - proxy1); + btAssert(index == freeIndex); + + m_pProxies[m_numProxies] = proxy; + m_numProxies++; + //validate(); + + return proxy; +} + +class RemovingOverlapCallback : public btOverlapCallback +{ +protected: + virtual bool processOverlap(btBroadphasePair& pair) + { + (void)pair; + btAssert(0); + return false; + } +}; + +class RemovePairContainingProxy +{ + + btBroadphaseProxy* m_targetProxy; + public: + virtual ~RemovePairContainingProxy() + { + } +protected: + virtual bool processOverlap(btBroadphasePair& pair) + { + btSimpleBroadphaseProxy* proxy0 = static_cast(pair.m_pProxy0); + btSimpleBroadphaseProxy* proxy1 = static_cast(pair.m_pProxy1); + + return ((m_targetProxy == proxy0 || m_targetProxy == proxy1)); + }; +}; + +void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg) +{ + + int i; + + btSimpleBroadphaseProxy* proxy0 = static_cast(proxyOrg); + btSimpleBroadphaseProxy* proxy1 = &m_proxies[0]; + + int index = int(proxy0 - proxy1); + btAssert (index < m_maxProxies); + m_freeProxies[--m_firstFreeProxy] = index; + + removeOverlappingPairsContainingProxy(proxyOrg); + + for (i=0;im_min = aabbMin; + sbp->m_max = aabbMax; +} + + + + + + + + + +bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1) +{ + return proxy0->m_min[0] <= proxy1->m_max[0] && proxy1->m_min[0] <= proxy0->m_max[0] && + proxy0->m_min[1] <= proxy1->m_max[1] && proxy1->m_min[1] <= proxy0->m_max[1] && + proxy0->m_min[2] <= proxy1->m_max[2] && proxy1->m_min[2] <= proxy0->m_max[2]; + +} + + + +//then remove non-overlapping ones +class CheckOverlapCallback : public btOverlapCallback +{ +public: + virtual bool processOverlap(btBroadphasePair& pair) + { + return (!btSimpleBroadphase::aabbOverlap(static_cast(pair.m_pProxy0),static_cast(pair.m_pProxy1))); + } +}; + +void btSimpleBroadphase::refreshOverlappingPairs() +{ + //first check for new overlapping pairs + int i,j; + + for (i=0;i(proxy); + return proxy0; + } + + + void validate(); + +protected: + + + virtual void refreshOverlappingPairs(); +public: + btSimpleBroadphase(int maxProxies=16384); + virtual ~btSimpleBroadphase(); + + + static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1); + + + virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask); + + + virtual void destroyProxy(btBroadphaseProxy* proxy); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); + + + + + + +}; + + + +#endif //SIMPLE_BROADPHASE_H + diff --git a/extern/bullet2/src/BulletCollision/CMakeLists.txt b/extern/bullet2/src/BulletCollision/CMakeLists.txt new file mode 100644 index 00000000000..e565bf7edea --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CMakeLists.txt @@ -0,0 +1,60 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src } +) + +ADD_LIBRARY(LibBulletCollision + BroadphaseCollision/btAxisSweep3.cpp + BroadphaseCollision/btBroadphaseProxy.cpp + BroadphaseCollision/btCollisionAlgorithm.cpp + BroadphaseCollision/btDispatcher.cpp + BroadphaseCollision/btOverlappingPairCache.cpp + BroadphaseCollision/btSimpleBroadphase.cpp + CollisionDispatch/btCollisionDispatcher.cpp + CollisionDispatch/btCollisionObject.cpp + CollisionDispatch/btCollisionWorld.cpp + CollisionDispatch/btCompoundCollisionAlgorithm.cpp + CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp + CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp + CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp + CollisionDispatch/btConvexConvexAlgorithm.cpp + CollisionDispatch/btEmptyCollisionAlgorithm.cpp + CollisionDispatch/btManifoldResult.cpp + CollisionDispatch/btSimulationIslandManager.cpp + CollisionDispatch/btUnionFind.cpp + CollisionShapes/btBoxShape.cpp + CollisionShapes/btBvhTriangleMeshShape.cpp + CollisionShapes/btCollisionShape.cpp + CollisionShapes/btCompoundShape.cpp + CollisionShapes/btConcaveShape.cpp + CollisionShapes/btConeShape.cpp + CollisionShapes/btConvexHullShape.cpp + CollisionShapes/btConvexShape.cpp + CollisionShapes/btConvexTriangleMeshShape.cpp + CollisionShapes/btCylinderShape.cpp + CollisionShapes/btEmptyShape.cpp + CollisionShapes/btMinkowskiSumShape.cpp + CollisionShapes/btMultiSphereShape.cpp + CollisionShapes/btOptimizedBvh.cpp + CollisionShapes/btPolyhedralConvexShape.cpp + CollisionShapes/btTetrahedronShape.cpp + CollisionShapes/btSphereShape.cpp + CollisionShapes/btStaticPlaneShape.cpp + CollisionShapes/btStridingMeshInterface.cpp + CollisionShapes/btTriangleCallback.cpp + CollisionShapes/btTriangleBuffer.cpp + CollisionShapes/btTriangleIndexVertexArray.cpp + CollisionShapes/btTriangleMesh.cpp + CollisionShapes/btTriangleMeshShape.cpp + NarrowPhaseCollision/btContinuousConvexCollision.cpp + NarrowPhaseCollision/btGjkEpa.cpp + NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp + NarrowPhaseCollision/btConvexCast.cpp + NarrowPhaseCollision/btGjkConvexCast.cpp + NarrowPhaseCollision/btGjkPairDetector.cpp + NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp + NarrowPhaseCollision/btPersistentManifold.cpp + NarrowPhaseCollision/btRaycastCallback.cpp + NarrowPhaseCollision/btSubSimplexConvexCast.cpp + NarrowPhaseCollision/btVoronoiSimplexSolver.cpp +) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp new file mode 100644 index 00000000000..81133670f0c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp @@ -0,0 +1,200 @@ +/* +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. +*/ + +#include "LinearMath/btScalar.h" +#include "SphereTriangleDetector.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + + +SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle) +:m_sphere(sphere), +m_triangle(triangle) +{ + +} + +void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) +{ + + (void)debugDraw; + const btTransform& transformA = input.m_transformA; + const btTransform& transformB = input.m_transformB; + + btVector3 point,normal; + btScalar timeOfImpact = btScalar(1.); + btScalar depth = btScalar(0.); +// output.m_distance = btScalar(1e30); + //move sphere into triangle space + btTransform sphereInTr = transformB.inverseTimes(transformA); + + if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact)) + { + output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth); + } + +} + +#define MAX_OVERLAP btScalar(0.) + + + +// See also geometrictools.com +// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv +btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) { + btVector3 diff = p - from; + btVector3 v = to - from; + btScalar t = v.dot(diff); + + if (t > 0) { + btScalar dotVV = v.dot(v); + if (t < dotVV) { + t /= dotVV; + diff -= t*v; + } else { + t = 1; + diff -= v; + } + } else + t = 0; + + nearest = from + t*v; + return diff.dot(diff); +} + +bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal) { + btVector3 lp(p); + btVector3 lnormal(normal); + + return pointInTriangle(vertices, lnormal, &lp); +} + +///combined discrete/continuous sphere-triangle +bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact) +{ + + const btVector3* vertices = &m_triangle->getVertexPtr(0); + const btVector3& c = sphereCenter; + btScalar r = m_sphere->getRadius(); + + btVector3 delta (0,0,0); + + btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]); + normal.normalize(); + btVector3 p1ToCentre = c - vertices[0]; + btScalar distanceFromPlane = p1ToCentre.dot(normal); + + if (distanceFromPlane < btScalar(0.)) + { + //triangle facing the other way + + distanceFromPlane *= btScalar(-1.); + normal *= btScalar(-1.); + } + + ///todo: move this gContactBreakingThreshold into a proper structure + extern btScalar gContactBreakingThreshold; + + btScalar contactMargin = gContactBreakingThreshold; + bool isInsideContactPlane = distanceFromPlane < r + contactMargin; + bool isInsideShellPlane = distanceFromPlane < r; + + btScalar deltaDotNormal = delta.dot(normal); + if (!isInsideShellPlane && deltaDotNormal >= btScalar(0.0)) + return false; + + // Check for contact / intersection + bool hasContact = false; + btVector3 contactPoint; + if (isInsideContactPlane) { + if (facecontains(c,vertices,normal)) { + // Inside the contact wedge - touches a point on the shell plane + hasContact = true; + contactPoint = c - normal*distanceFromPlane; + } else { + // Could be inside one of the contact capsules + btScalar contactCapsuleRadiusSqr = (r + contactMargin) * (r + contactMargin); + btVector3 nearestOnEdge; + for (int i = 0; i < m_triangle->getNumEdges(); i++) { + + btPoint3 pa; + btPoint3 pb; + + m_triangle->getEdge(i,pa,pb); + + btScalar distanceSqr = SegmentSqrDistance(pa,pb,c, nearestOnEdge); + if (distanceSqr < contactCapsuleRadiusSqr) { + // Yep, we're inside a capsule + hasContact = true; + contactPoint = nearestOnEdge; + } + + } + } + } + + if (hasContact) { + btVector3 contactToCentre = c - contactPoint; + btScalar distanceSqr = contactToCentre.length2(); + if (distanceSqr < (r - MAX_OVERLAP)*(r - MAX_OVERLAP)) { + btScalar distance = btSqrt(distanceSqr); + resultNormal = contactToCentre; + resultNormal.normalize(); + point = contactPoint; + depth = -(r-distance); + return true; + } + + if (delta.dot(contactToCentre) >= btScalar(0.0)) + return false; + + // Moving towards the contact point -> collision + point = contactPoint; + timeOfImpact = btScalar(0.0); + return true; + } + + return false; +} + + +bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ) +{ + const btVector3* p1 = &vertices[0]; + const btVector3* p2 = &vertices[1]; + const btVector3* p3 = &vertices[2]; + + btVector3 edge1( *p2 - *p1 ); + btVector3 edge2( *p3 - *p2 ); + btVector3 edge3( *p1 - *p3 ); + + btVector3 p1_to_p( *p - *p1 ); + btVector3 p2_to_p( *p - *p2 ); + btVector3 p3_to_p( *p - *p3 ); + + btVector3 edge1_normal( edge1.cross(normal)); + btVector3 edge2_normal( edge2.cross(normal)); + btVector3 edge3_normal( edge3.cross(normal)); + + btScalar r1, r2, r3; + r1 = edge1_normal.dot( p1_to_p ); + r2 = edge2_normal.dot( p2_to_p ); + r3 = edge3_normal.dot( p3_to_p ); + if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) || + ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) ) + return true; + return false; + +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h new file mode 100644 index 00000000000..b32806a6846 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h @@ -0,0 +1,49 @@ +/* +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. +*/ + +#ifndef SPHERE_TRIANGLE_DETECTOR_H +#define SPHERE_TRIANGLE_DETECTOR_H + +#include "../NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "../../LinearMath/btPoint3.h" + + +class btSphereShape; +class btTriangleShape; + + + +/// sphere-triangle to match the btDiscreteCollisionDetectorInterface +struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface +{ + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw); + + SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle); + + virtual ~SphereTriangleDetector() {}; + +private: + + bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact); + bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p ); + bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal); + + btSphereShape* m_sphere; + btTriangleShape* m_triangle; + + +}; +#endif //SPHERE_TRIANGLE_DETECTOR_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h new file mode 100644 index 00000000000..d51a59af7f0 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h @@ -0,0 +1,46 @@ +/* +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. +*/ + +#ifndef COLLISION_CREATE_FUNC +#define COLLISION_CREATE_FUNC + +#include "../../LinearMath/btAlignedObjectArray.h" +typedef btAlignedObjectArray btCollisionObjectArray; +class btCollisionAlgorithm; +class btCollisionObject; + +struct btCollisionAlgorithmConstructionInfo; + +///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm +struct btCollisionAlgorithmCreateFunc +{ + bool m_swapped; + + btCollisionAlgorithmCreateFunc() + :m_swapped(false) + { + } + virtual ~btCollisionAlgorithmCreateFunc(){}; + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , btCollisionObject* body0,btCollisionObject* body1) + { + + (void)body0; + (void)body1; + return 0; + } +}; +#endif //COLLISION_CREATE_FUNC + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp new file mode 100644 index 00000000000..b535fac6563 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @@ -0,0 +1,367 @@ +/* +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. +*/ + + + +#include "btCollisionDispatcher.h" + + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + +int gNumManifold = 0; + +#include + + +btCollisionDispatcher::btCollisionDispatcher(bool noDefaultAlgorithms): +m_count(0), +m_useIslands(true), +m_convexConvexCreateFunc(0), +m_convexConcaveCreateFunc(0), +m_swappedConvexConcaveCreateFunc(0), +m_compoundCreateFunc(0), +m_swappedCompoundCreateFunc(0), +m_emptyCreateFunc(0) +{ + (void)noDefaultAlgorithms; + int i; + + setNearCallback(defaultNearCallback); + + m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc; + for (i=0;iclearManifold(); +} + + +void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) +{ + + gNumManifold--; + + //printf("releaseManifold: gNumManifold %d\n",gNumManifold); + clearManifold(manifold); + + ///todo: this can be improved a lot, linear search might be slow part! + int findIndex = m_manifoldsPtr.findLinearSearch(manifold); + if (findIndex < m_manifoldsPtr.size()) + { + m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); + m_manifoldsPtr.pop_back(); + delete manifold; + } + +} + + + +btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) +{ + +#ifdef USE_DISPATCH_REGISTRY_ARRAY + + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher = this; + ci.m_manifold = sharedManifold; + btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()] + ->CreateCollisionAlgorithm(ci,body0,body1); +#else + btCollisionAlgorithm* algo = internalFindAlgorithm(body0,body1); +#endif //USE_DISPATCH_REGISTRY_ARRAY + return algo; +} + + +#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION + +btCollisionAlgorithmCreateFunc* btCollisionDispatcher::internalFindCreateFunc(int proxyType0,int proxyType1) +{ + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_convexConvexCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_convexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) + { + return m_swappedConvexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isCompound(proxyType0)) + { + return m_compoundCreateFunc; + } else + { + if (btBroadphaseProxy::isCompound(proxyType1)) + { + return m_swappedCompoundCreateFunc; + } + } + + //failed to find an algorithm + return m_emptyCreateFunc; +} + +#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION + + +#ifndef USE_DISPATCH_REGISTRY_ARRAY + +btCollisionAlgorithm* btCollisionDispatcher::internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) +{ + m_count++; + + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher = this; + + if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConvex() ) + { + return new btConvexConvexAlgorithm(sharedManifold,ci,body0,body1); + } + + if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConcave()) + { + return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); + } + + if (body1->getCollisionShape()->isConvex() && body0->getCollisionShape()->isConcave()) + { + return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); + } + + if (body0->getCollisionShape()->isCompound()) + { + return new btCompoundCollisionAlgorithm(ci,body0,body1,false); + } else + { + if (body1->getCollisionShape()->isCompound()) + { + return new btCompoundCollisionAlgorithm(ci,body0,body1,true); + } + } + + //failed to find an algorithm + return new btEmptyAlgorithm(ci); + +} +#endif //USE_DISPATCH_REGISTRY_ARRAY + +bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1) +{ + //here you can do filtering + bool hasResponse = + (body0->hasContactResponse() && body1->hasContactResponse()); + //no response between two static/kinematic bodies: + hasResponse = hasResponse && + ((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject())); + return hasResponse; +} + +bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1) +{ + assert(body0); + assert(body1); + + bool needsCollision = true; + + //broadphase filtering already deals with this + if ((body0->isStaticObject() || body0->isKinematicObject()) && + (body1->isStaticObject() || body1->isKinematicObject())) + { + printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); + } + + if ((!body0->isActive()) && (!body1->isActive())) + needsCollision = false; + else if (!body0->checkCollideWith(body1)) + needsCollision = false; + + return needsCollision ; + +} + + + +///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc) +///this is useful for the collision dispatcher. +class btCollisionPairCallback : public btOverlapCallback +{ + btDispatcherInfo& m_dispatchInfo; + btCollisionDispatcher* m_dispatcher; + +public: + + btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) + :m_dispatchInfo(dispatchInfo), + m_dispatcher(dispatcher) + { + } + + btCollisionPairCallback& operator=(btCollisionPairCallback& other) + { + m_dispatchInfo = other.m_dispatchInfo; + m_dispatcher = other.m_dispatcher; + return *this; + } + + virtual ~btCollisionPairCallback() {} + + + virtual bool processOverlap(btBroadphasePair& pair) + { + (*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo); + + return false; + } +}; + + +void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo) +{ + //m_blockedForChanges = true; + + btCollisionPairCallback collisionCallback(dispatchInfo,this); + + pairCache->processAllOverlappingPairs(&collisionCallback); + + //m_blockedForChanges = false; + +} + + + + +//by default, Bullet will use this near callback +void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) +{ + btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + + if (dispatcher.needsCollision(colObj0,colObj1)) + { + //dispatcher will keep algorithms persistent in the collision pair + if (!collisionPair.m_algorithm) + { + collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1); + } + + if (collisionPair.m_algorithm) + { + btManifoldResult contactPointResult(colObj0,colObj1); + + if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE) + { + //discrete collision detection query + collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult); + } else + { + //continuous collision detection query, time of impact (toi) + btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult); + if (dispatchInfo.m_timeOfImpact > toi) + dispatchInfo.m_timeOfImpact = toi; + + } + } + } + +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h new file mode 100644 index 00000000000..ca5aba8f01c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h @@ -0,0 +1,135 @@ +/* +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. +*/ + +#ifndef COLLISION__DISPATCHER_H +#define COLLISION__DISPATCHER_H + +#include "../BroadphaseCollision/btDispatcher.h" +#include "../NarrowPhaseCollision/btPersistentManifold.h" + +#include "../CollisionDispatch/btManifoldResult.h" + +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../../LinearMath/btAlignedObjectArray.h" + +class btIDebugDraw; +class btOverlappingPairCache; + + +#include "btCollisionCreateFunc.h" + +#define USE_DISPATCH_REGISTRY_ARRAY 1 + +class btCollisionDispatcher; +///user can override this nearcallback for collision filtering and more finegrained control over collision detection +typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); + + +///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. +///Time of Impact, Closest Points and Penetration Depth. +class btCollisionDispatcher : public btDispatcher +{ + int m_count; + + btAlignedObjectArray m_manifoldsPtr; + + bool m_useIslands; + + btManifoldResult m_defaultManifoldResult; + + btNearCallback m_nearCallback; + + btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; + + btCollisionAlgorithmCreateFunc* internalFindCreateFunc(int proxyType0,int proxyType1); + + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; + +#ifndef USE_DISPATCH_REGISTRY_ARRAY + btCollisionAlgorithm* internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0); +#endif //USE_DISPATCH_REGISTRY_ARRAY + +public: + + ///registerCollisionCreateFunc allows registration of custom/alternative collision create functions + void registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc); + + int getNumManifolds() const + { + return int( m_manifoldsPtr.size()); + } + + btPersistentManifold** getInternalManifoldPointer() + { + return &m_manifoldsPtr[0]; + } + + btPersistentManifold* getManifoldByIndexInternal(int index) + { + return m_manifoldsPtr[index]; + } + + const btPersistentManifold* getManifoldByIndexInternal(int index) const + { + return m_manifoldsPtr[index]; + } + + ///the default constructor creates/register default collision algorithms, for convex, compound and concave shape support + btCollisionDispatcher (); + + ///a special constructor that doesn't create/register the default collision algorithms + btCollisionDispatcher(bool noDefaultAlgorithms); + + virtual ~btCollisionDispatcher(); + + virtual btPersistentManifold* getNewManifold(void* b0,void* b1); + + virtual void releaseManifold(btPersistentManifold* manifold); + + + virtual void clearManifold(btPersistentManifold* manifold); + + + btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0); + + virtual bool needsCollision(btCollisionObject* body0,btCollisionObject* body1); + + virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1); + + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo); + + void setNearCallback(btNearCallback nearCallback) + { + m_nearCallback = nearCallback; + } + + btNearCallback getNearCallback() const + { + return m_nearCallback; + } + + //by default, Bullet will use this near callback + static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); + +}; + +#endif //COLLISION__DISPATCHER_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp new file mode 100644 index 00000000000..d4c0a4e8cb3 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp @@ -0,0 +1,57 @@ +/* +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. +*/ + +#include "btCollisionObject.h" + +btCollisionObject::btCollisionObject() + : m_broadphaseHandle(0), + m_collisionShape(0), + m_collisionFlags(0), + m_activationState1(1), + m_deactivationTime(btScalar(0.)), + m_userObjectPointer(0), + m_hitFraction(btScalar(1.)), + m_ccdSweptSphereRadius(btScalar(0.)), + m_ccdSquareMotionThreshold(btScalar(0.)), + m_checkCollideWith(false) +{ + +} + +btCollisionObject::~btCollisionObject() +{ +} + +void btCollisionObject::setActivationState(int newState) +{ + if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION)) + m_activationState1 = newState; +} + +void btCollisionObject::forceActivationState(int newState) +{ + m_activationState1 = newState; +} + +void btCollisionObject::activate(bool forceActivation) +{ + if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT))) + { + setActivationState(ACTIVE_TAG); + m_deactivationTime = btScalar(0.); + } +} + + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h new file mode 100644 index 00000000000..9fb6a67c4a3 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -0,0 +1,346 @@ +/* +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. +*/ + +#ifndef COLLISION_OBJECT_H +#define COLLISION_OBJECT_H + +#include "../../LinearMath/btTransform.h" + +//island management, m_activationState1 +#define ACTIVE_TAG 1 +#define ISLAND_SLEEPING 2 +#define WANTS_DEACTIVATION 3 +#define DISABLE_DEACTIVATION 4 +#define DISABLE_SIMULATION 5 + +struct btBroadphaseProxy; +class btCollisionShape; +#include "../../LinearMath/btMotionState.h" + + + +/// btCollisionObject can be used to manage collision detection objects. +/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy. +/// They can be added to the btCollisionWorld. +ATTRIBUTE_ALIGNED16(class) btCollisionObject +{ + +protected: + + btTransform m_worldTransform; + + ///m_interpolationWorldTransform is used for CCD and interpolation + ///it can be either previous or future (predicted) transform + btTransform m_interpolationWorldTransform; + //those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities) + //without destroying the continuous interpolated motion (which uses this interpolation velocities) + btVector3 m_interpolationLinearVelocity; + btVector3 m_interpolationAngularVelocity; + btBroadphaseProxy* m_broadphaseHandle; + btCollisionShape* m_collisionShape; + + int m_collisionFlags; + + int m_islandTag1; + int m_companionId; + + int m_activationState1; + btScalar m_deactivationTime; + + btScalar m_friction; + btScalar m_restitution; + + ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer + void* m_userObjectPointer; + + ///m_internalOwner is reserved to point to Bullet's btRigidBody. Don't use this, use m_userObjectPointer instead. + void* m_internalOwner; + + ///time of impact calculation + btScalar m_hitFraction; + + ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: + btScalar m_ccdSweptSphereRadius; + + /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold + btScalar m_ccdSquareMotionThreshold; + + /// If some object should have elaborate collision filtering by sub-classes + bool m_checkCollideWith; + + char m_pad[7]; + + virtual bool checkCollideWithOverride(btCollisionObject* co) + { + return true; + } + +public: + + enum CollisionFlags + { + CF_STATIC_OBJECT= 1, + CF_KINEMATIC_OBJECT= 2, + CF_NO_CONTACT_RESPONSE = 4, + CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution) + }; + + + inline bool mergesSimulationIslands() const + { + ///static objects, kinematic and object without contact response don't merge islands + return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0); + } + + + inline bool isStaticObject() const { + return (m_collisionFlags & CF_STATIC_OBJECT) != 0; + } + + inline bool isKinematicObject() const + { + return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0; + } + + inline bool isStaticOrKinematicObject() const + { + return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ; + } + + inline bool hasContactResponse() const { + return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0; + } + + + btCollisionObject(); + + virtual ~btCollisionObject(); + + void setCollisionShape(btCollisionShape* collisionShape) + { + m_collisionShape = collisionShape; + } + + const btCollisionShape* getCollisionShape() const + { + return m_collisionShape; + } + + btCollisionShape* getCollisionShape() + { + return m_collisionShape; + } + + + + + int getActivationState() const { return m_activationState1;} + + void setActivationState(int newState); + + void setDeactivationTime(btScalar time) + { + m_deactivationTime = time; + } + btScalar getDeactivationTime() const + { + return m_deactivationTime; + } + + void forceActivationState(int newState); + + void activate(bool forceActivation = false); + + inline bool isActive() const + { + return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION)); + } + + void setRestitution(btScalar rest) + { + m_restitution = rest; + } + btScalar getRestitution() const + { + return m_restitution; + } + void setFriction(btScalar frict) + { + m_friction = frict; + } + btScalar getFriction() const + { + return m_friction; + } + + ///reserved for Bullet internal usage + void* getInternalOwner() + { + return m_internalOwner; + } + + const void* getInternalOwner() const + { + return m_internalOwner; + } + + btTransform& getWorldTransform() + { + return m_worldTransform; + } + + const btTransform& getWorldTransform() const + { + return m_worldTransform; + } + + void setWorldTransform(const btTransform& worldTrans) + { + m_worldTransform = worldTrans; + } + + + btBroadphaseProxy* getBroadphaseHandle() + { + return m_broadphaseHandle; + } + + const btBroadphaseProxy* getBroadphaseHandle() const + { + return m_broadphaseHandle; + } + + void setBroadphaseHandle(btBroadphaseProxy* handle) + { + m_broadphaseHandle = handle; + } + + + const btTransform& getInterpolationWorldTransform() const + { + return m_interpolationWorldTransform; + } + + btTransform& getInterpolationWorldTransform() + { + return m_interpolationWorldTransform; + } + + void setInterpolationWorldTransform(const btTransform& trans) + { + m_interpolationWorldTransform = trans; + } + + + const btVector3& getInterpolationLinearVelocity() const + { + return m_interpolationLinearVelocity; + } + + const btVector3& getInterpolationAngularVelocity() const + { + return m_interpolationAngularVelocity; + } + + const int getIslandTag() const + { + return m_islandTag1; + } + + void setIslandTag(int tag) + { + m_islandTag1 = tag; + } + + const int getCompanionId() const + { + return m_companionId; + } + + void setCompanionId(int id) + { + m_companionId = id; + } + + const btScalar getHitFraction() const + { + return m_hitFraction; + } + + void setHitFraction(btScalar hitFraction) + { + m_hitFraction = hitFraction; + } + + + const int getCollisionFlags() const + { + return m_collisionFlags; + } + + void setCollisionFlags(int flags) + { + m_collisionFlags = flags; + } + + ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: + btScalar getCcdSweptSphereRadius() const + { + return m_ccdSweptSphereRadius; + } + + ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: + void setCcdSweptSphereRadius(btScalar radius) + { + m_ccdSweptSphereRadius = radius; + } + + btScalar getCcdSquareMotionThreshold() const + { + return m_ccdSquareMotionThreshold; + } + + + /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold + void setCcdSquareMotionThreshold(btScalar ccdSquareMotionThreshold) + { + m_ccdSquareMotionThreshold = ccdSquareMotionThreshold; + } + + ///users can point to their objects, userPointer is not used by Bullet + void* getUserPointer() const + { + return m_userObjectPointer; + } + + ///users can point to their objects, userPointer is not used by Bullet + void setUserPointer(void* userPointer) + { + m_userObjectPointer = userPointer; + } + + inline bool checkCollideWith(btCollisionObject* co) + { + if (m_checkCollideWith) + return checkCollideWithOverride(co); + + return true; + } + + +} +; + +#endif //COLLISION_OBJECT_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp new file mode 100644 index 00000000000..b49036a5b50 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -0,0 +1,362 @@ +/* +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. +*/ + +#include "btCollisionWorld.h" +#include "btCollisionDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting +#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" //for raycasting +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "LinearMath/btAabbUtil2.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btStackAlloc.h" + +//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" + + +btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize) +:m_dispatcher1(dispatcher), +m_broadphasePairCache(pairCache), +m_ownsDispatcher(false), +m_ownsBroadphasePairCache(false) +{ + m_stackAlloc = new btStackAlloc(stackSize); + m_dispatchInfo.m_stackAllocator = m_stackAlloc; +} + + +btCollisionWorld::~btCollisionWorld() +{ + m_stackAlloc->destroy(); + delete m_stackAlloc; + + //clean up remaining objects + int i; + for (i=0;igetBroadphaseHandle(); + if (bp) + { + // + // only clear the cached algorithms + // + getBroadphase()->cleanProxyFromPairs(bp); + getBroadphase()->destroyProxy(bp); + } + } + + if (m_ownsDispatcher) + delete m_dispatcher1; + if (m_ownsBroadphasePairCache) + delete m_broadphasePairCache; + +} + + + + + + + + + + +void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask) +{ + + //check that the object isn't already added + btAssert( m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size()); + + m_collisionObjects.push_back(collisionObject); + + //calculate new AABB + btTransform trans = collisionObject->getWorldTransform(); + + btVector3 minAabb; + btVector3 maxAabb; + collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb); + + int type = collisionObject->getCollisionShape()->getShapeType(); + collisionObject->setBroadphaseHandle( getBroadphase()->createProxy( + minAabb, + maxAabb, + type, + collisionObject, + collisionFilterGroup, + collisionFilterMask + )) ; + + + + + +} + + + + +void btCollisionWorld::performDiscreteCollisionDetection() +{ + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + + BEGIN_PROFILE("perform Broadphase Collision Detection"); + + + //update aabb (of all moved objects) + + btVector3 aabbMin,aabbMax; + for (int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax); + m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax); + } + + m_broadphasePairCache->refreshOverlappingPairs(); + + + END_PROFILE("perform Broadphase Collision Detection"); + + BEGIN_PROFILE("performDiscreteCollisionDetection"); + + btDispatcher* dispatcher = getDispatcher(); + if (dispatcher) + dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache,dispatchInfo); + + END_PROFILE("performDiscreteCollisionDetection"); + +} + + +void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) +{ + + + //bool removeFromBroadphase = false; + + { + + btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); + if (bp) + { + // + // only clear the cached algorithms + // + getBroadphase()->cleanProxyFromPairs(bp); + getBroadphase()->destroyProxy(bp); + collisionObject->setBroadphaseHandle(0); + } + } + + + //swapremove + m_collisionObjects.remove(collisionObject); + +} + + + +void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback,short int collisionFilterMask) +{ + + btSphereShape pointShape(btScalar(0.0)); + pointShape.setMargin(0.f); + + objectQuerySingle(&pointShape,rayFromTrans,rayToTrans, + collisionObject, + collisionShape, + colObjWorldTransform, + resultCallback,collisionFilterMask); +} + +void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback,short int collisionFilterMask) +{ + + + if (collisionShape->isConvex()) + { + btConvexCast::CastResult castResult; + castResult.m_fraction = btScalar(1.);//?? + + btConvexShape* convexShape = (btConvexShape*) collisionShape; + btVoronoiSimplexSolver simplexSolver; + btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); + //GjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); + //ContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); + + if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + castResult.m_normal.normalize(); + if (castResult.m_fraction < resultCallback.m_closestHitFraction) + { + + btCollisionWorld::LocalRayResult localRayResult + ( + collisionObject, + 0, + castResult.m_normal, + castResult.m_fraction + ); + + resultCallback.AddSingleResult(localRayResult); + + } + } + } + } + else + { + + if (collisionShape->isConcave()) + { + + btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; + + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + + btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); + btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); + + //ConvexCast::CastResult + + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + { + btCollisionWorld::RayResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; + + BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, + btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): + btTriangleRaycastCallback(from,to), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + + btCollisionWorld::LocalRayResult rayResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitFraction); + + return m_resultCallback->AddSingleResult(rayResult); + + + } + + }; + + + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); + rcb.m_hitFraction = resultCallback.m_closestHitFraction; + + btVector3 rayAabbMinLocal = rayFromLocal; + rayAabbMinLocal.setMin(rayToLocal); + btVector3 rayAabbMaxLocal = rayFromLocal; + rayAabbMaxLocal.setMax(rayToLocal); + + triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); + + } else + { + //todo: use AABB tree or other BVH acceleration structure! + if (collisionShape->isCompound()) + { + const btCompoundShape* compoundShape = static_cast(collisionShape); + int i=0; + for (i=0;igetNumChildShapes();i++) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childWorldTrans = colObjWorldTransform * childTrans; + objectQuerySingle(castShape, rayFromTrans,rayToTrans, + collisionObject, + childCollisionShape, + childWorldTrans, + resultCallback, collisionFilterMask); + + } + + + } + } + } +} + +void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask) +{ + + + btTransform rayFromTrans,rayToTrans; + rayFromTrans.setIdentity(); + rayFromTrans.setOrigin(rayFromWorld); + rayToTrans.setIdentity(); + + rayToTrans.setOrigin(rayToWorld); + + /// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD) + + int i; + for (i=0;igetBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); + + btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing + btVector3 hitNormal; + if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) + { + rayTestSingle(rayFromTrans,rayToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback); + } + } + } + +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h new file mode 100644 index 00000000000..b6d80233ab7 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -0,0 +1,255 @@ +/* +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. +*/ + + +/** + * @mainpage Bullet Documentation + * + * @section intro_sec Introduction + * Bullet Collision Detection & Physics SDK + * + * Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ). + * + * There is the Physics Forum for Feedback and bteral Collision Detection and Physics discussions. + * Please visit http://www.continuousphysics.com/Bullet/phpBB2/index.php + * + * @section install_sec Installation + * + * @subsection step1 Step 1: Download + * You can download the Bullet Physics Library from our website: http://www.continuousphysics.com/Bullet/ + * @subsection step2 Step 2: Building + * Bullet comes with autogenerated Project Files for Microsoft Visual Studio 6, 7, 7.1 and 8. + * The main Workspace/Solution is located in Bullet/msvc/8/wksbullet.sln (replace 8 with your version). + * + * Under other platforms, like Linux or Mac OS-X, Bullet can be build using either using cmake, http://www.cmake.org, or jam, http://www.perforce.com/jam/jam.html . cmake can autogenerate Xcode, KDevelop, MSVC and other build systems. just run cmake . in the root of Bullet. + * Jam is a build system that can build the library, demos and also autogenerate the MSVC Project Files. + * So if you are not using MSVC, you can run configure and jam . + * If you don't have jam installed, you can make jam from the included jam-2.5 sources, or download jam from ftp://ftp.perforce.com/pub/jam/ + * + * @subsection step3 Step 3: Testing demos + * Try to run and experiment with CcdPhysicsDemo executable as a starting point. + * Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation. + * The Dependencies can be seen in this documentation under Directories + * + * @subsection step4 Step 4: Integrating in your application, Full Rigid Body Simulation + * Check out CcdPhysicsDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform. + * PLEASE NOTE THE CcdPhysicsEnvironment and CcdPhysicsController is obsolete and will be removed. It has been replaced by classes derived frmo btDynamicsWorld and btRididBody + * @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras) + * Bullet Collision Detection can also be used without the Dynamics/Extras. + * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo. Also in Extras/test_BulletOde.cpp there is a sample Collision Detection integration with Open Dynamics Engine, ODE, http://www.ode.org + * @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation. + * Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector. + * + * @section copyright Copyright + * Copyright (C) 2005-2007 Erwin Coumans, some contributions Copyright Gino van den Bergen, Christer Ericson, Simon Hobbs, Ricardo Padrela, F Richter(res), Stephane Redon + * Special thanks to all visitors of the Bullet Physics forum, and in particular above contributors, Dave Eberle, Dirk Gregorius, Erin Catto, Dave Eberle, Adam Moravanszky, + * Pierre Terdiman, Kenny Erleben, Russell Smith, Oliver Strunk, Jan Paul van Waveren, Marten Svanfeldt. + * + */ + + + +#ifndef COLLISION_WORLD_H +#define COLLISION_WORLD_H + +class btStackAlloc; +class btCollisionShape; +class btConvexShape; +class btBroadphaseInterface; +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btTransform.h" +#include "btCollisionObject.h" +#include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray +#include "../BroadphaseCollision/btOverlappingPairCache.h" +#include "../../LinearMath/btAlignedObjectArray.h" + +///CollisionWorld is interface and container for the collision detection +class btCollisionWorld +{ + + +protected: + + btAlignedObjectArray m_collisionObjects; + + btDispatcher* m_dispatcher1; + + btDispatcherInfo m_dispatchInfo; + + btStackAlloc* m_stackAlloc; + + btOverlappingPairCache* m_broadphasePairCache; + + bool m_ownsDispatcher; + bool m_ownsBroadphasePairCache; + +public: + + //this constructor doesn't own the dispatcher and paircache/broadphase + btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize = 2*1024*1024); + + virtual ~btCollisionWorld(); + + + btBroadphaseInterface* getBroadphase() + { + return m_broadphasePairCache; + } + + btOverlappingPairCache* getPairCache() + { + return m_broadphasePairCache; + } + + + btDispatcher* getDispatcher() + { + return m_dispatcher1; + } + + ///LocalShapeInfo gives extra information for complex shapes + ///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart + struct LocalShapeInfo + { + int m_shapePart; + int m_triangleIndex; + + //const btCollisionShape* m_shapeTemp; + //const btTransform* m_shapeLocalTransform; + }; + + struct LocalRayResult + { + LocalRayResult(btCollisionObject* collisionObject, + LocalShapeInfo* localShapeInfo, + const btVector3& hitNormalLocal, + btScalar hitFraction) + :m_collisionObject(collisionObject), + m_localShapeInfo(localShapeInfo), + m_hitNormalLocal(hitNormalLocal), + m_hitFraction(hitFraction) + { + } + + btCollisionObject* m_collisionObject; + LocalShapeInfo* m_localShapeInfo; + btVector3 m_hitNormalLocal; + btScalar m_hitFraction; + + }; + + ///RayResultCallback is used to report new raycast results + struct RayResultCallback + { + virtual ~RayResultCallback() + { + } + btScalar m_closestHitFraction; + bool HasHit() + { + return (m_closestHitFraction < btScalar(1.)); + } + + RayResultCallback() + :m_closestHitFraction(btScalar(1.)) + { + } + virtual btScalar AddSingleResult(LocalRayResult& rayResult) = 0; + }; + + struct ClosestRayResultCallback : public RayResultCallback + { + ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) + :m_rayFromWorld(rayFromWorld), + m_rayToWorld(rayToWorld), + m_collisionObject(0) + { + } + + btVector3 m_rayFromWorld;//used to calculate hitPointWorld from hitFraction + btVector3 m_rayToWorld; + + btVector3 m_hitNormalWorld; + btVector3 m_hitPointWorld; + btCollisionObject* m_collisionObject; + + virtual btScalar AddSingleResult(LocalRayResult& rayResult) + { + +//caller already does the filter on the m_closestHitFraction + assert(rayResult.m_hitFraction <= m_closestHitFraction); + + m_closestHitFraction = rayResult.m_hitFraction; + m_collisionObject = rayResult.m_collisionObject; + m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); + return rayResult.m_hitFraction; + } + }; + + + + + int getNumCollisionObjects() const + { + return int(m_collisionObjects.size()); + } + + /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback + /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. + void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1); + + /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. + /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. + /// This allows more customization. + static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback, short int collisionFilterMask=-1); + + /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest. + static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans, + btCollisionObject* collisionObject, + const btCollisionShape* collisionShape, + const btTransform& colObjWorldTransform, + RayResultCallback& resultCallback, short int collisionFilterMask=-1); + + void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1); + + btCollisionObjectArray& getCollisionObjectArray() + { + return m_collisionObjects; + } + + const btCollisionObjectArray& getCollisionObjectArray() const + { + return m_collisionObjects; + } + + + void removeCollisionObject(btCollisionObject* collisionObject); + + virtual void performDiscreteCollisionDetection(); + + btDispatcherInfo& getDispatchInfo() + { + return m_dispatchInfo; + } + +}; + + +#endif //COLLISION_WORLD_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp new file mode 100644 index 00000000000..92f4c8b28a6 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -0,0 +1,140 @@ +/* +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. +*/ + +#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" + + +btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) +:m_isSwapped(isSwapped) +{ + btCollisionObject* colObj = m_isSwapped? body1 : body0; + btCollisionObject* otherObj = m_isSwapped? body0 : body1; + assert (colObj->getCollisionShape()->isCompound()); + + btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); + int numChildren = compoundShape->getNumChildShapes(); + int i; + + m_childCollisionAlgorithms.resize(numChildren); + for (i=0;igetChildShape(i); + btCollisionShape* orgShape = colObj->getCollisionShape(); + colObj->setCollisionShape( childShape ); + m_childCollisionAlgorithms[i] = ci.m_dispatcher->findAlgorithm(colObj,otherObj); + colObj->setCollisionShape( orgShape ); + } +} + + +btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() +{ + int numChildren = m_childCollisionAlgorithms.size(); + int i; + for (i=0;igetCollisionShape()->isCompound()); + btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); + + //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps + //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals + //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: + //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1 + //then use each overlapping node AABB against Tree0 + //and vise versa. + + int numChildren = m_childCollisionAlgorithms.size(); + int i; + for (i=0;igetChildShape(i); + + //backup + btTransform orgTrans = colObj->getWorldTransform(); + btCollisionShape* orgShape = colObj->getCollisionShape(); + + const btTransform& childTrans = compoundShape->getChildTransform(i); + //btTransform newChildWorldTrans = orgTrans*childTrans ; + colObj->setWorldTransform( orgTrans*childTrans ); + //the contactpoint is still projected back using the original inverted worldtrans + colObj->setCollisionShape( childShape ); + m_childCollisionAlgorithms[i]->processCollision(colObj,otherObj,dispatchInfo,resultOut); + //revert back + colObj->setCollisionShape( orgShape); + colObj->setWorldTransform( orgTrans ); + } +} + +btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + btCollisionObject* colObj = m_isSwapped? body1 : body0; + btCollisionObject* otherObj = m_isSwapped? body0 : body1; + + assert (colObj->getCollisionShape()->isCompound()); + + btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); + + //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps + //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals + //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: + //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1 + //then use each overlapping node AABB against Tree0 + //and vise versa. + + btScalar hitFraction = btScalar(1.); + + int numChildren = m_childCollisionAlgorithms.size(); + int i; + for (i=0;igetChildShape(i); + + //backup + btTransform orgTrans = colObj->getWorldTransform(); + btCollisionShape* orgShape = colObj->getCollisionShape(); + + const btTransform& childTrans = compoundShape->getChildTransform(i); + //btTransform newChildWorldTrans = orgTrans*childTrans ; + colObj->setWorldTransform( orgTrans*childTrans ); + + colObj->setCollisionShape( childShape ); + btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut); + if (fracsetCollisionShape( orgShape); + colObj->setWorldTransform( orgTrans); + } + return hitFraction; + +} + + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h new file mode 100644 index 00000000000..7091b233b46 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -0,0 +1,64 @@ +/* +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. +*/ + +#ifndef COMPOUND_COLLISION_ALGORITHM_H +#define COMPOUND_COLLISION_ALGORITHM_H + +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../BroadphaseCollision/btDispatcher.h" +#include "../BroadphaseCollision/btBroadphaseInterface.h" + +#include "../NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "btCollisionCreateFunc.h" +#include "../../LinearMath/btAlignedObjectArray.h" + +/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes +/// Place holder, not fully implemented yet +class btCompoundCollisionAlgorithm : public btCollisionAlgorithm +{ + btAlignedObjectArray m_childCollisionAlgorithms; + bool m_isSwapped; + +public: + + btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + virtual ~btCompoundCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + return new btCompoundCollisionAlgorithm(ci,body0,body1,false); + } + }; + + struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + return new btCompoundCollisionAlgorithm(ci,body0,body1,true); + } + }; + +}; + +#endif //COMPOUND_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp new file mode 100644 index 00000000000..24ceacfd40d --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp @@ -0,0 +1,312 @@ +/* +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. +*/ + + +#include "btConvexConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" + +btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) +: btCollisionAlgorithm(ci), +m_isSwapped(isSwapped), +m_btConvexTriangleCallback(ci.m_dispatcher,body0,body1,isSwapped) +{ +} + +btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm() +{ +} + + + +btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): + m_dispatcher(dispatcher), + m_dispatchInfoPtr(0) +{ + m_convexBody = isSwapped? body1:body0; + m_triBody = isSwapped? body0:body1; + + // + // create the manifold from the dispatcher 'manifold pool' + // + m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); + + clearCache(); +} + +btConvexTriangleCallback::~btConvexTriangleCallback() +{ + clearCache(); + m_dispatcher->releaseManifold( m_manifoldPtr ); + +} + + +void btConvexTriangleCallback::clearCache() +{ + m_dispatcher->clearManifold(m_manifoldPtr); +}; + + + +void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) +{ + + //just for debugging purposes + //printf("triangle %d",m_triangleCount++); + + + //aabb filter is already applied! + + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher = m_dispatcher; + + btCollisionObject* ob = static_cast(m_triBody); + + + + ///debug drawing of the overlapping triangles + if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() > 0) + { + btVector3 color(255,255,0); + btTransform& tr = ob->getWorldTransform(); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); + + //btVector3 center = triangle[0] + triangle[1]+triangle[2]; + //center *= btScalar(0.333333); + //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(center),color); + //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(center),color); + //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(center),color); + + } + + + //btCollisionObject* colObj = static_cast(m_convexProxy->m_clientObject); + + if (m_convexBody->getCollisionShape()->isConvex()) + { + btTriangleShape tm(triangle[0],triangle[1],triangle[2]); + tm.setMargin(m_collisionMarginTriangle); + + + btCollisionShape* tmpShape = ob->getCollisionShape(); + ob->setCollisionShape( &tm ); + + + btCollisionAlgorithm* colAlgo = ci.m_dispatcher->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); + ///this should use the btDispatcher, so the actual registered algorithm is used + // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); + + m_resultOut->setShapeIdentifiers(-1,-1,partId,triangleIndex); + // cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex); +// cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + delete colAlgo; + ob->setCollisionShape( tmpShape ); + + } + + + +} + + + +void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + m_dispatchInfoPtr = &dispatchInfo; + m_collisionMarginTriangle = collisionMarginTriangle; + m_resultOut = resultOut; + + //recalc aabbs + btTransform convexInTriangleSpace; + convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_convexBody->getWorldTransform(); + btCollisionShape* convexShape = static_cast(m_convexBody->getCollisionShape()); + //CollisionShape* triangleShape = static_cast(triBody->m_collisionShape); + convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax); + btScalar extraMargin = collisionMarginTriangle; + btVector3 extra(extraMargin,extraMargin,extraMargin); + + m_aabbMax += extra; + m_aabbMin -= extra; + +} + +void btConvexConcaveCollisionAlgorithm::clearCache() +{ + m_btConvexTriangleCallback.clearCache(); + +} + +void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + + btCollisionObject* convexBody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + if (triBody->getCollisionShape()->isConcave()) + { + + + btCollisionObject* triOb = triBody; + btConcaveShape* concaveShape = static_cast( triOb->getCollisionShape()); + + if (convexBody->getCollisionShape()->isConvex()) + { + btScalar collisionMarginTriangle = concaveShape->getMargin(); + + resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr); + m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut); + + //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here. + //m_dispatcher->clearManifold(m_btConvexTriangleCallback.m_manifoldPtr); + + m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody); + + concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax()); + + + } + + } + +} + + +btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + btCollisionObject* convexbody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + + //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) + + //only perform CCD above a certain threshold, this prevents blocking on the long run + //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... + btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); + if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) + { + return btScalar(1.); + } + + //const btVector3& from = convexbody->m_worldTransform.getOrigin(); + //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); + //todo: only do if the motion exceeds the 'radius' + + btTransform triInv = triBody->getWorldTransform().inverse(); + btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); + btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); + + struct LocalTriangleSphereCastCallback : public btTriangleCallback + { + btTransform m_ccdSphereFromTrans; + btTransform m_ccdSphereToTrans; + btTransform m_meshTransform; + + btScalar m_ccdSphereRadius; + btScalar m_hitFraction; + + + LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) + :m_ccdSphereFromTrans(from), + m_ccdSphereToTrans(to), + m_ccdSphereRadius(ccdSphereRadius), + m_hitFraction(hitFraction) + { + } + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + //do a swept sphere for now + btTransform ident; + ident.setIdentity(); + btConvexCast::CastResult castResult; + castResult.m_fraction = m_hitFraction; + btSphereShape pointShape(m_ccdSphereRadius); + btTriangleShape triShape(triangle[0],triangle[1],triangle[2]); + btVoronoiSimplexSolver simplexSolver; + btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); + //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); + //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); + //local space? + + if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, + ident,ident,castResult)) + { + if (m_hitFraction > castResult.m_fraction) + m_hitFraction = castResult.m_fraction; + } + + } + + }; + + + + + + if (triBody->getCollisionShape()->isConcave()) + { + btVector3 rayAabbMin = convexFromLocal.getOrigin(); + rayAabbMin.setMin(convexToLocal.getOrigin()); + btVector3 rayAabbMax = convexFromLocal.getOrigin(); + rayAabbMax.setMax(convexToLocal.getOrigin()); + btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); + rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + + btScalar curHitFraction = btScalar(1.); //is this available? + LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, + convexbody->getCcdSweptSphereRadius(),curHitFraction); + + raycastCallback.m_hitFraction = convexbody->getHitFraction(); + + btCollisionObject* concavebody = triBody; + + btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); + + if (triangleMesh) + { + triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); + } + + + + if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) + { + convexbody->setHitFraction( raycastCallback.m_hitFraction); + return raycastCallback.m_hitFraction; + } + } + + return btScalar(1.); + +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h new file mode 100644 index 00000000000..4915b6c20c8 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h @@ -0,0 +1,111 @@ +/* +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. +*/ + +#ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H +#define CONVEX_CONCAVE_COLLISION_ALGORITHM_H + +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../BroadphaseCollision/btDispatcher.h" +#include "../BroadphaseCollision/btBroadphaseInterface.h" +#include "../CollisionShapes/btTriangleCallback.h" +#include "../NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "btCollisionCreateFunc.h" + +///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called. +class btConvexTriangleCallback : public btTriangleCallback +{ + btCollisionObject* m_convexBody; + btCollisionObject* m_triBody; + + btVector3 m_aabbMin; + btVector3 m_aabbMax ; + + btManifoldResult* m_resultOut; + + btDispatcher* m_dispatcher; + const btDispatcherInfo* m_dispatchInfoPtr; + btScalar m_collisionMarginTriangle; + +public: +int m_triangleCount; + + btPersistentManifold* m_manifoldPtr; + + btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual ~btConvexTriangleCallback(); + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + void clearCache(); + + inline const btVector3& getAabbMin() const + { + return m_aabbMin; + } + inline const btVector3& getAabbMax() const + { + return m_aabbMax; + } + +}; + + + + +/// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes. +class btConvexConcaveCollisionAlgorithm : public btCollisionAlgorithm +{ + + bool m_isSwapped; + + btConvexTriangleCallback m_btConvexTriangleCallback; + + +public: + + btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + virtual ~btConvexConcaveCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + void clearCache(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); + } + }; + + struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); + } + }; + +}; + +#endif //CONVEX_CONCAVE_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp new file mode 100644 index 00000000000..9105fe20b49 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp @@ -0,0 +1,254 @@ +/* +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. +*/ + +#include "btConvexConvexAlgorithm.h" + +#include +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" + +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" + + + +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" + +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" + + + + + + + +btConvexConvexAlgorithm::CreateFunc::CreateFunc() +{ + m_ownsSolvers = true; + m_simplexSolver = new btVoronoiSimplexSolver(); + m_pdSolver = new btGjkEpaPenetrationDepthSolver; +} + +btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) +{ + m_ownsSolvers = false; + m_simplexSolver = simplexSolver; + m_pdSolver = pdSolver; +} + +btConvexConvexAlgorithm::CreateFunc::~CreateFunc() +{ + if (m_ownsSolvers){ + delete m_simplexSolver; + delete m_pdSolver; + } +} + +btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) +: btCollisionAlgorithm(ci), +m_gjkPairDetector(0,0,simplexSolver,pdSolver), +m_ownManifold (false), +m_manifoldPtr(mf), +m_lowLevelOfDetail(false) +{ + (void)body0; + (void)body1; + + +} + + + + +btConvexConvexAlgorithm::~btConvexConvexAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel) +{ + m_lowLevelOfDetail = useLowLevel; +} + + + + + +// +// Convex-Convex collision algorithm +// +void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + if (!m_manifoldPtr) + { + //swapped? + m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); + m_ownManifold = true; + } + resultOut->setPersistentManifold(m_manifoldPtr); + +#ifdef USE_BT_GJKEPA + btConvexShape* shape0(static_cast(body0->getCollisionShape())); + btConvexShape* shape1(static_cast(body1->getCollisionShape())); + const btScalar radialmargin(0/*shape0->getMargin()+shape1->getMargin()*/); + btGjkEpaSolver::sResults results; + if(btGjkEpaSolver::Collide( shape0,body0->getWorldTransform(), + shape1,body1->getWorldTransform(), + radialmargin,results)) + { + dispatchInfo.m_debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); + resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); + } +#else + + btConvexShape* min0 = static_cast(body0->getCollisionShape()); + btConvexShape* min1 = static_cast(body1->getCollisionShape()); + + btGjkPairDetector::ClosestPointInput input; + + //TODO: if (dispatchInfo.m_useContinuous) + m_gjkPairDetector.setMinkowskiA(min0); + m_gjkPairDetector.setMinkowskiB(min1); + input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold(); + input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared; + input.m_stackAlloc = dispatchInfo.m_stackAllocator; + +// input.m_maximumDistanceSquared = btScalar(1e30); + + input.m_transformA = body0->getWorldTransform(); + input.m_transformB = body1->getWorldTransform(); + + m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); +#endif + +} + + + +bool disableCcd = false; +btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold + + ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold + ///col0->m_worldTransform, + btScalar resultFraction = btScalar(1.); + + + btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2(); + btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2(); + + if (squareMot0 < col0->getCcdSquareMotionThreshold() && + squareMot1 < col1->getCcdSquareMotionThreshold()) + return resultFraction; + + if (disableCcd) + return btScalar(1.); + + + //An adhoc way of testing the Continuous Collision Detection algorithms + //One object is approximated as a sphere, to simplify things + //Starting in penetration should report no time of impact + //For proper CCD, better accuracy and handling of 'allowed' penetration should be added + //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies) + + + /// Convex0 against sphere for Convex1 + { + btConvexShape* convex0 = static_cast(col0->getCollisionShape()); + + btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation + btConvexCast::CastResult result; + btVoronoiSimplexSolver voronoiSimplex; + //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); + ///Simplification, one object is simplified as a sphere + btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex); + //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); + if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), + col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) + { + + //store result.m_fraction in both bodies + + if (col0->getHitFraction()> result.m_fraction) + col0->setHitFraction( result.m_fraction ); + + if (col1->getHitFraction() > result.m_fraction) + col1->setHitFraction( result.m_fraction); + + if (resultFraction > result.m_fraction) + resultFraction = result.m_fraction; + + } + + + + + } + + /// Sphere (for convex0) against Convex1 + { + btConvexShape* convex1 = static_cast(col1->getCollisionShape()); + + btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation + btConvexCast::CastResult result; + btVoronoiSimplexSolver voronoiSimplex; + //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex); + ///Simplification, one object is simplified as a sphere + btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex); + //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0); + if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(), + col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result)) + { + + //store result.m_fraction in both bodies + + if (col0->getHitFraction() > result.m_fraction) + col0->setHitFraction( result.m_fraction); + + if (col1->getHitFraction() > result.m_fraction) + col1->setHitFraction( result.m_fraction); + + if (resultFraction > result.m_fraction) + resultFraction = result.m_fraction; + + } + } + + return resultFraction; + +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h new file mode 100644 index 00000000000..cbea9a92b75 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h @@ -0,0 +1,76 @@ +/* +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. +*/ + +#ifndef CONVEX_CONVEX_ALGORITHM_H +#define CONVEX_CONVEX_ALGORITHM_H + +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../NarrowPhaseCollision/btGjkPairDetector.h" +#include "../NarrowPhaseCollision/btPersistentManifold.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "btCollisionCreateFunc.h" + +class btConvexPenetrationDepthSolver; + +///ConvexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations. +class btConvexConvexAlgorithm : public btCollisionAlgorithm +{ + btGjkPairDetector m_gjkPairDetector; +public: + + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_lowLevelOfDetail; + + +public: + + btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); + + virtual ~btConvexConvexAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + void setLowLevelOfDetail(bool useLowLevel); + + + const btPersistentManifold* getManifold() + { + return m_manifoldPtr; + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + btConvexPenetrationDepthSolver* m_pdSolver; + btSimplexSolverInterface* m_simplexSolver; + bool m_ownsSolvers; + + CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); + CreateFunc(); + virtual ~CreateFunc(); + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + return new btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver); + } + }; + + +}; + +#endif //CONVEX_CONVEX_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp new file mode 100644 index 00000000000..936054387c4 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp @@ -0,0 +1,34 @@ +/* +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. +*/ + +#include "btEmptyCollisionAlgorithm.h" + + + +btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btCollisionAlgorithm(ci) +{ +} + +void btEmptyAlgorithm::processCollision (btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* ) +{ +} + +btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* ) +{ + return btScalar(1.); +} + + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h new file mode 100644 index 00000000000..b1a193d2cfd --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h @@ -0,0 +1,48 @@ +/* +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. +*/ + +#ifndef EMPTY_ALGORITH +#define EMPTY_ALGORITH +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "btCollisionCreateFunc.h" + +#define ATTRIBUTE_ALIGNED(a) + +///EmptyAlgorithm is a stub for unsupported collision pairs. +///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame. +class btEmptyAlgorithm : public btCollisionAlgorithm +{ + +public: + + btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + (void)body0; + (void)body1; + return new btEmptyAlgorithm(ci); + } + }; + +} ATTRIBUTE_ALIGNED(16); + +#endif //EMPTY_ALGORITH diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp new file mode 100644 index 00000000000..490acc0b611 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp @@ -0,0 +1,109 @@ +/* +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. +*/ + + +#include "btManifoldResult.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + + +///This is to allow MaterialCombiner/Custom Friction/Restitution values +ContactAddedCallback gContactAddedCallback=0; + +///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback; +inline btScalar calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1) +{ + btScalar friction = body0->getFriction() * body1->getFriction(); + + const btScalar MAX_FRICTION = btScalar(10.); + if (friction < -MAX_FRICTION) + friction = -MAX_FRICTION; + if (friction > MAX_FRICTION) + friction = MAX_FRICTION; + return friction; + +} + +inline btScalar calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1) +{ + return body0->getRestitution() * body1->getRestitution(); +} + + + +btManifoldResult::btManifoldResult(btCollisionObject* body0,btCollisionObject* body1) + :m_manifoldPtr(0), + m_body0(body0), + m_body1(body1) +{ + m_rootTransA = body0->getWorldTransform(); + m_rootTransB = body1->getWorldTransform(); +} + + +void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) +{ + assert(m_manifoldPtr); + //order in manifold needs to match + + if (depth > m_manifoldPtr->getContactBreakingThreshold()) + return; + + bool isSwapped = m_manifoldPtr->getBody0() != m_body0; + + btVector3 pointA = pointInWorld + normalOnBInWorld * depth; + + btVector3 localA; + btVector3 localB; + + if (isSwapped) + { + localA = m_rootTransB.invXform(pointA ); + localB = m_rootTransA.invXform(pointInWorld); + } else + { + localA = m_rootTransA.invXform(pointA ); + localB = m_rootTransB.invXform(pointInWorld); + } + + btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); + + int insertIndex = m_manifoldPtr->getCacheEntry(newPt); + + newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1); + newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1); + + //User can override friction and/or restitution + if (gContactAddedCallback && + //and if either of the two bodies requires custom material + ((m_body0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) || + (m_body1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK))) + { + //experimental feature info, for per-triangle material etc. + btCollisionObject* obj0 = isSwapped? m_body1 : m_body0; + btCollisionObject* obj1 = isSwapped? m_body0 : m_body1; + (*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1); + } + + if (insertIndex >= 0) + { + //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); + m_manifoldPtr->replaceContactPoint(newPt,insertIndex); + } else + { + m_manifoldPtr->AddManifoldPoint(newPt); + } +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h new file mode 100644 index 00000000000..77192625513 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h @@ -0,0 +1,77 @@ +/* +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. +*/ + + +#ifndef MANIFOLD_RESULT_H +#define MANIFOLD_RESULT_H + +class btCollisionObject; +class btPersistentManifold; +class btManifoldPoint; + +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + +#include "../../LinearMath/btTransform.h" + +typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1); +extern ContactAddedCallback gContactAddedCallback; + + + +///btManifoldResult is a helper class to manage contact results. +class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result +{ + btPersistentManifold* m_manifoldPtr; + + //we need this for compounds + btTransform m_rootTransA; + btTransform m_rootTransB; + + btCollisionObject* m_body0; + btCollisionObject* m_body1; + int m_partId0; + int m_partId1; + int m_index0; + int m_index1; +public: + + btManifoldResult() + { + } + + btManifoldResult(btCollisionObject* body0,btCollisionObject* body1); + + virtual ~btManifoldResult() {}; + + void setPersistentManifold(btPersistentManifold* manifoldPtr) + { + m_manifoldPtr = manifoldPtr; + } + + virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1) + { + m_partId0=partId0; + m_partId1=partId1; + m_index0=index0; + m_index1=index1; + } + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); + + + +}; + +#endif //MANIFOLD_RESULT_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp new file mode 100644 index 00000000000..ac2e8554c3a --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -0,0 +1,357 @@ + + +#include "LinearMath/btScalar.h" +#include "btSimulationIslandManager.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" + +#include +#include "LinearMath/btQuickprof.h" + +btSimulationIslandManager::btSimulationIslandManager() +{ +} + +btSimulationIslandManager::~btSimulationIslandManager() +{ +} + + +void btSimulationIslandManager::initUnionFind(int n) +{ + m_unionFind.reset(n); +} + + +void btSimulationIslandManager::findUnions(btDispatcher* dispatcher) +{ + + { + for (int i=0;igetNumManifolds();i++) + { + const btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); + //static objects (invmass btScalar(0.)) don't merge ! + + const btCollisionObject* colObj0 = static_cast(manifold->getBody0()); + const btCollisionObject* colObj1 = static_cast(manifold->getBody1()); + + if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && + ((colObj1) && ((colObj1)->mergesSimulationIslands()))) + { + + m_unionFind.unite((colObj0)->getIslandTag(), + (colObj1)->getIslandTag()); + } + } + } +} + + +void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher) +{ + + initUnionFind( int (colWorld->getCollisionObjectArray().size())); + + // put the index into m_controllers into m_tag + { + + int index = 0; + int i; + for (i=0;igetCollisionObjectArray().size(); i++) + { + btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; + collisionObject->setIslandTag(index); + collisionObject->setCompanionId(-1); + collisionObject->setHitFraction(btScalar(1.)); + index++; + + } + } + // do the union find + + findUnions(dispatcher); + + + +} + + + + +void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld) +{ + // put the islandId ('find' value) into m_tag + { + + + int index = 0; + int i; + for (i=0;igetCollisionObjectArray().size();i++) + { + btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; + if (collisionObject->mergesSimulationIslands()) + { + collisionObject->setIslandTag( m_unionFind.find(index) ); + collisionObject->setCompanionId(-1); + } else + { + collisionObject->setIslandTag(-1); + collisionObject->setCompanionId(-2); + } + index++; + } + } +} + +inline int getIslandId(const btPersistentManifold* lhs) +{ + int islandId; + const btCollisionObject* rcolObj0 = static_cast(lhs->getBody0()); + const btCollisionObject* rcolObj1 = static_cast(lhs->getBody1()); + islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag(); + return islandId; + +} + + + +/// function object that routes calls to operator< +class btPersistentManifoldSortPredicate +{ + public: + + SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs ) + { + return getIslandId(lhs) < getIslandId(rhs); + } +}; + + + + + +// +// todo: this is random access, it can be walked 'cache friendly'! +// +void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) +{ + + + + /*if (0) + { + int maxNumManifolds = dispatcher->getNumManifolds(); + btCollisionDispatcher* colDis = (btCollisionDispatcher*)dispatcher; + btPersistentManifold** manifold = colDis->getInternalManifoldPointer(); + callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, 0); + return; + } + */ + + + BEGIN_PROFILE("islandUnionFindAndHeapSort"); + + //we are going to sort the unionfind array, and store the element id in the size + //afterwards, we clean unionfind, to make sure no-one uses it anymore + + getUnionFind().sortIslands(); + int numElem = getUnionFind().getNumElements(); + + int endIslandIndex=1; + int startIslandIndex; + + + //update the sleeping state for bodies, if all are sleeping + for ( startIslandIndex=0;startIslandIndexgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { + printf("error in island management\n"); + } + + assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + if (colObj0->getIslandTag() == islandId) + { + if (colObj0->getActivationState()== ACTIVE_TAG) + { + allSleeping = false; + } + if (colObj0->getActivationState()== DISABLE_DEACTIVATION) + { + allSleeping = false; + } + } + } + + + if (allSleeping) + { + int idx; + for (idx=startIslandIndex;idxgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { + printf("error in island management\n"); + } + + assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + + if (colObj0->getIslandTag() == islandId) + { + colObj0->setActivationState( ISLAND_SLEEPING ); + } + } + } else + { + + int idx; + for (idx=startIslandIndex;idxgetIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) + { + printf("error in island management\n"); + } + + assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); + + if (colObj0->getIslandTag() == islandId) + { + if ( colObj0->getActivationState() == ISLAND_SLEEPING) + { + colObj0->setActivationState( WANTS_DEACTIVATION); + } + } + } + } + } + + btAlignedObjectArray islandmanifold; + int i; + int maxNumManifolds = dispatcher->getNumManifolds(); + islandmanifold.reserve(maxNumManifolds); + + for (i=0;igetManifoldByIndexInternal(i); + + btCollisionObject* colObj0 = static_cast(manifold->getBody0()); + btCollisionObject* colObj1 = static_cast(manifold->getBody1()); + + //todo: check sleeping conditions! + if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) || + ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING)) + { + + //kinematic objects don't merge islands, but wake up all connected objects + if (colObj0->isStaticOrKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) + { + colObj1->activate(); + } + if (colObj1->isStaticOrKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) + { + colObj0->activate(); + } + + //filtering for response + if (dispatcher->needsResponse(colObj0,colObj1)) + islandmanifold.push_back(manifold); + } + } + + int numManifolds = int (islandmanifold.size()); + + // Sort manifolds, based on islands + // Sort the vector using predicate and std::sort + //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); + + //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) + islandmanifold.heapSort(btPersistentManifoldSortPredicate()); + + //now process all active islands (sets of manifolds for now) + + int startManifoldIndex = 0; + int endManifoldIndex = 1; + + //int islandId; + + END_PROFILE("islandUnionFindAndHeapSort"); + + btAlignedObjectArray islandBodies; + + + //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated + for ( startIslandIndex=0;startIslandIndexisActive()) + islandSleeping = true; + } + + + //find the accompanying contact manifold for this islandId + int numIslandManifolds = 0; + btPersistentManifold** startManifold = 0; + + if (startManifoldIndexProcessIsland(&islandBodies[0],islandBodies.size(),startManifold,numIslandManifolds, islandId); + } + + if (numIslandManifolds) + { + startManifoldIndex = endManifoldIndex; + } + + islandBodies.resize(0); + } + + +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h new file mode 100644 index 00000000000..d91ed1c20eb --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h @@ -0,0 +1,61 @@ +/* +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. +*/ + +#ifndef SIMULATION_ISLAND_MANAGER_H +#define SIMULATION_ISLAND_MANAGER_H + +#include "../CollisionDispatch/btUnionFind.h" +#include "btCollisionCreateFunc.h" + +class btCollisionObject; +class btCollisionWorld; +class btDispatcher; + +///SimulationIslandManager creates and handles simulation islands, using btUnionFind +class btSimulationIslandManager +{ + btUnionFind m_unionFind; + +public: + btSimulationIslandManager(); + virtual ~btSimulationIslandManager(); + + + void initUnionFind(int n); + + + btUnionFind& getUnionFind() { return m_unionFind;} + + virtual void updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher); + virtual void storeIslandActivationState(btCollisionWorld* world); + + + void findUnions(btDispatcher* dispatcher); + + + + struct IslandCallback + { + virtual ~IslandCallback() {}; + + virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold** manifolds,int numManifolds, int islandId) = 0; + }; + + void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback); + +}; + +#endif //SIMULATION_ISLAND_MANAGER_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp new file mode 100644 index 00000000000..05556bd34e2 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp @@ -0,0 +1,249 @@ +/* +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. +*/ + +#include "btSphereBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +//#include + +btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped) +: btCollisionAlgorithm(ci), +m_ownManifold(false), +m_manifoldPtr(mf), +m_isSwapped(isSwapped) +{ + btCollisionObject* sphereObj = m_isSwapped? col1 : col0; + btCollisionObject* boxObj = m_isSwapped? col0 : col1; + + if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObj,boxObj)) + { + m_manifoldPtr = m_dispatcher->getNewManifold(sphereObj,boxObj); + m_ownManifold = true; + } +} + + +btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + + + +void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + (void)resultOut; + if (!m_manifoldPtr) + return; + + btCollisionObject* sphereObj = m_isSwapped? body1 : body0; + btCollisionObject* boxObj = m_isSwapped? body0 : body1; + + + btSphereShape* sphere0 = (btSphereShape*)sphereObj->getCollisionShape(); + + btVector3 normalOnSurfaceB; + btVector3 pOnBox,pOnSphere; + btVector3 sphereCenter = sphereObj->getWorldTransform().getOrigin(); + btScalar radius = sphere0->getRadius(); + + btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius); + + if (dist < SIMD_EPSILON) + { + btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize(); + + /// report a contact. internally this will be kept persistent, and contact reduction is done + + resultOut->setPersistentManifold(m_manifoldPtr); + resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist); + + } + + + +} + +btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} + + +btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* boxObj, btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius ) +{ + + btScalar margins; + btVector3 bounds[2]; + btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape(); + + bounds[0] = -boxShape->getHalfExtents(); + bounds[1] = boxShape->getHalfExtents(); + + margins = boxShape->getMargin();//also add sphereShape margin? + + const btTransform& m44T = boxObj->getWorldTransform(); + + btVector3 boundsVec[2]; + btScalar fPenetration; + + boundsVec[0] = bounds[0]; + boundsVec[1] = bounds[1]; + + btVector3 marginsVec( margins, margins, margins ); + + // add margins + bounds[0] += marginsVec; + bounds[1] -= marginsVec; + + ///////////////////////////////////////////////// + + btVector3 tmp, prel, n[6], normal, v3P; + btScalar fSep = btScalar(10000000.0), fSepThis; + + n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) ); + n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) ); + n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) ); + n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) ); + n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) ); + n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) ); + + // convert point in local space + prel = m44T.invXform( sphereCenter); + + bool bFound = false; + + v3P = prel; + + for (int i=0;i<6;i++) + { + int j = i<3? 0:1; + if ( (fSepThis = ((v3P-bounds[j]) .dot(n[i]))) > btScalar(0.0) ) + { + v3P = v3P - n[i]*fSepThis; + bFound = true; + } + } + + // + + if ( bFound ) + { + bounds[0] = boundsVec[0]; + bounds[1] = boundsVec[1]; + + normal = (prel - v3P).normalize(); + pointOnBox = v3P + normal*margins; + v3PointOnSphere = prel - normal*fRadius; + + if ( ((v3PointOnSphere - pointOnBox) .dot (normal)) > btScalar(0.0) ) + { + return btScalar(1.0); + } + + // transform back in world space + tmp = m44T( pointOnBox); + pointOnBox = tmp; + tmp = m44T( v3PointOnSphere); + v3PointOnSphere = tmp; + btScalar fSeps2 = (pointOnBox-v3PointOnSphere).length2(); + + //if this fails, fallback into deeper penetration case, below + if (fSeps2 > SIMD_EPSILON) + { + fSep = - btSqrt(fSeps2); + normal = (pointOnBox-v3PointOnSphere); + normal *= btScalar(1.)/fSep; + } + + return fSep; + } + + ////////////////////////////////////////////////// + // Deep penetration case + + fPenetration = getSpherePenetration( boxObj,pointOnBox, v3PointOnSphere, sphereCenter, fRadius,bounds[0],bounds[1] ); + + bounds[0] = boundsVec[0]; + bounds[1] = boundsVec[1]; + + if ( fPenetration <= btScalar(0.0) ) + return (fPenetration-margins); + else + return btScalar(1.0); +} + +btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* boxObj,btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax) +{ + + btVector3 bounds[2]; + + bounds[0] = aabbMin; + bounds[1] = aabbMax; + + btVector3 p0, tmp, prel, n[6], normal; + btScalar fSep = btScalar(-10000000.0), fSepThis; + + n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) ); + n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) ); + n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) ); + n[3].setValue( btScalar(1.0), btScalar(0.0), btScalar(0.0) ); + n[4].setValue( btScalar(0.0), btScalar(1.0), btScalar(0.0) ); + n[5].setValue( btScalar(0.0), btScalar(0.0), btScalar(1.0) ); + + const btTransform& m44T = boxObj->getWorldTransform(); + + // convert point in local space + prel = m44T.invXform( sphereCenter); + + /////////// + + for (int i=0;i<6;i++) + { + int j = i<3 ? 0:1; + if ( (fSepThis = ((prel-bounds[j]) .dot( n[i]))-fRadius) > btScalar(0.0) ) return btScalar(1.0); + if ( fSepThis > fSep ) + { + p0 = bounds[j]; normal = (btVector3&)n[i]; + fSep = fSepThis; + } + } + + pointOnBox = prel - normal*(normal.dot((prel-p0))); + v3PointOnSphere = pointOnBox + normal*fSep; + + // transform back in world space + tmp = m44T( pointOnBox); + pointOnBox = tmp; + tmp = m44T( v3PointOnSphere); v3PointOnSphere = tmp; + normal = (pointOnBox-v3PointOnSphere).normalize(); + + return fSep; + +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h new file mode 100644 index 00000000000..07592909200 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h @@ -0,0 +1,64 @@ +/* +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. +*/ + +#ifndef SPHERE_BOX_COLLISION_ALGORITHM_H +#define SPHERE_BOX_COLLISION_ALGORITHM_H + +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "../../LinearMath/btVector3.h" + +/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +class btSphereBoxCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_isSwapped; + +public: + + btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); + + virtual ~btSphereBoxCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius ); + + btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + if (!m_swapped) + { + return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); + } else + { + return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); + } + } + }; + +}; + +#endif //SPHERE_BOX_COLLISION_ALGORITHM_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp new file mode 100644 index 00000000000..424ff432f84 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp @@ -0,0 +1,85 @@ +/* +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. +*/ + +#include "btSphereSphereCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + +btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1) +: btCollisionAlgorithm(ci), +m_ownManifold(false), +m_manifoldPtr(mf) +{ + if (!m_manifoldPtr) + { + m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1); + m_ownManifold = true; + } +} + +btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + + if (!m_manifoldPtr) + return; + + btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape(); + btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape(); + + btVector3 diff = col0->getWorldTransform().getOrigin()- col1->getWorldTransform().getOrigin(); + btScalar len = diff.length(); + btScalar radius0 = sphere0->getRadius(); + btScalar radius1 = sphere1->getRadius(); + + ///iff distance positive, don't generate a new contact + if ( len > (radius0+radius1)) + return; + + ///distance (negative means penetration) + btScalar dist = len - (radius0+radius1); + + btVector3 normalOnSurfaceB = diff / len; + ///point on A (worldspace) + btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; + ///point on B (worldspace) + btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; + + /// report a contact. internally this will be kept persistent, and contact reduction is done + resultOut->setPersistentManifold(m_manifoldPtr); + resultOut->addContactPoint(normalOnSurfaceB,pos1,dist); + +} + +btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)col0; + (void)col1; + (void)dispatchInfo; + (void)resultOut; + + //not yet + return btScalar(1.); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h new file mode 100644 index 00000000000..7a19ff31edf --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h @@ -0,0 +1,56 @@ +/* +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. +*/ + +#ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H +#define SPHERE_SPHERE_COLLISION_ALGORITHM_H + +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; + +/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +/// Also provides the most basic sample for custom/user btCollisionAlgorithm +class btSphereSphereCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + +public: + btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); + + btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btCollisionAlgorithm(ci) {} + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + + virtual ~btSphereSphereCollisionAlgorithm(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + return new btSphereSphereCollisionAlgorithm(0,ci,body0,body1); + } + }; + +}; + +#endif //SPHERE_SPHERE_COLLISION_ALGORITHM_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp new file mode 100644 index 00000000000..b011b707e3f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp @@ -0,0 +1,76 @@ +/* +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. +*/ + + +#include "btSphereTriangleCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "SphereTriangleDetector.h" + + +btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,bool swapped) +: btCollisionAlgorithm(ci), +m_ownManifold(false), +m_manifoldPtr(mf), +m_swapped(swapped) +{ + if (!m_manifoldPtr) + { + m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1); + m_ownManifold = true; + } +} + +btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + if (!m_manifoldPtr) + return; + + btSphereShape* sphere = (btSphereShape*)col0->getCollisionShape(); + btTriangleShape* triangle = (btTriangleShape*)col1->getCollisionShape(); + + /// report a contact. internally this will be kept persistent, and contact reduction is done + resultOut->setPersistentManifold(m_manifoldPtr); + SphereTriangleDetector detector(sphere,triangle); + + btDiscreteCollisionDetectorInterface::ClosestPointInput input; + input.m_maximumDistanceSquared = btScalar(1e30);//todo: tighter bounds + input.m_transformA = col0->getWorldTransform(); + input.m_transformB = col1->getWorldTransform(); + + detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + +} + +btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h new file mode 100644 index 00000000000..57c6e6af619 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h @@ -0,0 +1,59 @@ +/* +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. +*/ + +#ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H +#define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H + +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; + +/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +/// Also provides the most basic sample for custom/user btCollisionAlgorithm +class btSphereTriangleCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_swapped; + +public: + btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool swapped); + + btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btCollisionAlgorithm(ci) {} + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + + virtual ~btSphereTriangleCollisionAlgorithm(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + + return new btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); + } + }; + +}; + +#endif //SPHERE_TRIANGLE_COLLISION_ALGORITHM_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp new file mode 100644 index 00000000000..62254335796 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp @@ -0,0 +1,83 @@ +/* +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. +*/ + +#include "btUnionFind.h" +#include + + + +btUnionFind::~btUnionFind() +{ + Free(); + +} + +btUnionFind::btUnionFind() +{ + +} + +void btUnionFind::allocate(int N) +{ + m_elements.resize(N); +} +void btUnionFind::Free() +{ + m_elements.clear(); +} + + +void btUnionFind::reset(int N) +{ + allocate(N); + + for (int i = 0; i < N; i++) + { + m_elements[i].m_id = i; m_elements[i].m_sz = 1; + } +} + + +class btUnionFindElementSortPredicate +{ + public: + + bool operator() ( const btElement& lhs, const btElement& rhs ) + { + return lhs.m_id < rhs.m_id; + } +}; + +///this is a special operation, destroying the content of btUnionFind. +///it sorts the elements, based on island id, in order to make it easy to iterate over islands +void btUnionFind::sortIslands() +{ + + //first store the original body index, and islandId + int numElements = m_elements.size(); + + for (int i=0;i m_elements; + + public: + + btUnionFind(); + ~btUnionFind(); + + + //this is a special operation, destroying the content of btUnionFind. + //it sorts the elements, based on island id, in order to make it easy to iterate over islands + void sortIslands(); + + void reset(int N); + + inline int getNumElements() const + { + return int(m_elements.size()); + } + inline bool isRoot(int x) const + { + return (x == m_elements[x].m_id); + } + + btElement& getElement(int index) + { + return m_elements[index]; + } + const btElement& getElement(int index) const + { + return m_elements[index]; + } + + void allocate(int N); + void Free(); + + + + + int find(int p, int q) + { + return (find(p) == find(q)); + } + + void unite(int p, int q) + { + int i = find(p), j = find(q); + if (i == j) + return; + +#ifndef USE_PATH_COMPRESSION + //weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) ) + if (m_elements[i].m_sz < m_elements[j].m_sz) + { + m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; + } + else + { + m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz; + } +#else + m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; +#endif //USE_PATH_COMPRESSION + } + + int find(int x) + { + //assert(x < m_N); + //assert(x >= 0); + + while (x != m_elements[x].m_id) + { + //not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically + + #ifdef USE_PATH_COMPRESSION + // + m_elements[x].m_id = m_elements[m_elements[x].m_id].m_id; + #endif // + x = m_elements[x].m_id; + //assert(x < m_N); + //assert(x >= 0); + + } + return x; + } + + + }; + + +#endif //UNION_FIND_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp new file mode 100644 index 00000000000..636b0046c13 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp @@ -0,0 +1,57 @@ +/* +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. +*/ + +#include "btBoxShape.h" + +btVector3 btBoxShape::getHalfExtents() const +{ + return m_implicitShapeDimensions * m_localScaling; +} +//{ + + +void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 halfExtents = getHalfExtents(); + + btMatrix3x3 abs_b = t.getBasis().absolute(); + btPoint3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtents), + abs_b[1].dot(halfExtents), + abs_b[2].dot(halfExtents)); + extent += btVector3(getMargin(),getMargin(),getMargin()); + + aabbMin = center - extent; + aabbMax = center + extent; + + +} + + +void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +{ + //btScalar margin = btScalar(0.); + btVector3 halfExtents = getHalfExtents(); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + lz*lz), + mass/(btScalar(12.0)) * (lx*lx + ly*ly)); + +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h new file mode 100644 index 00000000000..bc42f146c7c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h @@ -0,0 +1,293 @@ +/* +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. +*/ + +#ifndef OBB_BOX_MINKOWSKI_H +#define OBB_BOX_MINKOWSKI_H + +#include "btPolyhedralConvexShape.h" +#include "btCollisionMargin.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../../LinearMath/btPoint3.h" +#include "../../LinearMath/btSimdMinMax.h" + +///btBoxShape implements both a feature based (vertex/edge/plane) and implicit (getSupportingVertex) Box +class btBoxShape: public btPolyhedralConvexShape +{ + + //btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead + + +public: + + btVector3 getHalfExtents() const; + + virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;} + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const + { + + btVector3 halfExtents = getHalfExtents(); + + btVector3 supVertex; + supVertex = btPoint3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), + vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), + vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); + + return supVertex; + } + + virtual inline btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + btVector3 halfExtents = getHalfExtents(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents -= margin; + + return btVector3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), + vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), + vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); + } + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + { + btVector3 halfExtents = getHalfExtents(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents -= margin; + + + for (int i=0;i>1)) - halfExtents.y() * ((i&2)>>1), + halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2)); + } + + + virtual void getPlaneEquation(btVector4& plane,int i) const + { + btVector3 halfExtents = getHalfExtents(); + + switch (i) + { + case 0: + plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); + plane[3] = -halfExtents.x(); + break; + case 1: + plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); + plane[3] = -halfExtents.x(); + break; + case 2: + plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); + plane[3] = -halfExtents.y(); + break; + case 3: + plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); + plane[3] = -halfExtents.y(); + break; + case 4: + plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); + plane[3] = -halfExtents.z(); + break; + case 5: + plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); + plane[3] = -halfExtents.z(); + break; + default: + assert(0); + } + } + + + virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const + //virtual void getEdge(int i,Edge& edge) const + { + int edgeVert0 = 0; + int edgeVert1 = 0; + + switch (i) + { + case 0: + edgeVert0 = 0; + edgeVert1 = 1; + break; + case 1: + edgeVert0 = 0; + edgeVert1 = 2; + break; + case 2: + edgeVert0 = 1; + edgeVert1 = 3; + + break; + case 3: + edgeVert0 = 2; + edgeVert1 = 3; + break; + case 4: + edgeVert0 = 0; + edgeVert1 = 4; + break; + case 5: + edgeVert0 = 1; + edgeVert1 = 5; + + break; + case 6: + edgeVert0 = 2; + edgeVert1 = 6; + break; + case 7: + edgeVert0 = 3; + edgeVert1 = 7; + break; + case 8: + edgeVert0 = 4; + edgeVert1 = 5; + break; + case 9: + edgeVert0 = 4; + edgeVert1 = 6; + break; + case 10: + edgeVert0 = 5; + edgeVert1 = 7; + break; + case 11: + edgeVert0 = 6; + edgeVert1 = 7; + break; + default: + btAssert(0); + + } + + getVertex(edgeVert0,pa ); + getVertex(edgeVert1,pb ); + } + + + + + + virtual bool isInside(const btPoint3& pt,btScalar tolerance) const + { + btVector3 halfExtents = getHalfExtents(); + + //btScalar minDist = 2*tolerance; + + bool result = (pt.x() <= (halfExtents.x()+tolerance)) && + (pt.x() >= (-halfExtents.x()-tolerance)) && + (pt.y() <= (halfExtents.y()+tolerance)) && + (pt.y() >= (-halfExtents.y()-tolerance)) && + (pt.z() <= (halfExtents.z()+tolerance)) && + (pt.z() >= (-halfExtents.z()-tolerance)); + + return result; + } + + + //debugging + virtual char* getName()const + { + return "Box"; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 6; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + switch (index) + { + case 0: + penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.)); + break; + case 1: + penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.)); + break; + case 2: + penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.)); + break; + case 3: + penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.)); + break; + case 4: + penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.)); + break; + case 5: + penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.)); + break; + default: + assert(0); + } + } + +}; + +#endif //OBB_BOX_MINKOWSKI_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp new file mode 100644 index 00000000000..8da554ef14d --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp @@ -0,0 +1,173 @@ +/* +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. +*/ + +//#define DISABLE_BVH + +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" + + +///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. +///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. +btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression) +:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression) +{ + //construct bvh from meshInterface +#ifndef DISABLE_BVH + + m_bvh = new btOptimizedBvh(); + btVector3 bvhAabbMin,bvhAabbMax; + meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax); + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + +#endif //DISABLE_BVH + +} + +btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) +:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression) +{ + //construct bvh from meshInterface +#ifndef DISABLE_BVH + + m_bvh = new btOptimizedBvh(); + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + +#endif //DISABLE_BVH + +} + +void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax) +{ + m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax ); + + m_localAabbMin.setMin(aabbMin); + m_localAabbMax.setMax(aabbMax); +} + + +void btBvhTriangleMeshShape::refitTree() +{ + m_bvh->refit( m_meshInterface ); + + recalcLocalAabb(); +} + +btBvhTriangleMeshShape::~btBvhTriangleMeshShape() +{ + delete m_bvh; +} + +//perform bvh tree traversal and report overlapping triangles to 'callback' +void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + +#ifdef DISABLE_BVH + //brute force traverse all triangles + btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax); +#else + + //first get all the nodes + + + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btStridingMeshInterface* m_meshInterface; + btTriangleCallback* m_callback; + btVector3 m_triangle[3]; + + + MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) + :m_meshInterface(meshInterface), + m_callback(callback) + { + } + + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + nodeSubPart); + + int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); + + const btVector3& meshScaling = m_meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + + int graphicsindex = gfxbase[j]; + + +#ifdef DEBUG_TRIANGLE_MESH + printf("%d ,",graphicsindex); +#endif //DEBUG_TRIANGLE_MESH + btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3( + graphicsbase[0]*meshScaling.getX(), + graphicsbase[1]*meshScaling.getY(), + graphicsbase[2]*meshScaling.getZ()); +#ifdef DEBUG_TRIANGLE_MESH + printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z()); +#endif //DEBUG_TRIANGLE_MESH + } + + m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); + m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + } + + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); + + +#endif//DISABLE_BVH + + +} + + +void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) + { + btTriangleMeshShape::setLocalScaling(scaling); + delete m_bvh; + ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work + m_bvh = new btOptimizedBvh(); + //rebuild the bvh... + m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); + + } +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h new file mode 100644 index 00000000000..4914d9f959c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h @@ -0,0 +1,75 @@ +/* +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. +*/ + +#ifndef BVH_TRIANGLE_MESH_SHAPE_H +#define BVH_TRIANGLE_MESH_SHAPE_H + +#include "btTriangleMeshShape.h" +#include "btOptimizedBvh.h" + +///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. +///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. +ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape +{ + + btOptimizedBvh* m_bvh; + bool m_useQuantizedAabbCompression; + bool m_pad[12];////need padding due to alignment + +public: + + btBvhTriangleMeshShape() :btTriangleMeshShape(0) {}; + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression); + + ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); + + virtual ~btBvhTriangleMeshShape(); + + + /* + virtual int getShapeType() const + { + return TRIANGLE_MESH_SHAPE_PROXYTYPE; + } + */ + + + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void refitTree(); + + ///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks + void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax); + + //debugging + virtual char* getName()const {return "BVHTRIANGLEMESH";} + + + virtual void setLocalScaling(const btVector3& scaling); + + btOptimizedBvh* getOptimizedBvh() + { + return m_bvh; + } + bool usesQuantizedAabbCompression() const + { + return m_useQuantizedAabbCompression; + } +} +; + +#endif //BVH_TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp new file mode 100644 index 00000000000..b7e15172da2 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp @@ -0,0 +1,146 @@ +/* +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. +*/ + + +#include "btCapsuleShape.h" + +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "LinearMath/btQuaternion.h" + +btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) +{ + m_implicitShapeDimensions.setValue(radius,0.5f*height,radius); +} + + + btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + + btVector3 supVec(0,0,0); + + btScalar maxDot(btScalar(-1e30)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + btVector3 vtx; + btScalar newDot; + + btScalar radius = getRadius(); + + + { + btVector3 pos(0,getHalfHeight(),0); + vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + { + btVector3 pos(0,-getHalfHeight(),0); + vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + + return supVec; + +} + + void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + + + btScalar radius = getRadius(); + + for (int j=0;j maxDot) + { + maxDot = newDot; + supportVerticesOut[j] = vtx; + } + } + { + btVector3 pos(0,-getHalfHeight(),0); + vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); + newDot = vec.dot(vtx); + if (newDot > maxDot) + { + maxDot = newDot; + supportVerticesOut[j] = vtx; + } + } + + } +} + + +void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +{ + //as an approximation, take the inertia of the box that bounds the spheres + + btTransform ident; + ident.setIdentity(); + + + btScalar radius = getRadius(); + + btVector3 halfExtents(radius,radius+getHalfHeight(),radius); + + btScalar margin = CONVEX_DISTANCE_MARGIN; + + btScalar lx=btScalar(2.)*(halfExtents[0]+margin); + btScalar ly=btScalar(2.)*(halfExtents[1]+margin); + btScalar lz=btScalar(2.)*(halfExtents[2]+margin); + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(.08333333); + + inertia[0] = scaledmass * (y2+z2); + inertia[1] = scaledmass * (x2+z2); + inertia[2] = scaledmass * (x2+y2); + +} + + + + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h new file mode 100644 index 00000000000..27da8adefa5 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h @@ -0,0 +1,60 @@ +/* +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. +*/ + +#ifndef BT_CAPSULE_SHAPE_H +#define BT_CAPSULE_SHAPE_H + +#include "btConvexShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types + + +///btCapsuleShape represents a capsule around the Y axis +///A more general solution that can represent capsules is the btMultiSphereShape +class btCapsuleShape : public btConvexShape +{ + +public: + btCapsuleShape(btScalar radius,btScalar height); + + ///CollisionShape Interface + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + + /// btConvexShape Interface + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; } + + virtual char* getName()const + { + return "CapsuleShape"; + } + + btScalar getRadius() const + { + return m_implicitShapeDimensions.getX(); + } + + btScalar getHalfHeight() const + { + return m_implicitShapeDimensions.getY(); + } + +}; + + + +#endif //BT_CAPSULE_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h new file mode 100644 index 00000000000..4730264d3df --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionMargin.h @@ -0,0 +1,26 @@ +/* +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. +*/ + +#ifndef COLLISION_MARGIN_H +#define COLLISION_MARGIN_H + +//used by Gjk and some other algorithms + +#define CONVEX_DISTANCE_MARGIN btScalar(0.04)// btScalar(0.1)//;//btScalar(0.01) + + + +#endif //COLLISION_MARGIN_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp new file mode 100644 index 00000000000..81d82428f4c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp @@ -0,0 +1,85 @@ +/* +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. +*/ + +#include "BulletCollision/CollisionShapes/btCollisionShape.h" + + +/* + Make sure this dummy function never changes so that it + can be used by probes that are checking whether the + library is actually installed. +*/ +extern "C" void btBulletCollisionProbe () {} + + + +void btCollisionShape::getBoundingSphere(btVector3& center,btScalar& radius) const +{ + btTransform tr; + tr.setIdentity(); + btVector3 aabbMin,aabbMax; + + getAabb(tr,aabbMin,aabbMax); + + radius = (aabbMax-aabbMin).length()*btScalar(0.5); + center = (aabbMin+aabbMax)*btScalar(0.5); +} + +btScalar btCollisionShape::getAngularMotionDisc() const +{ + btVector3 center; + btScalar disc; + getBoundingSphere(center,disc); + disc += (center).length(); + return disc; +} + +void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) +{ + //start with static aabb + getAabb(curTrans,temporalAabbMin,temporalAabbMax); + + btScalar temporalAabbMaxx = temporalAabbMax.getX(); + btScalar temporalAabbMaxy = temporalAabbMax.getY(); + btScalar temporalAabbMaxz = temporalAabbMax.getZ(); + btScalar temporalAabbMinx = temporalAabbMin.getX(); + btScalar temporalAabbMiny = temporalAabbMin.getY(); + btScalar temporalAabbMinz = temporalAabbMin.getZ(); + + // add linear motion + btVector3 linMotion = linvel*timeStep; + //todo: simd would have a vector max/min operation, instead of per-element access + if (linMotion.x() > btScalar(0.)) + temporalAabbMaxx += linMotion.x(); + else + temporalAabbMinx += linMotion.x(); + if (linMotion.y() > btScalar(0.)) + temporalAabbMaxy += linMotion.y(); + else + temporalAabbMiny += linMotion.y(); + if (linMotion.z() > btScalar(0.)) + temporalAabbMaxz += linMotion.z(); + else + temporalAabbMinz += linMotion.z(); + + //add conservative angular motion + btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep; + btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion); + temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz); + temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz); + + temporalAabbMin -= angularMotion3d; + temporalAabbMax += angularMotion3d; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h new file mode 100644 index 00000000000..96268734a83 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h @@ -0,0 +1,94 @@ +/* +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. +*/ + +#ifndef COLLISION_SHAPE_H +#define COLLISION_SHAPE_H + +#include "../../LinearMath/btTransform.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btMatrix3x3.h" +#include "../../LinearMath/btPoint3.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" //for the shape types + +///btCollisionShape provides interface for collision shapes that can be shared among btCollisionObjects. +class btCollisionShape +{ +public: + + btCollisionShape() + { + } + virtual ~btCollisionShape() + { + } + + ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + + virtual void getBoundingSphere(btVector3& center,btScalar& radius) const; + + ///getAngularMotionDisc returns the maximus radius needed for Conservative Advancement to handle time-of-impact with rotations. + virtual btScalar getAngularMotionDisc() const; + + + ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep) + ///result is conservative + void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax); + +#ifndef __SPU__ + + inline bool isPolyhedral() const + { + return btBroadphaseProxy::isPolyhedral(getShapeType()); + } + + inline bool isConvex() const + { + return btBroadphaseProxy::isConvex(getShapeType()); + } + inline bool isConcave() const + { + return btBroadphaseProxy::isConcave(getShapeType()); + } + inline bool isCompound() const + { + return btBroadphaseProxy::isCompound(getShapeType()); + } + + ///isInfinite is used to catch simulation error (aabb check) + inline bool isInfinite() const + { + return btBroadphaseProxy::isInfinite(getShapeType()); + } + + virtual int getShapeType() const=0; + virtual void setLocalScaling(const btVector3& scaling) =0; + virtual const btVector3& getLocalScaling() const =0; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) = 0; + + +//debugging support + virtual char* getName()const =0 ; +#endif //__SPU__ + + + + virtual void setMargin(btScalar margin) = 0; + virtual btScalar getMargin() const = 0; + +}; + +#endif //COLLISION_SHAPE_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp new file mode 100644 index 00000000000..a4712b3e925 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -0,0 +1,100 @@ +/* +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. +*/ + +#include "btCompoundShape.h" + + +#include "btCollisionShape.h" + + +btCompoundShape::btCompoundShape() +:m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)), +m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)), +m_aabbTree(0), +m_collisionMargin(btScalar(0.)), +m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)) +{ +} + + +btCompoundShape::~btCompoundShape() +{ +} + +void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) +{ + m_childTransforms.push_back(localTransform); + m_childShapes.push_back(shape); + + //extend the local aabbMin/aabbMax + btVector3 localAabbMin,localAabbMax; + shape->getAabb(localTransform,localAabbMin,localAabbMax); + for (int i=0;i<3;i++) + { + if (m_localAabbMin[i] > localAabbMin[i]) + { + m_localAabbMin[i] = localAabbMin[i]; + } + if (m_localAabbMax[i] < localAabbMax[i]) + { + m_localAabbMax[i] = localAabbMax[i]; + } + + } +} + + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btPoint3 center = trans(localCenter); + + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + extent += btVector3(getMargin(),getMargin(),getMargin()); + + aabbMin = center - extent; + aabbMax = center + extent; +} + +void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +{ + //approximation: take the inertia from the aabb for now + btTransform ident; + ident.setIdentity(); + btVector3 aabbMin,aabbMax; + getAabb(ident,aabbMin,aabbMax); + + btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); + + btScalar lx=btScalar(2.)*(halfExtents.x()); + btScalar ly=btScalar(2.)*(halfExtents.y()); + btScalar lz=btScalar(2.)*(halfExtents.z()); + + inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz); + inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz); + inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly); + +} + + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h new file mode 100644 index 00000000000..86dc1f80947 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h @@ -0,0 +1,117 @@ +/* +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. +*/ + +#ifndef COMPOUND_SHAPE_H +#define COMPOUND_SHAPE_H + +#include "btCollisionShape.h" + +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btTransform.h" +#include "../../LinearMath/btMatrix3x3.h" +#include "btCollisionMargin.h" +#include "../../LinearMath/btAlignedObjectArray.h" + +class btOptimizedBvh; + +/// btCompoundShape allows to store multiple other btCollisionShapes +/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape. +class btCompoundShape : public btCollisionShape +{ + btAlignedObjectArray m_childTransforms; + btAlignedObjectArray m_childShapes; + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + + btOptimizedBvh* m_aabbTree; + +public: + btCompoundShape(); + + virtual ~btCompoundShape(); + + void addChildShape(const btTransform& localTransform,btCollisionShape* shape); + + int getNumChildShapes() const + { + return int (m_childShapes.size()); + } + + btCollisionShape* getChildShape(int index) + { + return m_childShapes[index]; + } + const btCollisionShape* getChildShape(int index) const + { + return m_childShapes[index]; + } + + btTransform& getChildTransform(int index) + { + return m_childTransforms[index]; + } + const btTransform& getChildTransform(int index) const + { + return m_childTransforms[index]; + } + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + + virtual void setLocalScaling(const btVector3& scaling) + { + m_localScaling = scaling; + } + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + + virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;} + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + } + virtual btScalar getMargin() const + { + return m_collisionMargin; + } + virtual char* getName()const + { + return "Compound"; + } + + //this is optional, but should make collision queries faster, by culling non-overlapping nodes + void createAabbTreeFromChildren(); + + const btOptimizedBvh* getAabbTree() const + { + return m_aabbTree; + } + +private: + btScalar m_collisionMargin; +protected: + btVector3 m_localScaling; + +}; + + + +#endif //COMPOUND_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.cpp new file mode 100644 index 00000000000..5103500a012 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.cpp @@ -0,0 +1,28 @@ + +/* +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. +*/ + + +#include "btConcaveShape.h" + +btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.)) +{ + +} + +btConcaveShape::~btConcaveShape() +{ + +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h new file mode 100644 index 00000000000..73f974e4ee9 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h @@ -0,0 +1,50 @@ +/* +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. +*/ + +#ifndef CONCAVE_SHAPE_H +#define CONCAVE_SHAPE_H + +#include "btCollisionShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btTriangleCallback.h" + + +///Concave shape proves an interface concave shapes that can produce triangles that overlapping a given AABB. +///Static triangle mesh, infinite plane, height field/landscapes are example that implement this interface. +class btConcaveShape : public btCollisionShape +{ +protected: + btScalar m_collisionMargin; + +public: + btConcaveShape(); + + virtual ~btConcaveShape(); + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const = 0; + + virtual btScalar getMargin() const { + return m_collisionMargin; + } + virtual void setMargin(btScalar collisionMargin) + { + m_collisionMargin = collisionMargin; + } + + + +}; + +#endif //CONCAVE_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp new file mode 100644 index 00000000000..207b3024bc3 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.cpp @@ -0,0 +1,133 @@ +/* +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. +*/ + +#include "btConeShape.h" +#include "LinearMath/btPoint3.h" + + + +btConeShape::btConeShape (btScalar radius,btScalar height): +m_radius (radius), +m_height(height) +{ + setConeUpIndex(1); + btVector3 halfExtents; + m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height)); +} + +btConeShapeZ::btConeShapeZ (btScalar radius,btScalar height): +btConeShape(radius,height) +{ + setConeUpIndex(2); +} + +btConeShapeX::btConeShapeX (btScalar radius,btScalar height): +btConeShape(radius,height) +{ + setConeUpIndex(0); +} + +///choose upAxis index +void btConeShape::setConeUpIndex(int upIndex) +{ + switch (upIndex) + { + case 0: + m_coneIndices[0] = 1; + m_coneIndices[1] = 0; + m_coneIndices[2] = 2; + break; + case 1: + m_coneIndices[0] = 0; + m_coneIndices[1] = 1; + m_coneIndices[2] = 2; + break; + case 2: + m_coneIndices[0] = 0; + m_coneIndices[1] = 2; + m_coneIndices[2] = 1; + break; + default: + assert(0); + }; +} + +btVector3 btConeShape::coneLocalSupport(const btVector3& v) const +{ + + btScalar halfHeight = m_height * btScalar(0.5); + + if (v[m_coneIndices[1]] > v.length() * m_sinAngle) + { + btVector3 tmp; + + tmp[m_coneIndices[0]] = btScalar(0.); + tmp[m_coneIndices[1]] = halfHeight; + tmp[m_coneIndices[2]] = btScalar(0.); + return tmp; + } + else { + btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]); + if (s > SIMD_EPSILON) { + btScalar d = m_radius / s; + btVector3 tmp; + tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d; + tmp[m_coneIndices[1]] = -halfHeight; + tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d; + return tmp; + } + else { + btVector3 tmp; + tmp[m_coneIndices[0]] = btScalar(0.); + tmp[m_coneIndices[1]] = -halfHeight; + tmp[m_coneIndices[2]] = btScalar(0.); + return tmp; + } + } + +} + +btVector3 btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const +{ + return coneLocalSupport(vec); +} + +void btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + for (int i=0;i maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + return supVec; +} + +void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + btScalar newDot; + //use 'w' component of supportVerticesOut? + { + for (int i=0;i supportVerticesOut[j][3]) + { + //WARNING: don't swap next lines, the w component would get overwritten! + supportVerticesOut[j] = vtx; + supportVerticesOut[j][3] = newDot; + } + } + } + + + +} + + + +btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const +{ + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; +} + + + + + + + + + +//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection +//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo +int btConvexHullShape::getNumVertices() const +{ + return m_points.size(); +} + +int btConvexHullShape::getNumEdges() const +{ + return m_points.size(); +} + +void btConvexHullShape::getEdge(int i,btPoint3& pa,btPoint3& pb) const +{ + + int index0 = i%m_points.size(); + int index1 = (i+1)%m_points.size(); + pa = m_points[index0]*m_localScaling; + pb = m_points[index1]*m_localScaling; +} + +void btConvexHullShape::getVertex(int i,btPoint3& vtx) const +{ + vtx = m_points[i]*m_localScaling; +} + +int btConvexHullShape::getNumPlanes() const +{ + return 0; +} + +void btConvexHullShape::getPlane(btVector3& ,btPoint3& ,int ) const +{ + + btAssert(0); +} + +//not yet +bool btConvexHullShape::isInside(const btPoint3& ,btScalar ) const +{ + assert(0); + return false; +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h new file mode 100644 index 00000000000..3fd5e382525 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h @@ -0,0 +1,76 @@ +/* +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. +*/ + +#ifndef CONVEX_HULL_SHAPE_H +#define CONVEX_HULL_SHAPE_H + +#include "btPolyhedralConvexShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "../../LinearMath/btAlignedObjectArray.h" + +///ConvexHullShape implements an implicit (getSupportingVertex) Convex Hull of a Point Cloud (vertices) +///No connectivity is needed. localGetSupportingVertex iterates linearly though all vertices. +///on modern hardware, due to cache coherency this isn't that bad. Complex algorithms tend to trash the cash. +///(memory is much slower then the cpu) +ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexShape +{ + btAlignedObjectArray m_points; + +public: + + + ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory. + ///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint. + ///btConvexHullShape make an internal copy of the points. + btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btPoint3)); + + void addPoint(const btPoint3& point); + + btPoint3* getPoints() + { + return &m_points[0]; + } + + int getNumPoints() + { + return m_points.size(); + } + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + + virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; } + + //debugging + virtual char* getName()const {return "Convex";} + + + virtual int getNumVertices() const; + virtual int getNumEdges() const; + virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const; + virtual void getVertex(int i,btPoint3& vtx) const; + virtual int getNumPlanes() const; + virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const; + virtual bool isInside(const btPoint3& pt,btScalar tolerance) const; + + + +}; + + +#endif //CONVEX_HULL_SHAPE_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp new file mode 100644 index 00000000000..7edf1ea6db8 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp @@ -0,0 +1,77 @@ +/* +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. +*/ + +#include "btConvexShape.h" + + +btConvexShape::btConvexShape() +: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), +m_collisionMargin(CONVEX_DISTANCE_MARGIN) +{ +} + + +void btConvexShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} + + + +void btConvexShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const +{ + + btScalar margin = getMargin(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + + btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); + + btVector3 tmp = trans(sv); + maxAabb[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); + minAabb[i] = tmp[i]-margin; + } +}; + + +btVector3 btConvexShape::localGetSupportingVertex(const btVector3& vec)const +{ +#ifndef __SPU__ + + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; + +#else + return btVector3(0,0,0); +#endif //__SPU__ + + } + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h new file mode 100644 index 00000000000..746f383dfc7 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h @@ -0,0 +1,127 @@ +/* +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. +*/ + +#ifndef CONVEX_SHAPE_INTERFACE1 +#define CONVEX_SHAPE_INTERFACE1 + +#include "btCollisionShape.h" + +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btTransform.h" +#include "../../LinearMath/btMatrix3x3.h" +#include "btCollisionMargin.h" + +//todo: get rid of this btConvexCastResult thing! +struct btConvexCastResult; +#define MAX_PREFERRED_PENETRATION_DIRECTIONS 10 + +/// btConvexShape is an abstract shape interface. +/// The explicit part provides plane-equations, the implicit part provides GetClosestPoint interface. +/// used in combination with GJK or btConvexCast +ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape +{ + +protected: + + //local scaling. collisionMargin is not scaled ! + btVector3 m_localScaling; + + btVector3 m_implicitShapeDimensions; + + btScalar m_collisionMargin; + + btScalar m_padding[2]; + + + + +public: + btConvexShape(); + + virtual ~btConvexShape() + { + + } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; +#ifndef __SPU__ + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; + + //notice that the vectors should be unit length + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; +#endif //#ifndef __SPU__ + + const btVector3& getImplicitShapeDimensions() const + { + return m_implicitShapeDimensions; + } + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + getAabbSlow(t,aabbMin,aabbMax); + } + + + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + const btVector3& getLocalScalingNV() const + { + return m_localScaling; + } + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + } + virtual btScalar getMargin() const + { + return m_collisionMargin; + } + + btScalar getMarginNV() const + { + return m_collisionMargin; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 0; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + (void)penetrationVector; + (void)index; + btAssert(0); + } + + + +} +; + + + +#endif //CONVEX_SHAPE_INTERFACE1 diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp new file mode 100644 index 00000000000..6941030b15f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp @@ -0,0 +1,205 @@ +/* +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. +*/ +#include "btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btQuaternion.h" +#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" + + +btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface) +:m_stridingMesh(meshInterface) +{ + recalcLocalAabb(); +} + + + + +///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once +///but then we are duplicating +class LocalSupportVertexCallback: public btInternalTriangleIndexCallback +{ + + btVector3 m_supportVertexLocal; +public: + + btScalar m_maxDot; + btVector3 m_supportVecLocal; + + LocalSupportVertexCallback(const btVector3& supportVecLocal) + : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), + m_maxDot(btScalar(-1e30)), + m_supportVecLocal(supportVecLocal) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + (void)triangleIndex; + (void)partId; + + for (int i=0;i<3;i++) + { + btScalar dot = m_supportVecLocal.dot(triangle[i]); + if (dot > m_maxDot) + { + m_maxDot = dot; + m_supportVertexLocal = triangle[i]; + } + } + } + + btVector3 GetSupportVertexLocal() + { + return m_supportVertexLocal; + } + +}; + + + + + +btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + LocalSupportVertexCallback supportCallback(vec); + btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); + supVec = supportCallback.GetSupportVertexLocal(); + + return supVec; +} + +void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + //use 'w' component of supportVerticesOut? + { + for (int i=0;iInternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax); + supportVerticesOut[j] = supportCallback.GetSupportVertexLocal(); + } + +} + + + +btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const +{ + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; +} + + + + + + + + + +//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection +//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo +int btConvexTriangleMeshShape::getNumVertices() const +{ + //cache this? + return 0; + +} + +int btConvexTriangleMeshShape::getNumEdges() const +{ + return 0; +} + +void btConvexTriangleMeshShape::getEdge(int ,btPoint3& ,btPoint3& ) const +{ + btAssert(0); +} + +void btConvexTriangleMeshShape::getVertex(int ,btPoint3& ) const +{ + btAssert(0); +} + +int btConvexTriangleMeshShape::getNumPlanes() const +{ + return 0; +} + +void btConvexTriangleMeshShape::getPlane(btVector3& ,btPoint3& ,int ) const +{ + btAssert(0); +} + +//not yet +bool btConvexTriangleMeshShape::isInside(const btPoint3& ,btScalar ) const +{ + btAssert(0); + return false; +} + + + +void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + m_stridingMesh->setScaling(scaling); + + recalcLocalAabb(); + +} + + +const btVector3& btConvexTriangleMeshShape::getLocalScaling() const +{ + return m_stridingMesh->getScaling(); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h new file mode 100644 index 00000000000..34ee7af744c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h @@ -0,0 +1,51 @@ +#ifndef CONVEX_TRIANGLEMESH_SHAPE_H +#define CONVEX_TRIANGLEMESH_SHAPE_H + + +#include "btPolyhedralConvexShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types + + +/// btConvexTriangleMeshShape is a convex hull of a triangle mesh. If you just have a point cloud, you can use btConvexHullShape instead. +/// It uses the btStridingMeshInterface instead of a point cloud. This can avoid the duplication of the triangle mesh data. +class btConvexTriangleMeshShape : public btPolyhedralConvexShape +{ + + class btStridingMeshInterface* m_stridingMesh; + +public: + btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface); + + class btStridingMeshInterface* getStridingMesh() + { + return m_stridingMesh; + } + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual int getShapeType()const { return CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; } + + //debugging + virtual char* getName()const {return "ConvexTrimesh";} + + virtual int getNumVertices() const; + virtual int getNumEdges() const; + virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const; + virtual void getVertex(int i,btPoint3& vtx) const; + virtual int getNumPlanes() const; + virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const; + virtual bool isInside(const btPoint3& pt,btScalar tolerance) const; + + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + +}; + + + +#endif //CONVEX_TRIANGLEMESH_SHAPE_H + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp new file mode 100644 index 00000000000..1666afb3b88 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp @@ -0,0 +1,206 @@ +/* +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. +*/ +#include "btCylinderShape.h" +#include "LinearMath/btPoint3.h" + +btCylinderShape::btCylinderShape (const btVector3& halfExtents) +:btBoxShape(halfExtents), +m_upAxis(1) +{ + recalcLocalAabb(); +} + + +btCylinderShapeX::btCylinderShapeX (const btVector3& halfExtents) +:btCylinderShape(halfExtents) +{ + m_upAxis = 0; + recalcLocalAabb(); +} + + +btCylinderShapeZ::btCylinderShapeZ (const btVector3& halfExtents) +:btCylinderShape(halfExtents) +{ + m_upAxis = 2; + recalcLocalAabb(); +} + +void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + //skip the box 'getAabb' + btPolyhedralConvexShape::getAabb(t,aabbMin,aabbMax); +} + + +inline btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) +{ +const int cylinderUpAxis = 0; +const int XX = 1; +const int YY = 0; +const int ZZ = 2; + + //mapping depends on how cylinder local orientation is + // extents of the cylinder is: X,Y is for radius, and Z for height + + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return tmp; + } + else + { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return tmp; + } + + +} + + + + + + +inline btVector3 CylinderLocalSupportY(const btVector3& halfExtents,const btVector3& v) +{ + +const int cylinderUpAxis = 1; +const int XX = 0; +const int YY = 1; +const int ZZ = 2; + + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return tmp; + } + else + { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return tmp; + } + +} + +inline btVector3 CylinderLocalSupportZ(const btVector3& halfExtents,const btVector3& v) +{ +const int cylinderUpAxis = 2; +const int XX = 0; +const int YY = 2; +const int ZZ = 1; + + //mapping depends on how cylinder local orientation is + // extents of the cylinder is: X,Y is for radius, and Z for height + + + btScalar radius = halfExtents[XX]; + btScalar halfHeight = halfExtents[cylinderUpAxis]; + + + btVector3 tmp; + btScalar d ; + + btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]); + if (s != btScalar(0.0)) + { + d = radius / s; + tmp[XX] = v[XX] * d; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = v[ZZ] * d; + return tmp; + } + else + { + tmp[XX] = radius; + tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight; + tmp[ZZ] = btScalar(0.0); + return tmp; + } + + +} + +btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + return CylinderLocalSupportX(getHalfExtents(),vec); +} + + +btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + return CylinderLocalSupportZ(getHalfExtents(),vec); +} +btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + return CylinderLocalSupportY(getHalfExtents(),vec); +} + +void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + for (int i=0;i=0); + btAssert(y>=0); + btAssert(xstartX) + startX = quantizedAabbMin[1]; + if (quantizedAabbMax[1]startJ) + startJ = quantizedAabbMin[2]; + if (quantizedAabbMax[2]startX) + startX = quantizedAabbMin[0]; + if (quantizedAabbMax[0]startJ) + startJ = quantizedAabbMin[2]; + if (quantizedAabbMax[2]startX) + startX = quantizedAabbMin[0]; + if (quantizedAabbMax[0]startJ) + startJ = quantizedAabbMin[1]; + if (quantizedAabbMax[1]processTriangle(vertices,x,j); + //second triangle + getVertex(x,j,vertices[0]); + getVertex(x+1,j+1,vertices[1]); + getVertex(x,j+1,vertices[2]); + callback->processTriangle(vertices,x,j); + } else + { + //first triangle + getVertex(x,j,vertices[0]); + getVertex(x,j+1,vertices[1]); + getVertex(x+1,j,vertices[2]); + callback->processTriangle(vertices,x,j); + //second triangle + getVertex(x+1,j,vertices[0]); + getVertex(x,j+1,vertices[1]); + getVertex(x+1,j+1,vertices[2]); + callback->processTriangle(vertices,x,j); + } + } + } + + + +} + +void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) +{ + //moving concave objects not supported + + inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); +} + +void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} +const btVector3& btHeightfieldTerrainShape::getLocalScaling() const +{ + return m_localScaling; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h new file mode 100644 index 00000000000..49f3e106733 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h @@ -0,0 +1,88 @@ +/* +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. +*/ + +#ifndef HEIGHTFIELD_TERRAIN_SHAPE_H +#define HEIGHTFIELD_TERRAIN_SHAPE_H + +#include "btConcaveShape.h" + +///btHeightfieldTerrainShape simulates a 2D heightfield terrain +class btHeightfieldTerrainShape : public btConcaveShape +{ +protected: + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + + ///terrain data + int m_width; + int m_length; + btScalar m_maxHeight; + union + { + unsigned char* m_heightfieldDataUnsignedChar; + btScalar* m_heightfieldDataFloat; + void* m_heightfieldDataUnknown; + }; + + bool m_useFloatData; + bool m_flipQuadEdges; + bool m_useDiamondSubdivision; + + int m_upAxis; + + btVector3 m_localScaling; + + virtual btScalar getHeightFieldValue(int x,int y) const; + void quantizeWithClamp(int* out, const btVector3& point) const; + void getVertex(int x,int y,btVector3& vertex) const; + + inline bool testQuantizedAabbAgainstQuantizedAabb(int* aabbMin1, int* aabbMax1,const int* aabbMin2,const int* aabbMax2) const + { + bool overlap = true; + overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; + overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; + overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; + return overlap; + } + +public: + btHeightfieldTerrainShape(int width,int height,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges); + + virtual ~btHeightfieldTerrainShape(); + + + void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;} + + virtual int getShapeType() const + { + return TERRAIN_SHAPE_PROXYTYPE; + } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + + virtual void setLocalScaling(const btVector3& scaling); + + virtual const btVector3& getLocalScaling() const; + + //debugging + virtual char* getName()const {return "HEIGHTFIELD";} + +}; + +#endif //HEIGHTFIELD_TERRAIN_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp new file mode 100644 index 00000000000..015314bc09f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp @@ -0,0 +1,57 @@ +/* +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. +*/ + +#include "btMinkowskiSumShape.h" + + +btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB) +:m_shapeA(shapeA), +m_shapeB(shapeB) +{ + m_transA.setIdentity(); + m_transB.setIdentity(); +} + +btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis())); + btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(vec*m_transB.getBasis())); + return supVertexA + supVertexB; +} + +void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + //todo: could make recursive use of batching. probably this shape is not used frequently. + for (int i=0;igetMargin() + m_shapeB->getMargin(); +} + + +void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +{ + (void)mass; + btAssert(0); + inertia.setValue(0,0,0); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h new file mode 100644 index 00000000000..198faaff9f9 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h @@ -0,0 +1,62 @@ +/* +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. +*/ + +#ifndef MINKOWSKI_SUM_SHAPE_H +#define MINKOWSKI_SUM_SHAPE_H + +#include "btConvexShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types + +/// btMinkowskiSumShape represents implicit (getSupportingVertex) based minkowski sum of two convex implicit shapes. +class btMinkowskiSumShape : public btConvexShape +{ + + btTransform m_transA; + btTransform m_transB; + const btConvexShape* m_shapeA; + const btConvexShape* m_shapeB; + +public: + + btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB); + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + + void setTransformA(const btTransform& transA) { m_transA = transA;} + void setTransformB(const btTransform& transB) { m_transB = transB;} + + const btTransform& getTransformA()const { return m_transA;} + const btTransform& GetTransformB()const { return m_transB;} + + + virtual int getShapeType() const { return MINKOWSKI_SUM_SHAPE_PROXYTYPE; } + + virtual btScalar getMargin() const; + + const btConvexShape* getShapeA() const { return m_shapeA;} + const btConvexShape* getShapeB() const { return m_shapeB;} + + virtual char* getName()const + { + return "MinkowskiSum"; + } +}; + +#endif //MINKOWSKI_SUM_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp new file mode 100644 index 00000000000..6015a618082 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp @@ -0,0 +1,148 @@ +/* +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. +*/ + +#include "btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "LinearMath/btQuaternion.h" + +btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,const btVector3* positions,const btScalar* radi,int numSpheres) +:m_inertiaHalfExtents(inertiaHalfExtents) +{ + btScalar startMargin = btScalar(1e30); + + m_numSpheres = numSpheres; + for (int i=0;i maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + + return supVec; + +} + + void btMultiSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + + for (int j=0;j maxDot) + { + maxDot = newDot; + supportVerticesOut[j] = vtx; + } + } + } +} + + + + + + + + +void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +{ + //as an approximation, take the inertia of the box that bounds the spheres + + btTransform ident; + ident.setIdentity(); +// btVector3 aabbMin,aabbMax; + +// getAabb(ident,aabbMin,aabbMax); + + btVector3 halfExtents = m_inertiaHalfExtents;//(aabbMax - aabbMin)* btScalar(0.5); + + btScalar margin = CONVEX_DISTANCE_MARGIN; + + btScalar lx=btScalar(2.)*(halfExtents[0]+margin); + btScalar ly=btScalar(2.)*(halfExtents[1]+margin); + btScalar lz=btScalar(2.)*(halfExtents[2]+margin); + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(.08333333); + + inertia[0] = scaledmass * (y2+z2); + inertia[1] = scaledmass * (x2+z2); + inertia[2] = scaledmass * (x2+y2); + +} + + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h new file mode 100644 index 00000000000..1897b474057 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h @@ -0,0 +1,74 @@ +/* +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. +*/ + +#ifndef MULTI_SPHERE_MINKOWSKI_H +#define MULTI_SPHERE_MINKOWSKI_H + +#include "btConvexShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types + +#define MAX_NUM_SPHERES 5 + +///btMultiSphereShape represents implicit convex hull of a collection of spheres (using getSupportingVertex) +class btMultiSphereShape : public btConvexShape + +{ + + btVector3 m_localPositions[MAX_NUM_SPHERES]; + btScalar m_radi[MAX_NUM_SPHERES]; + btVector3 m_inertiaHalfExtents; + + int m_numSpheres; + + + + +public: + btMultiSphereShape (const btVector3& inertiaHalfExtents,const btVector3* positions,const btScalar* radi,int numSpheres); + + ///CollisionShape Interface + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + + /// btConvexShape Interface + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + int getSphereCount() const + { + return m_numSpheres; + } + + const btVector3& getSpherePosition(int index) const + { + return m_localPositions[index]; + } + + btScalar getSphereRadius(int index) const + { + return m_radi[index]; + } + + virtual int getShapeType() const { return MULTI_SPHERE_SHAPE_PROXYTYPE; } + + virtual char* getName()const + { + return "MultiSphere"; + } + +}; + + +#endif //MULTI_SPHERE_MINKOWSKI_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp new file mode 100644 index 00000000000..44438a24455 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp @@ -0,0 +1,845 @@ +/* +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. +*/ + +#include "btOptimizedBvh.h" +#include "btStridingMeshInterface.h" +#include "LinearMath/btAabbUtil2.h" +#include "LinearMath/btIDebugDraw.h" + + + +btOptimizedBvh::btOptimizedBvh() : m_useQuantization(false), + m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY) + //m_traversalMode(TRAVERSAL_STACKLESS) + //m_traversalMode(TRAVERSAL_RECURSIVE) +{ + +} + + +void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax) +{ + m_useQuantization = useQuantizedAabbCompression; + + + // NodeArray triangleNodes; + + struct NodeTriangleCallback : public btInternalTriangleIndexCallback + { + + NodeArray& m_triangleNodes; + + NodeTriangleCallback& operator=(NodeTriangleCallback& other) + { + m_triangleNodes = other.m_triangleNodes; + return *this; + } + + NodeTriangleCallback(NodeArray& triangleNodes) + :m_triangleNodes(triangleNodes) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + btOptimizedBvhNode node; + btVector3 aabbMin,aabbMax; + aabbMin.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + aabbMax.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); + aabbMin.setMin(triangle[0]); + aabbMax.setMax(triangle[0]); + aabbMin.setMin(triangle[1]); + aabbMax.setMax(triangle[1]); + aabbMin.setMin(triangle[2]); + aabbMax.setMax(triangle[2]); + + //with quantization? + node.m_aabbMinOrg = aabbMin; + node.m_aabbMaxOrg = aabbMax; + + node.m_escapeIndex = -1; + + //for child nodes + node.m_subPart = partId; + node.m_triangleIndex = triangleIndex; + m_triangleNodes.push_back(node); + } + }; + struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback + { + QuantizedNodeArray& m_triangleNodes; + const btOptimizedBvh* m_optimizedTree; // for quantization + + QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other) + { + m_triangleNodes = other.m_triangleNodes; + m_optimizedTree = other.m_optimizedTree; + return *this; + } + + QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btOptimizedBvh* tree) + :m_triangleNodes(triangleNodes),m_optimizedTree(tree) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + btAssert(partId==0); + //negative indices are reserved for escapeIndex + btAssert(triangleIndex>=0); + + btQuantizedBvhNode node; + btVector3 aabbMin,aabbMax; + aabbMin.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + aabbMax.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); + aabbMin.setMin(triangle[0]); + aabbMax.setMax(triangle[0]); + aabbMin.setMin(triangle[1]); + aabbMax.setMax(triangle[1]); + aabbMin.setMin(triangle[2]); + aabbMax.setMax(triangle[2]); + + m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMin[0],aabbMin); + m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMax[0],aabbMax); + + node.m_escapeIndexOrTriangleIndex = triangleIndex; + + m_triangleNodes.push_back(node); + } + }; + + + + int numLeafNodes = 0; + + + if (m_useQuantization) + { + + //initialize quantization values + setQuantizationValues(bvhAabbMin,bvhAabbMax); + + QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes,this); + + + triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax); + + //now we have an array of leafnodes in m_leafNodes + numLeafNodes = m_quantizedLeafNodes.size(); + + + m_quantizedContiguousNodes.resize(2*numLeafNodes); + + + } else + { + NodeTriangleCallback callback(m_leafNodes); + + btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); + btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + + triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax); + + //now we have an array of leafnodes in m_leafNodes + numLeafNodes = m_leafNodes.size(); + + m_contiguousNodes.resize(2*numLeafNodes); + } + + m_curNodeIndex = 0; + + buildTree(0,numLeafNodes); + + ///if the entire tree is small then subtree size, we need to create a header info for the tree + if(m_useQuantization && !m_SubtreeHeaders.size()) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]); + subtree.m_rootNodeIndex = 0; + subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); + } +} + + + +void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax) +{ + //incrementally initialize quantization values + btAssert(m_useQuantization); + + btAssert(aabbMin.getX() > m_bvhAabbMin.getX()); + btAssert(aabbMin.getY() > m_bvhAabbMin.getY()); + btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ()); + + btAssert(aabbMax.getX() < m_bvhAabbMax.getX()); + btAssert(aabbMax.getY() < m_bvhAabbMax.getY()); + btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ()); + + ///we should update all quantization values, using updateBvhNodes(meshInterface); + ///but we only update chunks that overlap the given aabb + + unsigned short quantizedQueryAabbMin[3]; + unsigned short quantizedQueryAabbMax[3]; + + quantizeWithClamp(&quantizedQueryAabbMin[0],aabbMin); + quantizeWithClamp(&quantizedQueryAabbMax[0],aabbMax); + + int i; + for (i=0;im_SubtreeHeaders.size();i++) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; + + bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap) + { + updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i); + + subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]); + } + } + +} + +///just for debugging, to visualize the individual patches/subtrees +#ifdef DEBUG_PATCH_COLORS +btVector3 color[4]= +{ + btVector3(255,0,0), + btVector3(0,255,0), + btVector3(0,0,255), + btVector3(0,255,255) +}; +#endif //DEBUG_PATCH_COLORS + + +void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index) +{ + (void)index; + + btAssert(m_useQuantization); + + int nodeSubPart=0; + + //get access info to trianglemesh data + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); + + btVector3 triangleVerts[3]; + btVector3 aabbMin,aabbMax; + const btVector3& meshScaling = meshInterface->getScaling(); + + int i; + for (i=endNode-1;i>=firstNode;i--) + { + + + btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i]; + if (curNode.isLeafNode()) + { + //recalc aabb from triangle data + int nodeTriangleIndex = curNode.getTriangleIndex(); + //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts, + + int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); + + + for (int j=2;j>=0;j--) + { + + int graphicsindex = gfxbase[j]; + btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); +#ifdef DEBUG_PATCH_COLORS + btVector3 mycolor = color[index&3]; + graphicsbase[8] = mycolor.getX(); + graphicsbase[9] = mycolor.getY(); + graphicsbase[10] = mycolor.getZ(); +#endif //DEBUG_PATCH_COLORS + + + triangleVerts[j] = btVector3( + graphicsbase[0]*meshScaling.getX(), + graphicsbase[1]*meshScaling.getY(), + graphicsbase[2]*meshScaling.getZ()); + } + + + + aabbMin.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + aabbMax.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); + aabbMin.setMin(triangleVerts[0]); + aabbMax.setMax(triangleVerts[0]); + aabbMin.setMin(triangleVerts[1]); + aabbMax.setMax(triangleVerts[1]); + aabbMin.setMin(triangleVerts[2]); + aabbMax.setMax(triangleVerts[2]); + + quantizeWithClamp(&curNode.m_quantizedAabbMin[0],aabbMin); + quantizeWithClamp(&curNode.m_quantizedAabbMax[0],aabbMax); + + } else + { + //combine aabb from both children + + btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1]; + + btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] : + &m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()]; + + + { + for (int i=0;i<3;i++) + { + curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i]; + if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i]) + curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i]; + + curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i]; + if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i]) + curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i]; + } + } + } + + } + + meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + + +} + +void btOptimizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin) +{ + //enlarge the AABB to avoid division by zero when initializing the quantization values + btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin); + m_bvhAabbMin = bvhAabbMin - clampValue; + m_bvhAabbMax = bvhAabbMax + clampValue; + btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin; + m_bvhQuantization = btVector3(btScalar(65535.0),btScalar(65535.0),btScalar(65535.0)) / aabbSize; +} + + +void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface) +{ + if (m_useQuantization) + { + //calculate new aabb + btVector3 aabbMin,aabbMax; + meshInterface->calculateAabbBruteForce(aabbMin,aabbMax); + + setQuantizationValues(aabbMin,aabbMax); + + updateBvhNodes(meshInterface,0,m_curNodeIndex,0); + + ///now update all subtree headers + + int i; + for (i=0;i gMaxStackDepth) + gMaxStackDepth = gStackDepth; +#endif //DEBUG_TREE_BUILDING + + + int splitAxis, splitIndex, i; + int numIndices =endIndex-startIndex; + int curIndex = m_curNodeIndex; + + assert(numIndices>0); + + if (numIndices==1) + { +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex); + + m_curNodeIndex++; + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + splitAxis = calcSplittingAxis(startIndex,endIndex); + + splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis); + + int internalNodeIndex = m_curNodeIndex; + + setInternalNodeAabbMax(m_curNodeIndex,btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30))); + setInternalNodeAabbMin(m_curNodeIndex,btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30))); + + for (i=startIndex;im_escapeIndex; + + int leftChildNodexIndex = m_curNodeIndex; + + //build left child tree + buildTree(startIndex,splitIndex); + + int rightChildNodexIndex = m_curNodeIndex; + //build right child tree + buildTree(splitIndex,endIndex); + +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + int escapeIndex = m_curNodeIndex - curIndex; + + if (m_useQuantization) + { + //escapeIndex is the number of nodes of this subtree + const int sizeQuantizedNode =sizeof(btQuantizedBvhNode); + const int treeSizeInBytes = escapeIndex * sizeQuantizedNode; + if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES) + { + updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex); + } + } + + setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex); + +} + +void btOptimizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex) +{ + btAssert(m_useQuantization); + + btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex]; + int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex(); + int leftSubTreeSizeInBytes = leftSubTreeSize * sizeof(btQuantizedBvhNode); + + btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex]; + int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex(); + int rightSubTreeSizeInBytes = rightSubTreeSize * sizeof(btQuantizedBvhNode); + + if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(leftChildNode); + subtree.m_rootNodeIndex = leftChildNodexIndex; + subtree.m_subtreeSize = leftSubTreeSize; + } + + if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(rightChildNode); + subtree.m_rootNodeIndex = rightChildNodexIndex; + subtree.m_subtreeSize = rightSubTreeSize; + } +} + + +int btOptimizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis) +{ + int i; + int splitIndex =startIndex; + int numIndices = endIndex - startIndex; + btScalar splitValue; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + for (i=startIndex;i splitValue) + { + //swap + swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); + btAssert(!unbal); + + return splitIndex; +} + + +int btOptimizedBvh::calcSplittingAxis(int startIndex,int endIndex) +{ + int i; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); + int numIndices = endIndex-startIndex; + + for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg); + isLeafNode = rootNode->m_escapeIndex == -1; + + if (isLeafNode && aabbOverlap) + { + nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); + } + + if (aabbOverlap || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->m_escapeIndex; + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +/* +///this was the original recursive traversal, before we optimized towards stackless traversal +void btOptimizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax); + if (aabbOverlap) + { + isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild); + if (isLeafNode) + { + nodeCallback->processNode(rootNode); + } else + { + walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax); + walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax); + } + } + +} +*/ + +void btOptimizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + bool aabbOverlap, isLeafNode; + + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax); + isLeafNode = currentNode->isLeafNode(); + + if (aabbOverlap) + { + if (isLeafNode) + { + nodeCallback->processNode(0,currentNode->getTriangleIndex()); + } else + { + //process left and right children + const btQuantizedBvhNode* leftChildNode = currentNode+1; + walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + + const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex(); + walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + } + } +} + + + + + + + +void btOptimizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const +{ + btAssert(m_useQuantization); + + int curIndex = startNodeIndex; + int walkIterations = 0; + int subTreeSize = endNodeIndex - startNodeIndex; + + const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; + int escapeIndex; + + bool aabbOverlap, isLeafNode; + + while (curIndex < endNodeIndex) + { + +//#define VISUALLY_ANALYZE_BVH 1 +#ifdef VISUALLY_ANALYZE_BVH + //some code snippet to debugDraw aabb, to visually analyze bvh structure + static int drawPatch = 0; + //need some global access to a debugDrawer + extern btIDebugDraw* debugDrawerPtr; + if (curIndex==drawPatch) + { + btVector3 aabbMin,aabbMax; + aabbMin = unQuantize(rootNode->m_quantizedAabbMin); + aabbMax = unQuantize(rootNode->m_quantizedAabbMax); + btVector3 color(1,0,0); + debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); + } +#endif//VISUALLY_ANALYZE_BVH + + //catch bugs in tree data + assert (walkIterations < subTreeSize); + + walkIterations++; + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + + if (isLeafNode && aabbOverlap) + { + nodeCallback->processNode(0,rootNode->getTriangleIndex()); + } + + if (aabbOverlap || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +//This traversal can be called from Playstation 3 SPU +void btOptimizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + int i; + + + for (i=0;im_SubtreeHeaders.size();i++) + { + const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; + + bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap) + { + walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, + subtree.m_rootNodeIndex, + subtree.m_rootNodeIndex+subtree.m_subtreeSize); + } + } +} + + + + +void btOptimizedBvh::reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + (void)nodeCallback; + (void)aabbMin; + (void)aabbMax; + //not yet, please use aabb + btAssert(0); +} + + +void btOptimizedBvh::quantizeWithClamp(unsigned short* out, const btVector3& point) const +{ + + btAssert(m_useQuantization); + + btVector3 clampedPoint(point); + clampedPoint.setMax(m_bvhAabbMin); + clampedPoint.setMin(m_bvhAabbMax); + + btVector3 v = (clampedPoint - m_bvhAabbMin) * m_bvhQuantization; + out[0] = (unsigned short)(v.getX()+0.5f); + out[1] = (unsigned short)(v.getY()+0.5f); + out[2] = (unsigned short)(v.getZ()+0.5f); +} + +btVector3 btOptimizedBvh::unQuantize(const unsigned short* vecIn) const +{ + btVector3 vecOut; + vecOut.setValue( + (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()), + (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()), + (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ())); + vecOut += m_bvhAabbMin; + return vecOut; +} + + +void btOptimizedBvh::swapLeafNodes(int i,int splitIndex) +{ + if (m_useQuantization) + { + btQuantizedBvhNode tmp = m_quantizedLeafNodes[i]; + m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex]; + m_quantizedLeafNodes[splitIndex] = tmp; + } else + { + btOptimizedBvhNode tmp = m_leafNodes[i]; + m_leafNodes[i] = m_leafNodes[splitIndex]; + m_leafNodes[splitIndex] = tmp; + } +} + +void btOptimizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex) +{ + if (m_useQuantization) + { + m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex]; + } else + { + m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex]; + } +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h new file mode 100644 index 00000000000..d5159586344 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h @@ -0,0 +1,330 @@ +/* +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. +*/ + +#ifndef OPTIMIZED_BVH_H +#define OPTIMIZED_BVH_H + + +#include "../../LinearMath/btVector3.h" + + +//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp + + + +class btStridingMeshInterface; + +//Note: currently we have 16 bytes per quantized node +#define MAX_SUBTREE_SIZE_IN_BYTES 2048 + + +///btQuantizedBvhNode is a compressed aabb node, 16 bytes. +///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). +ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode +{ + + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes + int m_escapeIndexOrTriangleIndex; + + bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrTriangleIndex >= 0); + } + int getEscapeIndex() const + { + btAssert(!isLeafNode()); + return -m_escapeIndexOrTriangleIndex; + } + int getTriangleIndex() const + { + btAssert(isLeafNode()); + return m_escapeIndexOrTriangleIndex; + } +} +; + +/// btOptimizedBvhNode contains both internal and leaf node information. +/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. +ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode +{ + //32 bytes + btVector3 m_aabbMinOrg; + btVector3 m_aabbMaxOrg; + + //4 + int m_escapeIndex; + + //8 + //for child nodes + int m_subPart; + int m_triangleIndex; + int m_padding[5];//bad, due to alignment + + +}; + + +///btBvhSubtreeInfo provides info to gather a subtree of limited size +ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo +{ +public: + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes, points to the root of the subtree + int m_rootNodeIndex; + //4 bytes + int m_subtreeSize; + int m_padding[3]; + + + void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) + { + m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0]; + m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1]; + m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2]; + m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0]; + m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1]; + m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2]; + } +} +; + + +class btNodeOverlapCallback +{ +public: + virtual ~btNodeOverlapCallback() {}; + + virtual void processNode(int subPart, int triangleIndex) = 0; +}; + +#include "../../LinearMath/btAlignedAllocator.h" +#include "../../LinearMath/btAlignedObjectArray.h" + + + +///for code readability: +typedef btAlignedObjectArray NodeArray; +typedef btAlignedObjectArray QuantizedNodeArray; +typedef btAlignedObjectArray BvhSubtreeInfoArray; + + +///OptimizedBvh store an AABB tree that can be quickly traversed on CPU (and SPU,GPU in future) +ATTRIBUTE_ALIGNED16(class) btOptimizedBvh +{ + NodeArray m_leafNodes; + NodeArray m_contiguousNodes; + + QuantizedNodeArray m_quantizedLeafNodes; + + QuantizedNodeArray m_quantizedContiguousNodes; + + int m_curNodeIndex; + + + //quantization data + bool m_useQuantization; + btVector3 m_bvhAabbMin; + btVector3 m_bvhAabbMax; + btVector3 m_bvhQuantization; + + enum btTraversalMode + { + TRAVERSAL_STACKLESS = 0, + TRAVERSAL_STACKLESS_CACHE_FRIENDLY, + TRAVERSAL_RECURSIVE + }; + + btTraversalMode m_traversalMode; + + + + + BvhSubtreeInfoArray m_SubtreeHeaders; + + + ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) + ///this might be refactored into a virtual, it is usually not calculated at run-time + void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin) + { + if (m_useQuantization) + { + quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin; + + } + } + void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax) + { + if (m_useQuantization) + { + quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax; + } + } + + btVector3 getAabbMin(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMinOrg; + + } + btVector3 getAabbMax(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMaxOrg; + + } + + void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); + + void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex) + { + if (m_useQuantization) + { + m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex; + } + else + { + m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex; + } + + } + + void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) + { + if (m_useQuantization) + { + unsigned short int quantizedAabbMin[3]; + unsigned short int quantizedAabbMax[3]; + quantizeWithClamp(quantizedAabbMin,newAabbMin); + quantizeWithClamp(quantizedAabbMax,newAabbMax); + for (int i=0;i<3;i++) + { + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i]; + + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i]; + + } + } else + { + //non-quantized + m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin); + m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax); + } + } + + void swapLeafNodes(int firstIndex,int secondIndex); + + void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex); + +protected: + + + + void buildTree (int startIndex,int endIndex); + + int calcSplittingAxis(int startIndex,int endIndex); + + int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis); + + void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const; + + ///tree traversal designed for small-memory processors like PS3 SPU + void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; + + + inline bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const + { + bool overlap = true; + overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; + overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; + overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; + return overlap; + } + + void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); + +public: + btOptimizedBvh(); + + virtual ~btOptimizedBvh(); + + void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax); + + void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void quantizeWithClamp(unsigned short* out, const btVector3& point) const; + + btVector3 unQuantize(const unsigned short* vecIn) const; + + ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees. + void setTraversalMode(btTraversalMode traversalMode) + { + m_traversalMode = traversalMode; + } + + void refit(btStridingMeshInterface* triangles); + + void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax); + + void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index); + + + QuantizedNodeArray& getQuantizedNodeArray() + { + return m_quantizedContiguousNodes; + } + + BvhSubtreeInfoArray& getSubtreeInfoArray() + { + return m_SubtreeHeaders; + } + +} +; + + +#endif //OPTIMIZED_BVH_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp new file mode 100644 index 00000000000..bbc4ba62af6 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp @@ -0,0 +1,148 @@ +/* +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. +*/ + +#include + +btPolyhedralConvexShape::btPolyhedralConvexShape() +:m_localAabbMin(1,1,1), +m_localAabbMax(-1,-1,-1), +m_isLocalAabbValid(false), +m_optionalHull(0) +{ + +} + + + +btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const +{ + int i; + btVector3 supVec(0,0,0); + + btScalar maxDot(btScalar(-1e30)); + + btVector3 vec = vec0; + btScalar lenSqr = vec.length2(); + if (lenSqr < btScalar(0.0001)) + { + vec.setValue(1,0,0); + } else + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + vec *= rlen; + } + + btVector3 vtx; + btScalar newDot; + + for (i=0;i maxDot) + { + maxDot = newDot; + supVec = vtx; + } + } + + return supVec; + +} + +void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + int i; + + btVector3 vtx; + btScalar newDot; + + for (i=0;i supportVerticesOut[j][3]) + { + //WARNING: don't swap next lines, the w component would get overwritten! + supportVerticesOut[j] = vtx; + supportVerticesOut[j][3] = newDot; + } + } + } +} + + + +void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +{ + //not yet, return box inertia + + btScalar margin = getMargin(); + + btTransform ident; + ident.setIdentity(); + btVector3 aabbMin,aabbMax; + getAabb(ident,aabbMin,aabbMax); + btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); + + btScalar lx=btScalar(2.)*(halfExtents.x()+margin); + btScalar ly=btScalar(2.)*(halfExtents.y()+margin); + btScalar lz=btScalar(2.)*(halfExtents.z()+margin); + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); + +} + + + +void btPolyhedralConvexShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin()); +} + + + + +void btPolyhedralConvexShape::recalcLocalAabb() +{ + m_isLocalAabbValid = true; + + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + btVector3 tmp = localGetSupportingVertex(vec); + m_localAabbMax[i] = tmp[i]+m_collisionMargin; + vec[i] = btScalar(-1.); + tmp = localGetSupportingVertex(vec); + m_localAabbMin[i] = tmp[i]-m_collisionMargin; + } +} + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h new file mode 100644 index 00000000000..c35f7512663 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h @@ -0,0 +1,93 @@ +/* +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. +*/ + +#ifndef BU_SHAPE +#define BU_SHAPE + +#include "../../LinearMath/btPoint3.h" +#include "../../LinearMath/btMatrix3x3.h" +#include "btConvexShape.h" + + +///PolyhedralConvexShape is an interface class for feature based (vertex/edge/face) convex shapes. +class btPolyhedralConvexShape : public btConvexShape +{ + +protected: + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + bool m_isLocalAabbValid; + +public: + + btPolyhedralConvexShape(); + + //brute force implementations + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + + + inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const + { + + //lazy evaluation of local aabb + btAssert(m_isLocalAabbValid); + + btAssert(m_localAabbMin.getX() <= m_localAabbMax.getX()); + btAssert(m_localAabbMin.getY() <= m_localAabbMax.getY()); + btAssert(m_localAabbMin.getZ() <= m_localAabbMax.getZ()); + + + btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btPoint3 center = trans(localCenter); + + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + extent += btVector3(margin,margin,margin); + + aabbMin = center - extent; + aabbMax = center + extent; + + + } + + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + void recalcLocalAabb(); + + virtual int getNumVertices() const = 0 ; + virtual int getNumEdges() const = 0; + virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const = 0; + virtual void getVertex(int i,btPoint3& vtx) const = 0; + virtual int getNumPlanes() const = 0; + virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const = 0; +// virtual int getIndex(int i) const = 0 ; + + virtual bool isInside(const btPoint3& pt,btScalar tolerance) const = 0; + + /// optional Hull is for optional Separating Axis Test Hull collision detection, see Hull.cpp + class Hull* m_optionalHull; + +}; + +#endif //BU_SHAPE diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp new file mode 100644 index 00000000000..ca65dd03f3e --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp @@ -0,0 +1,77 @@ +/* +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. +*/ + +#include "btSphereShape.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "LinearMath/btQuaternion.h" + + +btSphereShape ::btSphereShape (btScalar radius) +{ + m_implicitShapeDimensions.setX(radius); +} + +btVector3 btSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + (void)vec; + return btVector3(btScalar(0.),btScalar(0.),btScalar(0.)); +} + +void btSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + (void)vectors; + + for (int i=0;iprocessTriangle(triangle,0,0); + + triangle[0] = projectedCenter - tangentDir0*radius - tangentDir1*radius; + triangle[1] = projectedCenter - tangentDir0*radius + tangentDir1*radius; + triangle[2] = projectedCenter + tangentDir0*radius + tangentDir1*radius; + + callback->processTriangle(triangle,0,1); + +} + +void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +{ + (void)mass; + + //moving concave objects not supported + + inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); +} + +void btStaticPlaneShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} +const btVector3& btStaticPlaneShape::getLocalScaling() const +{ + return m_localScaling; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h new file mode 100644 index 00000000000..f59cc0c3347 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h @@ -0,0 +1,61 @@ +/* +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. +*/ + +#ifndef STATIC_PLANE_SHAPE_H +#define STATIC_PLANE_SHAPE_H + +#include "btConcaveShape.h" + + +///StaticPlaneShape simulates an 'infinite' plane by dynamically reporting triangles approximated by intersection of the plane with the AABB. +///Assumed is that the other objects is not also infinite, so a reasonable sized AABB. +class btStaticPlaneShape : public btConcaveShape +{ +protected: + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + + btVector3 m_planeNormal; + btScalar m_planeConstant; + btVector3 m_localScaling; + +public: + btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant); + + virtual ~btStaticPlaneShape(); + + + virtual int getShapeType() const + { + return STATIC_PLANE_PROXYTYPE; + } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + + + //debugging + virtual char* getName()const {return "STATICPLANE";} + + +}; + +#endif //STATIC_PLANE_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp new file mode 100644 index 00000000000..03ca1ae7736 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp @@ -0,0 +1,124 @@ +/* +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. +*/ + +#include "btStridingMeshInterface.h" + +btStridingMeshInterface::~btStridingMeshInterface() +{ + +} + + +void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + (void)aabbMin; + (void)aabbMax; + int numtotalphysicsverts = 0; + int part,graphicssubparts = getNumSubParts(); + const unsigned char * vertexbase; + const unsigned char * indexbase; + int indexstride; + PHY_ScalarType type; + PHY_ScalarType gfxindextype; + int stride,numverts,numtriangles; + int gfxindex; + btVector3 triangle[3]; + btScalar* graphicsbase; + + btVector3 meshScaling = getScaling(); + + ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype + for (part=0;partinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + case PHY_SHORT: + { + for (gfxindex=0;gfxindexinternalProcessTriangleIndex(triangle,part,gfxindex); + } + break; + } + default: + btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT)); + } + + unLockReadOnlyVertexBase(part); + } +} + +void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax) +{ + + struct AabbCalculationCallback : public btInternalTriangleIndexCallback + { + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + AabbCalculationCallback() + { + m_aabbMin.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + m_aabbMax.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + (void)partId; + (void)triangleIndex; + + m_aabbMin.setMin(triangle[0]); + m_aabbMax.setMax(triangle[0]); + m_aabbMin.setMin(triangle[1]); + m_aabbMax.setMax(triangle[1]); + m_aabbMin.setMin(triangle[2]); + m_aabbMax.setMax(triangle[2]); + } + }; + + //first calculate the total aabb for all triangles + AabbCalculationCallback aabbCallback; + aabbMin.setValue(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); + aabbMax.setValue(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax); + + aabbMin = aabbCallback.m_aabbMin; + aabbMax = aabbCallback.m_aabbMax; +} \ No newline at end of file diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h new file mode 100644 index 00000000000..d7b354b7855 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h @@ -0,0 +1,89 @@ +/* +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. +*/ + +#ifndef STRIDING_MESHINTERFACE_H +#define STRIDING_MESHINTERFACE_H + +#include "../../LinearMath/btVector3.h" +#include "btTriangleCallback.h" + +/// PHY_ScalarType enumerates possible scalar types. +/// See the btStridingMeshInterface for its use +typedef enum PHY_ScalarType { + PHY_FLOAT, + PHY_DOUBLE, + PHY_INTEGER, + PHY_SHORT, + PHY_FIXEDPOINT88 +} PHY_ScalarType; + +/// btStridingMeshInterface is the interface class for high performance access to triangle meshes +/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory. +class btStridingMeshInterface +{ + protected: + + btVector3 m_scaling; + + public: + btStridingMeshInterface() :m_scaling(btScalar(1.),btScalar(1.),btScalar(1.)) + { + + } + + virtual ~btStridingMeshInterface(); + + + + void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + ///brute force method to calculate aabb + void calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax); + + /// get read and write access to a subpart of a triangle mesh + /// this subpart has a continuous array of vertices and indices + /// in this way the mesh can be handled as chunks of memory with striding + /// very similar to OpenGL vertexarray support + /// make a call to unLockVertexBase when the read and write access is finished + virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0; + + virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const=0; + + /// unLockVertexBase finishes the access to a subpart of the triangle mesh + /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished + virtual void unLockVertexBase(int subpart)=0; + + virtual void unLockReadOnlyVertexBase(int subpart) const=0; + + + /// getNumSubParts returns the number of seperate subparts + /// each subpart has a continuous array of vertices and indices + virtual int getNumSubParts() const=0; + + virtual void preallocateVertices(int numverts)=0; + virtual void preallocateIndices(int numindices)=0; + + const btVector3& getScaling() const { + return m_scaling; + } + void setScaling(const btVector3& scaling) + { + m_scaling = scaling; + } + + +}; + +#endif //STRIDING_MESHINTERFACE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp new file mode 100644 index 00000000000..3aa1eda9964 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.cpp @@ -0,0 +1,195 @@ + +/* +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. +*/ +#include "btTetrahedronShape.h" +#include "LinearMath/btMatrix3x3.h" + +btBU_Simplex1to4::btBU_Simplex1to4() +:m_numVertices(0) +{ +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btPoint3& pt0) +:m_numVertices(0) +{ + addVertex(pt0); +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1) +:m_numVertices(0) +{ + addVertex(pt0); + addVertex(pt1); +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1,const btPoint3& pt2) +:m_numVertices(0) +{ + addVertex(pt0); + addVertex(pt1); + addVertex(pt2); +} + +btBU_Simplex1to4::btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1,const btPoint3& pt2,const btPoint3& pt3) +:m_numVertices(0) +{ + addVertex(pt0); + addVertex(pt1); + addVertex(pt2); + addVertex(pt3); +} + + + + + +void btBU_Simplex1to4::addVertex(const btPoint3& pt) +{ + m_vertices[m_numVertices++] = pt; + + recalcLocalAabb(); +} + + +int btBU_Simplex1to4::getNumVertices() const +{ + return m_numVertices; +} + +int btBU_Simplex1to4::getNumEdges() const +{ + //euler formula, F-E+V = 2, so E = F+V-2 + + switch (m_numVertices) + { + case 0: + return 0; + case 1: return 0; + case 2: return 1; + case 3: return 3; + case 4: return 6; + + + } + + return 0; +} + +void btBU_Simplex1to4::getEdge(int i,btPoint3& pa,btPoint3& pb) const +{ + + switch (m_numVertices) + { + + case 2: + pa = m_vertices[0]; + pb = m_vertices[1]; + break; + case 3: + switch (i) + { + case 0: + pa = m_vertices[0]; + pb = m_vertices[1]; + break; + case 1: + pa = m_vertices[1]; + pb = m_vertices[2]; + break; + case 2: + pa = m_vertices[2]; + pb = m_vertices[0]; + break; + + } + break; + case 4: + switch (i) + { + case 0: + pa = m_vertices[0]; + pb = m_vertices[1]; + break; + case 1: + pa = m_vertices[1]; + pb = m_vertices[2]; + break; + case 2: + pa = m_vertices[2]; + pb = m_vertices[0]; + break; + case 3: + pa = m_vertices[0]; + pb = m_vertices[3]; + break; + case 4: + pa = m_vertices[1]; + pb = m_vertices[3]; + break; + case 5: + pa = m_vertices[2]; + pb = m_vertices[3]; + break; + } + + } + + + + +} + +void btBU_Simplex1to4::getVertex(int i,btPoint3& vtx) const +{ + vtx = m_vertices[i]; +} + +int btBU_Simplex1to4::getNumPlanes() const +{ + switch (m_numVertices) + { + case 0: + return 0; + case 1: + return 0; + case 2: + return 0; + case 3: + return 2; + case 4: + return 4; + default: + { + } + } + return 0; +} + + +void btBU_Simplex1to4::getPlane(btVector3&, btPoint3& ,int ) const +{ + +} + +int btBU_Simplex1to4::getIndex(int ) const +{ + return 0; +} + +bool btBU_Simplex1to4::isInside(const btPoint3& ,btScalar ) const +{ + return false; +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h new file mode 100644 index 00000000000..94bc4ec0fa5 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h @@ -0,0 +1,75 @@ +/* +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. +*/ + +#ifndef BU_SIMPLEX_1TO4_SHAPE +#define BU_SIMPLEX_1TO4_SHAPE + + +#include "btPolyhedralConvexShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" + + +///BU_Simplex1to4 implements feature based and implicit simplex of up to 4 vertices (tetrahedron, triangle, line, vertex). +class btBU_Simplex1to4 : public btPolyhedralConvexShape +{ +protected: + + int m_numVertices; + btPoint3 m_vertices[4]; + +public: + btBU_Simplex1to4(); + + btBU_Simplex1to4(const btPoint3& pt0); + btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1); + btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1,const btPoint3& pt2); + btBU_Simplex1to4(const btPoint3& pt0,const btPoint3& pt1,const btPoint3& pt2,const btPoint3& pt3); + + + void reset() + { + m_numVertices = 0; + } + + + virtual int getShapeType() const{ return TETRAHEDRAL_SHAPE_PROXYTYPE; } + + void addVertex(const btPoint3& pt); + + //PolyhedralConvexShape interface + + virtual int getNumVertices() const; + + virtual int getNumEdges() const; + + virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const; + + virtual void getVertex(int i,btPoint3& vtx) const; + + virtual int getNumPlanes() const; + + virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i) const; + + virtual int getIndex(int i) const; + + virtual bool isInside(const btPoint3& pt,btScalar tolerance) const; + + + ///getName is for debugging + virtual char* getName()const { return "btBU_Simplex1to4";} + +}; + +#endif //BU_SIMPLEX_1TO4_SHAPE diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp new file mode 100644 index 00000000000..54864c32f3a --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp @@ -0,0 +1,42 @@ +/* +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. +*/ + +#include "btTriangleBuffer.h" + + +///example usage of this class: +// btTriangleBuffer triBuf; +// concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax); +// for (int i=0;i m_triangleBuffer; + +public: + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + int getNumTriangles() const + { + return int(m_triangleBuffer.size()); + } + + const btTriangle& getTriangle(int index) const + { + return m_triangleBuffer[index]; + } + + void clearBuffer() + { + m_triangleBuffer.clear(); + } + +}; + + +#endif //BT_TRIANGLE_BUFFER_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp new file mode 100644 index 00000000000..a020746db5f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.cpp @@ -0,0 +1,28 @@ +/* +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. +*/ + +#include "btTriangleCallback.h" + +btTriangleCallback::~btTriangleCallback() +{ + +} + + +btInternalTriangleIndexCallback::~btInternalTriangleIndexCallback() +{ + +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h new file mode 100644 index 00000000000..fbb87bc4fd8 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h @@ -0,0 +1,40 @@ +/* +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. +*/ + +#ifndef TRIANGLE_CALLBACK_H +#define TRIANGLE_CALLBACK_H + +#include "../../LinearMath/btVector3.h" + + +class btTriangleCallback +{ +public: + + virtual ~btTriangleCallback(); + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) = 0; +}; + +class btInternalTriangleIndexCallback +{ +public: + + virtual ~btInternalTriangleIndexCallback(); + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) = 0; +}; + + + +#endif //TRIANGLE_CALLBACK_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp new file mode 100644 index 00000000000..00847861cf1 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp @@ -0,0 +1,65 @@ +/* +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. +*/ + +#include "btTriangleIndexVertexArray.h" + +btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride) +{ + btIndexedMesh mesh; + + mesh.m_numTriangles = numTriangles; + mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase; + mesh.m_triangleIndexStride = triangleIndexStride; + mesh.m_numVertices = numVertices; + mesh.m_vertexBase = (const unsigned char *)vertexBase; + mesh.m_vertexStride = vertexStride; + + addIndexedMesh(mesh); + +} + +void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) +{ + btAssert(subpart< getNumSubParts() ); + + btIndexedMesh& mesh = m_indexedMeshes[subpart]; + + numverts = mesh.m_numVertices; + (*vertexbase) = (unsigned char *) mesh.m_vertexBase; + type = PHY_FLOAT; + vertexStride = mesh.m_vertexStride; + + numfaces = mesh.m_numTriangles; + + (*indexbase) = (unsigned char *)mesh.m_triangleIndexBase; + indexstride = mesh.m_triangleIndexStride; + indicestype = PHY_INTEGER; +} + +void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const +{ + const btIndexedMesh& mesh = m_indexedMeshes[subpart]; + + numverts = mesh.m_numVertices; + (*vertexbase) = (const unsigned char *)mesh.m_vertexBase; + type = PHY_FLOAT; + vertexStride = mesh.m_vertexStride; + + numfaces = mesh.m_numTriangles; + (*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase; + indexstride = mesh.m_triangleIndexStride; + indicestype = PHY_INTEGER; +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h new file mode 100644 index 00000000000..6ab6a762b39 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h @@ -0,0 +1,97 @@ +/* +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. +*/ + +#ifndef BT_TRIANGLE_INDEX_VERTEX_ARRAY_H +#define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H + +#include "btStridingMeshInterface.h" +#include "../../LinearMath/btAlignedObjectArray.h" + +///IndexedMesh indexes into existing vertex and index arrays, in a similar way OpenGL glDrawElements +///instead of the number of indices, we pass the number of triangles +///todo: explain with pictures +ATTRIBUTE_ALIGNED16( struct) btIndexedMesh +{ + int m_numTriangles; + const unsigned char * m_triangleIndexBase; + int m_triangleIndexStride; + int m_numVertices; + const unsigned char * m_vertexBase; + int m_vertexStride; + int pad[2]; +} +; + + +typedef btAlignedObjectArray IndexedMeshArray; + +///TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays. +///Additional meshes can be added using addIndexedMesh +///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays. +///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray. +ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface +{ + IndexedMeshArray m_indexedMeshes; + int m_pad[3]; + + +public: + + btTriangleIndexVertexArray() + { + } + + //just to be backwards compatible + btTriangleIndexVertexArray(int numTriangleIndices,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride); + + void addIndexedMesh(const btIndexedMesh& mesh) + { + m_indexedMeshes.push_back(mesh); + } + + + virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0); + + virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const; + + /// unLockVertexBase finishes the access to a subpart of the triangle mesh + /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished + virtual void unLockVertexBase(int subpart) {(void)subpart;} + + virtual void unLockReadOnlyVertexBase(int subpart) const {(void)subpart;} + + /// getNumSubParts returns the number of seperate subparts + /// each subpart has a continuous array of vertices and indices + virtual int getNumSubParts() const { + return (int)m_indexedMeshes.size(); + } + + IndexedMeshArray& getIndexedMeshArray() + { + return m_indexedMeshes; + } + + const IndexedMeshArray& getIndexedMeshArray() const + { + return m_indexedMeshes; + } + + virtual void preallocateVertices(int numverts){(void) numverts;} + virtual void preallocateIndices(int numindices){(void) numindices;} + +} +; + +#endif //BT_TRIANGLE_INDEX_VERTEX_ARRAY_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp new file mode 100644 index 00000000000..98c54ef45f8 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp @@ -0,0 +1,60 @@ +/* +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. +*/ + +#include "btTriangleMesh.h" +#include + + +btTriangleMesh::btTriangleMesh () +{ + +} + +void btTriangleMesh::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) +{ + (void)subpart; + numverts = m_vertices.size(); + *vertexbase = (unsigned char*)&m_vertices[0]; + type = PHY_FLOAT; + stride = sizeof(btVector3); + + numfaces = m_indices.size()/3; + *indexbase = (unsigned char*) &m_indices[0]; + indicestype = PHY_INTEGER; + indexstride = 3*sizeof(int); + +} + +void btTriangleMesh::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const +{ + (void)subpart; + numverts = m_vertices.size(); + *vertexbase = (unsigned char*)&m_vertices[0]; + type = PHY_FLOAT; + stride = sizeof(btVector3); + + numfaces = m_indices.size()/3; + *indexbase = (unsigned char*) &m_indices[0]; + indicestype = PHY_INTEGER; + indexstride = 3*sizeof(int); + +} + + + +int btTriangleMesh::getNumSubParts() const +{ + return 1; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h new file mode 100644 index 00000000000..525f5336b48 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h @@ -0,0 +1,75 @@ +/* +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. +*/ + + +#ifndef TRIANGLE_MESH_H +#define TRIANGLE_MESH_H + +#include "btStridingMeshInterface.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btAlignedObjectArray.h" + +///TriangleMesh provides storage for a concave triangle mesh. It can be used as data for the btTriangleMeshShape. +class btTriangleMesh : public btStridingMeshInterface +{ + btAlignedObjectArray m_vertices; + btAlignedObjectArray m_indices; + + public: + btTriangleMesh (); + + void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2) + { + int curIndex = m_indices.size(); + m_vertices.push_back(vertex0); + m_vertices.push_back(vertex1); + m_vertices.push_back(vertex2); + + m_indices.push_back(curIndex++); + m_indices.push_back(curIndex++); + m_indices.push_back(curIndex++); + } + + int getNumTriangles() const + { + return m_indices.size() / 3; + } + + + +//StridingMeshInterface interface implementation + + virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0); + + virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const; + + /// unLockVertexBase finishes the access to a subpart of the triangle mesh + /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished + virtual void unLockVertexBase(int subpart) {(void) subpart;} + + virtual void unLockReadOnlyVertexBase(int subpart) const { (void) subpart;} + + /// getNumSubParts returns the number of seperate subparts + /// each subpart has a continuous array of vertices and indices + virtual int getNumSubParts() const; + + virtual void preallocateVertices(int numverts){(void) numverts;} + virtual void preallocateIndices(int numindices){(void) numindices;} + + +}; + +#endif //TRIANGLE_MESH_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp new file mode 100644 index 00000000000..ed81897b515 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp @@ -0,0 +1,203 @@ +/* +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. +*/ + +#include "btTriangleMeshShape.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btQuaternion.h" +#include "btStridingMeshInterface.h" +#include "LinearMath/btAabbUtil2.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" + +#include "stdio.h" + +btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface) +: m_meshInterface(meshInterface) +{ + recalcLocalAabb(); +} + + +btTriangleMeshShape::~btTriangleMeshShape() +{ + +} + + + + +void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + + btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btPoint3 center = trans(localCenter); + + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + extent += btVector3(getMargin(),getMargin(),getMargin()); + + aabbMin = center - extent; + aabbMax = center + extent; + + +} + +void btTriangleMeshShape::recalcLocalAabb() +{ + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + btVector3 tmp = localGetSupportingVertex(vec); + m_localAabbMax[i] = tmp[i]+m_collisionMargin; + vec[i] = btScalar(-1.); + tmp = localGetSupportingVertex(vec); + m_localAabbMin[i] = tmp[i]-m_collisionMargin; + } +} + + + +class SupportVertexCallback : public btTriangleCallback +{ + + btVector3 m_supportVertexLocal; +public: + + btTransform m_worldTrans; + btScalar m_maxDot; + btVector3 m_supportVecLocal; + + SupportVertexCallback(const btVector3& supportVecWorld,const btTransform& trans) + : m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), m_worldTrans(trans) ,m_maxDot(btScalar(-1e30)) + + { + m_supportVecLocal = supportVecWorld * m_worldTrans.getBasis(); + } + + virtual void processTriangle( btVector3* triangle,int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + for (int i=0;i<3;i++) + { + btScalar dot = m_supportVecLocal.dot(triangle[i]); + if (dot > m_maxDot) + { + m_maxDot = dot; + m_supportVertexLocal = triangle[i]; + } + } + } + + btVector3 GetSupportVertexWorldSpace() + { + return m_worldTrans(m_supportVertexLocal); + } + + btVector3 GetSupportVertexLocal() + { + return m_supportVertexLocal; + } + +}; + + +void btTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + m_meshInterface->setScaling(scaling); + recalcLocalAabb(); +} + +const btVector3& btTriangleMeshShape::getLocalScaling() const +{ + return m_meshInterface->getScaling(); +} + + + + + + +//#define DEBUG_TRIANGLE_MESH + + +void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + struct FilteredCallback : public btInternalTriangleIndexCallback + { + btTriangleCallback* m_callback; + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + FilteredCallback(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) + :m_callback(callback), + m_aabbMin(aabbMin), + m_aabbMax(aabbMax) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + if (TestTriangleAgainstAabb2(&triangle[0],m_aabbMin,m_aabbMax)) + { + //check aabb in triangle-space, before doing this + m_callback->processTriangle(triangle,partId,triangleIndex); + } + + } + + }; + + FilteredCallback filterCallback(callback,aabbMin,aabbMax); + + m_meshInterface->InternalProcessAllTriangles(&filterCallback,aabbMin,aabbMax); +} + + + + + + +void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +{ + (void)mass; + //moving concave objects not supported + btAssert(0); + inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); +} + + +btVector3 btTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const +{ + btVector3 supportVertex; + + btTransform ident; + ident.setIdentity(); + + SupportVertexCallback supportCallback(vec,ident); + + btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + + processAllTriangles(&supportCallback,-aabbMax,aabbMax); + + supportVertex = supportCallback.GetSupportVertexLocal(); + + return supportVertex; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h new file mode 100644 index 00000000000..e6173e47640 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h @@ -0,0 +1,78 @@ +/* +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. +*/ + +#ifndef TRIANGLE_MESH_SHAPE_H +#define TRIANGLE_MESH_SHAPE_H + +#include "btConcaveShape.h" +#include "btStridingMeshInterface.h" + + +///Concave triangle mesh. Uses an interface to access the triangles to allow for sharing graphics/physics triangles. +class btTriangleMeshShape : public btConcaveShape +{ +protected: + btVector3 m_localAabbMin; + btVector3 m_localAabbMax; + btStridingMeshInterface* m_meshInterface; + + +public: + btTriangleMeshShape(btStridingMeshInterface* meshInterface); + + virtual ~btTriangleMeshShape(); + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const; + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + assert(0); + return localGetSupportingVertex(vec); + } + + void recalcLocalAabb(); + + virtual int getShapeType() const + { + return TRIANGLE_MESH_SHAPE_PROXYTYPE; + } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + + btStridingMeshInterface* getMeshInterface() + { + return m_meshInterface; + } + + const btStridingMeshInterface* getMeshInterface() const + { + return m_meshInterface; + } + + + //debugging + virtual char* getName()const {return "TRIANGLEMESH";} + + +}; + +#endif //TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h new file mode 100644 index 00000000000..c2e240c051c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h @@ -0,0 +1,179 @@ +/* +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. +*/ + +#ifndef OBB_TRIANGLE_MINKOWSKI_H +#define OBB_TRIANGLE_MINKOWSKI_H + +#include "btConvexShape.h" +#include "btBoxShape.h" + +class btTriangleShape : public btPolyhedralConvexShape +{ + + +public: + + btVector3 m_vertices1[3]; + + + virtual int getNumVertices() const + { + return 3; + } + + const btVector3& getVertexPtr(int index) const + { + return m_vertices1[index]; + } + virtual void getVertex(int index,btVector3& vert) const + { + vert = m_vertices1[index]; + } + virtual int getShapeType() const + { + return TRIANGLE_SHAPE_PROXYTYPE; + } + + virtual int getNumEdges() const + { + return 3; + } + + virtual void getEdge(int i,btPoint3& pa,btPoint3& pb) const + { + getVertex(i,pa); + getVertex((i+1)%3,pb); + } + + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const + { +// btAssert(0); + getAabbSlow(t,aabbMin,aabbMax); + } + + btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir)const + { + btVector3 dots(dir.dot(m_vertices1[0]), dir.dot(m_vertices1[1]), dir.dot(m_vertices1[2])); + return m_vertices1[dots.maxAxis()]; + + } + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + { + for (int i=0;i= -tolerance && dist <= tolerance) + { + //inside check on edge-planes + int i; + for (i=0;i<3;i++) + { + btPoint3 pa,pb; + getEdge(i,pa,pb); + btVector3 edge = pb-pa; + btVector3 edgeNormal = edge.cross(normal); + edgeNormal.normalize(); + btScalar dist = pt.dot( edgeNormal); + btScalar edgeConst = pa.dot(edgeNormal); + dist -= edgeConst; + if (dist < -tolerance) + return false; + } + + return true; + } + + return false; + } + //debugging + virtual char* getName()const + { + return "Triangle"; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 2; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + calcNormal(penetrationVector); + if (index) + penetrationVector *= btScalar(-1.); + } + + +}; + +#endif //OBB_TRIANGLE_MINKOWSKI_H + diff --git a/extern/bullet2/src/BulletCollision/Doxyfile b/extern/bullet2/src/BulletCollision/Doxyfile new file mode 100644 index 00000000000..4ecb6acb62f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Doxyfile @@ -0,0 +1,746 @@ +# Doxyfile 1.2.4 + +# This file describes the settings to be used by doxygen for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. +PROJECT_NAME = "Bullet Continuous Collision Detection Library" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, +# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, +# Polish, Portuguese and Slovene. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a class diagram (in Html and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. + +CLASS_DIAGRAMS = YES + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# The ENABLE_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . + + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +FILE_PATTERNS = *.h *.cpp *.c + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse. + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Netscape 4.0+ +# or Internet explorer 4.0+). + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using a WORD or other. +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Warning: This feature +# is still experimental and very incomplete. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = ../../generic/extern + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other +# documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to +# YES then doxygen will generate a graph for each documented header file showing +# the documented files that directly or indirectly include this file + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = c:\program files\doxygen\bin + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp new file mode 100644 index 00000000000..2c565734e97 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp @@ -0,0 +1,200 @@ +/* +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. +*/ + + +#include "btContinuousConvexCollision.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "LinearMath/btTransformUtil.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" + +#include "btGjkPairDetector.h" +#include "btPointCollector.h" + + + +btContinuousConvexCollision::btContinuousConvexCollision ( btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) +:m_simplexSolver(simplexSolver), +m_penetrationDepthSolver(penetrationDepthSolver), +m_convexA(convexA),m_convexB(convexB) +{ +} + +/// This maximum should not be necessary. It allows for untested/degenerate cases in production code. +/// You don't want your game ever to lock-up. +#define MAX_ITERATIONS 1000 + +bool btContinuousConvexCollision::calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) +{ + + m_simplexSolver->reset(); + + /// compute linear and angular velocity for this interval, to interpolate + btVector3 linVelA,angVelA,linVelB,angVelB; + btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA); + btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB); + + btScalar boundingRadiusA = m_convexA->getAngularMotionDisc(); + btScalar boundingRadiusB = m_convexB->getAngularMotionDisc(); + + btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB; + + btScalar radius = btScalar(0.001); + + btScalar lambda = btScalar(0.); + btVector3 v(1,0,0); + + int maxIter = MAX_ITERATIONS; + + btVector3 n; + n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + bool hasResult = false; + btVector3 c; + + btScalar lastLambda = lambda; + //btScalar epsilon = btScalar(0.001); + + int numIter = 0; + //first solution, using GJK + + + btTransform identityTrans; + identityTrans.setIdentity(); + + btSphereShape raySphere(btScalar(0.0)); + raySphere.setMargin(btScalar(0.)); + + +// result.drawCoordSystem(sphereTr); + + btPointCollector pointCollector1; + + { + + btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver); + btGjkPairDetector::ClosestPointInput input; + + //we don't use margins during CCD + gjk.setIgnoreMargin(true); + + input.m_transformA = fromA; + input.m_transformB = fromB; + gjk.getClosestPoints(input,pointCollector1,0); + + hasResult = pointCollector1.m_hasResult; + c = pointCollector1.m_pointInWorld; + } + + if (hasResult) + { + btScalar dist; + dist = pointCollector1.m_distance; + n = pointCollector1.m_normalOnBInWorld; + + //not close enough + while (dist > radius) + { + numIter++; + if (numIter > maxIter) + return false; //todo: report a failure + + btScalar dLambda = btScalar(0.); + + //calculate safe moving fraction from distance / (linear+rotational velocity) + + //btScalar clippedDist = GEN_min(angularConservativeRadius,dist); + //btScalar clippedDist = dist; + + btScalar projectedLinearVelocity = (linVelB-linVelA).dot(n); + + dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); + + lambda = lambda + dLambda; + + if (lambda > btScalar(1.)) + return false; + + if (lambda < btScalar(0.)) + return false; + + //todo: next check with relative epsilon + if (lambda <= lastLambda) + break; + lastLambda = lambda; + + + + //interpolate to next lambda + btTransform interpolatedTransA,interpolatedTransB,relativeTrans; + + btTransformUtil::integrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA); + btTransformUtil::integrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB); + relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA); + + result.DebugDraw( lambda ); + + btPointCollector pointCollector; + btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver); + btGjkPairDetector::ClosestPointInput input; + input.m_transformA = interpolatedTransA; + input.m_transformB = interpolatedTransB; + gjk.getClosestPoints(input,pointCollector,0); + if (pointCollector.m_hasResult) + { + if (pointCollector.m_distance < btScalar(0.)) + { + //degenerate ?! + result.m_fraction = lastLambda; + result.m_normal = n; + return true; + } + c = pointCollector.m_pointInWorld; + + dist = pointCollector.m_distance; + } else + { + //?? + return false; + } + + } + + result.m_fraction = lambda; + result.m_normal = n; + return true; + } + + return false; + +/* +//todo: + //if movement away from normal, discard result + btVector3 move = transBLocalTo.getOrigin() - transBLocalFrom.getOrigin(); + if (result.m_fraction < btScalar(1.)) + { + if (move.dot(result.m_normal) <= btScalar(0.)) + { + } + } +*/ + +} + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h new file mode 100644 index 00000000000..9901bab4b45 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h @@ -0,0 +1,52 @@ +/* +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. +*/ + + +#ifndef CONTINUOUS_COLLISION_CONVEX_CAST_H +#define CONTINUOUS_COLLISION_CONVEX_CAST_H + +#include "btConvexCast.h" +#include "btSimplexSolverInterface.h" +class btConvexPenetrationDepthSolver; +class btConvexShape; + +/// btContinuousConvexCollision implements angular and linear time of impact for convex objects. +/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis). +/// Algorithm operates in worldspace, in order to keep inbetween motion globally consistent. +/// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops +class btContinuousConvexCollision : public btConvexCast +{ + btSimplexSolverInterface* m_simplexSolver; + btConvexPenetrationDepthSolver* m_penetrationDepthSolver; + btConvexShape* m_convexA; + btConvexShape* m_convexB; + + +public: + + btContinuousConvexCollision (btConvexShape* shapeA,btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result); + + +}; + +#endif //CONTINUOUS_COLLISION_CONVEX_CAST_H + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp new file mode 100644 index 00000000000..d2a1310b232 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp @@ -0,0 +1,20 @@ +/* +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. +*/ + +#include "btConvexCast.h" + +btConvexCast::~btConvexCast() +{ +} diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h new file mode 100644 index 00000000000..3101b59993d --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h @@ -0,0 +1,71 @@ +/* +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. +*/ + + +#ifndef CONVEX_CAST_H +#define CONVEX_CAST_H + +#include "../../LinearMath/btTransform.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btScalar.h" +class btMinkowskiSumShape; +#include "../../LinearMath/btIDebugDraw.h" + +/// btConvexCast is an interface for Casting +class btConvexCast +{ +public: + + + virtual ~btConvexCast(); + + ///RayResult stores the closest result + /// alternatively, add a callback method to decide about closest/all results + struct CastResult + { + //virtual bool addRayResult(const btVector3& normal,btScalar fraction) = 0; + + virtual void DebugDraw(btScalar fraction) {(void)fraction;} + virtual void drawCoordSystem(const btTransform& trans) {(void)trans;} + + CastResult() + :m_fraction(btScalar(1e30)), + m_debugDrawer(0) + { + } + + + virtual ~CastResult() {}; + + btVector3 m_normal; + btScalar m_fraction; + btTransform m_hitTransformA; + btTransform m_hitTransformB; + + btIDebugDraw* m_debugDrawer; + + }; + + + /// cast a convex against another convex object + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) = 0; +}; + +#endif //CONVEX_CAST_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h new file mode 100644 index 00000000000..7caeba4be45 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h @@ -0,0 +1,43 @@ +/* +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. +*/ + + +#ifndef CONVEX_PENETRATION_DEPTH_H +#define CONVEX_PENETRATION_DEPTH_H + +class btStackAlloc; +class btVector3; +#include "btSimplexSolverInterface.h" +class btConvexShape; +#include "../../LinearMath/btPoint3.h" +class btTransform; + +///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation. +class btConvexPenetrationDepthSolver +{ +public: + + virtual ~btConvexPenetrationDepthSolver() {}; + virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, + btConvexShape* convexA,btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btPoint3& pa, btPoint3& pb, + class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc + ) = 0; + + +}; +#endif //CONVEX_PENETRATION_DEPTH_H + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h new file mode 100644 index 00000000000..15000c1ab61 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h @@ -0,0 +1,88 @@ +/* +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. +*/ + + +#ifndef DISCRETE_COLLISION_DETECTOR1_INTERFACE_H +#define DISCRETE_COLLISION_DETECTOR1_INTERFACE_H +#include "../../LinearMath/btTransform.h" +#include "../../LinearMath/btVector3.h" +class btStackAlloc; + +/// This interface is made to be used by an iterative approach to do TimeOfImpact calculations +/// This interface allows to query for closest points and penetration depth between two (convex) objects +/// the closest point is on the second object (B), and the normal points from the surface on B towards A. +/// distance is between closest points on B and closest point on A. So you can calculate closest point on A +/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB +struct btDiscreteCollisionDetectorInterface +{ + + struct Result + { + + virtual ~Result(){} + + ///setShapeIdentifiers provides experimental support for per-triangle material / custom material combiner + virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1)=0; + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)=0; + }; + + struct ClosestPointInput + { + ClosestPointInput() + :m_maximumDistanceSquared(btScalar(1e30)), + m_stackAlloc(0) + { + } + + btTransform m_transformA; + btTransform m_transformB; + btScalar m_maximumDistanceSquared; + btStackAlloc* m_stackAlloc; + }; + + virtual ~btDiscreteCollisionDetectorInterface() {}; + + // + // give either closest points (distance > 0) or penetration (distance) + // the normal always points from B towards A + // + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) = 0; + +}; + +struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result +{ + btVector3 m_normalOnSurfaceB; + btVector3 m_closestPointInB; + btScalar m_distance; //negative means penetration ! + + btStorageResult() : m_distance(btScalar(1e30)) + { + + } + virtual ~btStorageResult() {}; + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + if (depth < m_distance) + { + m_normalOnSurfaceB = normalOnBInWorld; + m_closestPointInB = pointInWorld; + m_distance = depth; + } + } +}; + +#endif //DISCRETE_COLLISION_DETECTOR_INTERFACE1_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp new file mode 100644 index 00000000000..93edffeafd6 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp @@ -0,0 +1,174 @@ +/* +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. +*/ + + + +#include "btGjkConvexCast.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" +#include "btGjkPairDetector.h" +#include "btPointCollector.h" + + +btGjkConvexCast::btGjkConvexCast(btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) +:m_simplexSolver(simplexSolver), +m_convexA(convexA), +m_convexB(convexB) +{ +} + +bool btGjkConvexCast::calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) +{ + + + btMinkowskiSumShape combi(m_convexA,m_convexB); + btMinkowskiSumShape* convex = &combi; + + btTransform rayFromLocalA; + btTransform rayToLocalA; + + rayFromLocalA = fromA.inverse()* fromB; + rayToLocalA = toA.inverse()* toB; + + + btTransform trA,trB; + trA = btTransform(fromA); + trB = btTransform(fromB); + trA.setOrigin(btPoint3(0,0,0)); + trB.setOrigin(btPoint3(0,0,0)); + + convex->setTransformA(trA); + convex->setTransformB(trB); + + + + + btScalar radius = btScalar(0.01); + + btScalar lambda = btScalar(0.); + btVector3 s = rayFromLocalA.getOrigin(); + btVector3 r = rayToLocalA.getOrigin()-rayFromLocalA.getOrigin(); + btVector3 x = s; + btVector3 n; + n.setValue(0,0,0); + bool hasResult = false; + btVector3 c; + + btScalar lastLambda = lambda; + + //first solution, using GJK + + //no penetration support for now, perhaps pass a pointer when we really want it + btConvexPenetrationDepthSolver* penSolverPtr = 0; + + btTransform identityTrans; + identityTrans.setIdentity(); + + btSphereShape raySphere(btScalar(0.0)); + raySphere.setMargin(btScalar(0.)); + + btTransform sphereTr; + sphereTr.setIdentity(); + sphereTr.setOrigin( rayFromLocalA.getOrigin()); + + result.drawCoordSystem(sphereTr); + { + btPointCollector pointCollector1; + btGjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr); + + btGjkPairDetector::ClosestPointInput input; + input.m_transformA = sphereTr; + input.m_transformB = identityTrans; + gjk.getClosestPoints(input,pointCollector1,0); + + hasResult = pointCollector1.m_hasResult; + c = pointCollector1.m_pointInWorld; + n = pointCollector1.m_normalOnBInWorld; + } + + + + if (hasResult) + { + btScalar dist; + dist = (c-x).length(); + if (dist < radius) + { + //penetration + lastLambda = btScalar(1.); + } + + //not close enough + while (dist > radius) + { + + n = x - c; + btScalar nDotr = n.dot(r); + + if (nDotr >= -(SIMD_EPSILON*SIMD_EPSILON)) + return false; + + lambda = lambda - n.dot(n) / nDotr; + if (lambda <= lastLambda) + break; + + lastLambda = lambda; + + x = s + lambda * r; + + sphereTr.setOrigin( x ); + result.drawCoordSystem(sphereTr); + btPointCollector pointCollector; + btGjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr); + btGjkPairDetector::ClosestPointInput input; + input.m_transformA = sphereTr; + input.m_transformB = identityTrans; + gjk.getClosestPoints(input,pointCollector,0); + if (pointCollector.m_hasResult) + { + if (pointCollector.m_distance < btScalar(0.)) + { + //degeneracy, report a hit + result.m_fraction = lastLambda; + result.m_normal = n; + return true; + } + c = pointCollector.m_pointInWorld; + dist = (c-x).length(); + } else + { + //?? + return false; + } + + } + + if (lastLambda < btScalar(1.)) + { + + result.m_fraction = lastLambda; + result.m_normal = n; + return true; + } + } + + return false; +} + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h new file mode 100644 index 00000000000..3905c45e6d6 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h @@ -0,0 +1,50 @@ +/* +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. +*/ + + + +#ifndef GJK_CONVEX_CAST_H +#define GJK_CONVEX_CAST_H + +#include "../CollisionShapes/btCollisionMargin.h" + +#include "../../LinearMath/btVector3.h" +#include "btConvexCast.h" +class btConvexShape; +class btMinkowskiSumShape; +#include "btSimplexSolverInterface.h" + +///GjkConvexCast performs a raycast on a convex object using support mapping. +class btGjkConvexCast : public btConvexCast +{ + btSimplexSolverInterface* m_simplexSolver; + btConvexShape* m_convexA; + btConvexShape* m_convexB; + +public: + + btGjkConvexCast(btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); + + /// cast a convex against another convex object + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result); + +}; + +#endif //GJK_CONVEX_CAST_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp new file mode 100644 index 00000000000..8abdfdbb7e5 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp @@ -0,0 +1,628 @@ +/* +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. +*/ + +/* +GJK-EPA collision solver by Nathanael Presson +Nov.2006 +*/ + +#include "btGjkEpa.h" +#include //for memset +#include + +#if defined(DEBUG) || defined (_DEBUG) +#include //for debug printf +#ifdef __SPU__ +#include +#define printf spu_printf +#endif //__SPU__ +#endif + +namespace gjkepa_impl +{ + +// +// Port. typedefs +// + +typedef btScalar F; +typedef bool Z; +typedef int I; +typedef unsigned int U; +typedef unsigned char U1; +typedef unsigned short U2; + +typedef btVector3 Vector3; +typedef btMatrix3x3 Rotation; + +// +// Config +// + +#if 0 +#define BTLOCALSUPPORT localGetSupportingVertexWithoutMargin +#else +#define BTLOCALSUPPORT localGetSupportingVertex +#endif + +// +// Const +// + + +#define cstInf SIMD_INFINITY +#define cstPi SIMD_PI +#define cst2Pi SIMD_2_PI +#define GJK_maxiterations (128) +#define GJK_hashsize (1<<6) +#define GJK_hashmask (GJK_hashsize-1) +#define GJK_insimplex_eps F(0.0001) +#define GJK_sqinsimplex_eps (GJK_insimplex_eps*GJK_insimplex_eps) +#define EPA_maxiterations 256 +#define EPA_inface_eps F(0.01) +#define EPA_accuracy F(0.001) + +// +// Utils +// + +static inline F Abs(F v) { return(v<0?-v:v); } +static inline F Sign(F v) { return(F(v<0?-1:1)); } +template static inline void Swap(T& a,T& b) { T +t(a);a=b;b=t; } +template static inline T Min(const T& a,const T& b) { +return(a static inline T Max(const T& a,const T& b) { +return(a>b?a:b); } +static inline void ClearMemory(void* p,U sz) { memset(p,0,(size_t)sz); +} +#if 0 +template static inline void Raise(const T& object) { +throw(object); } +#else +template static inline void Raise(const T&) {} +#endif + + + +// +// GJK +// +struct GJK + { + struct Mkv + { + Vector3 w; /* Minkowski vertice */ + Vector3 r; /* Ray */ + }; + struct He + { + Vector3 v; + He* n; + }; + btStackAlloc* sa; + btBlock* sablock; + He* table[GJK_hashsize]; + Rotation wrotations[2]; + Vector3 positions[2]; + const btConvexShape* shapes[2]; + Mkv simplex[5]; + Vector3 ray; + U order; + U iterations; + F margin; + Z failed; + // + GJK(btStackAlloc* psa, + const Rotation& wrot0,const Vector3& pos0,const btConvexShape* shape0, + const Rotation& wrot1,const Vector3& pos1,const btConvexShape* shape1, + F pmargin=0) + { + wrotations[0]=wrot0;positions[0]=pos0;shapes[0]=shape0; + wrotations[1]=wrot1;positions[1]=pos1;shapes[1]=shape1; + sa =psa; + sablock =sa->beginBlock(); + margin =pmargin; + failed =false; + } + // + ~GJK() + { + sa->endBlock(sablock); + } + // vdh : very dumm hash + static inline U Hash(const Vector3& v) + { + //this doesn't compile under GCC 3.3.5, so add the ()... + //const U h(U(v[0]*15461)^U(v[1]*83003)^U(v[2]*15473)); + //return(((*((const U*)&h))*169639)&GJK_hashmask); + const U h((U)(v[0]*15461)^(U)(v[1]*83003)^(U)(v[2]*15473)); + return(((*((const U*)&h))*169639)&GJK_hashmask); + } + // + inline Vector3 LocalSupport(const Vector3& d,U i) const + { + return(wrotations[i]*shapes[i]->BTLOCALSUPPORT(d*wrotations[i])+positions[i]); + } + // + inline void Support(const Vector3& d,Mkv& v) const + { + v.r = d; + v.w = LocalSupport(d,0)-LocalSupport(-d,1)+d*margin; + } + #define SPX(_i_) simplex[_i_] + #define SPXW(_i_) simplex[_i_].w + // + inline Z FetchSupport() + { + const U h(Hash(ray)); + He* e = (He*)(table[h]); + while(e) { if(e->v==ray) { --order;return(false); } else e=e->n; } + e=(He*)sa->allocate(sizeof(He));e->v=ray;e->n=table[h];table[h]=e; + Support(ray,simplex[++order]); + return(ray.dot(SPXW(order))>0); + } + // + inline Z SolveSimplex2(const Vector3& ao,const Vector3& ab) + { + if(ab.dot(ao)>=0) + { + const Vector3 cabo(cross(ab,ao)); + if(cabo.length2()>GJK_sqinsimplex_eps) + { ray=cross(cabo,ab); } + else + { return(true); } + } + else + { order=0;SPX(0)=SPX(1);ray=ao; } + return(false); + } + // + inline Z SolveSimplex3(const Vector3& ao,const Vector3& ab,const Vector3& +ac) + { + return(SolveSimplex3a(ao,ab,ac,cross(ab,ac))); + } + // + inline Z SolveSimplex3a(const Vector3& ao,const Vector3& ab,const Vector3& +ac,const Vector3& cabc) + { + if((cross(cabc,ab)).dot(ao)<-GJK_insimplex_eps) + { order=1;SPX(0)=SPX(1);SPX(1)=SPX(2);return(SolveSimplex2(ao,ab)); } + else if((cross(cabc,ac)).dot(ao)>+GJK_insimplex_eps) + { order=1;SPX(1)=SPX(2);return(SolveSimplex2(ao,ac)); } + else + { + const F d(cabc.dot(ao)); + if(Abs(d)>GJK_insimplex_eps) + { + if(d>0) + { ray=cabc; } + else + { ray=-cabc;Swap(SPX(0),SPX(1)); } + return(false); + } else return(true); + } + } + // + inline Z SolveSimplex4(const Vector3& ao,const Vector3& ab,const Vector3& +ac,const Vector3& ad) + { + Vector3 crs; + if((crs=cross(ab,ac)).dot(ao)>GJK_insimplex_eps) + { +order=2;SPX(0)=SPX(1);SPX(1)=SPX(2);SPX(2)=SPX(3);return(SolveSimplex3a(ao,ab,ac,crs)); +} + else if((crs=cross(ac,ad)).dot(ao)>GJK_insimplex_eps) + { order=2;SPX(2)=SPX(3);return(SolveSimplex3a(ao,ac,ad,crs)); } + else if((crs=cross(ad,ab)).dot(ao)>GJK_insimplex_eps) + { +order=2;SPX(1)=SPX(0);SPX(0)=SPX(2);SPX(2)=SPX(3);return(SolveSimplex3a(ao,ad,ab,crs)); +} + else return(true); + } + // + inline Z SearchOrigin(const Vector3& initray=Vector3(1,0,0)) + { + iterations = 0; + order = (U)-1; + failed = false; + ray = initray.normalized(); + ClearMemory(table,sizeof(void*)*GJK_hashsize); + FetchSupport(); + ray = -SPXW(0); + for(;iterations0?rl:1; + if(FetchSupport()) + { + Z found(false); + switch(order) + { + case 1: found=SolveSimplex2(-SPXW(1),SPXW(0)-SPXW(1));break; + case 2: found=SolveSimplex3(-SPXW(2),SPXW(1)-SPXW(2),SPXW(0)-SPXW(2));break; + case 3: found=SolveSimplex4(-SPXW(3),SPXW(2)-SPXW(3),SPXW(1)-SPXW(3),SPXW(0)-SPXW(3));break; + } + if(found) return(true); + } else return(false); + } + failed=true; + return(false); + } + // + inline Z EncloseOrigin() + { + switch(order) + { + /* Point */ + case 0: break; + /* Line */ + case 1: + { + const Vector3 ab(SPXW(1)-SPXW(0)); + const Vector3 b[]={ cross(ab,Vector3(1,0,0)), + cross(ab,Vector3(0,1,0)), + cross(ab,Vector3(0,0,1))}; + const F m[]={b[0].length2(),b[1].length2(),b[2].length2()}; + const Rotation r(btQuaternion(ab.normalized(),cst2Pi/3)); + Vector3 w(b[m[0]>m[1]?m[0]>m[2]?0:2:m[1]>m[2]?1:2]); + Support(w.normalized(),simplex[4]);w=r*w; + Support(w.normalized(),simplex[2]);w=r*w; + Support(w.normalized(),simplex[3]);w=r*w; + order=4; + return(true); + } + break; + /* Triangle */ + case 2: + { + const +Vector3 n(cross((SPXW(1)-SPXW(0)),(SPXW(2)-SPXW(0))).normalized()); + Support( n,simplex[3]); + Support(-n,simplex[4]); + order=4; + return(true); + } + break; + /* Tetrahedron */ + case 3: return(true); + /* Hexahedron */ + case 4: return(true); + } + return(false); + } + #undef SPX + #undef SPXW + }; + +// +// EPA +// +struct EPA + { + // + struct Face + { + const GJK::Mkv* v[3]; + Face* f[3]; + U e[3]; + Vector3 n; + F d; + U mark; + Face* prev; + Face* next; + Face() {} + }; + // + GJK* gjk; + btStackAlloc* sa; + Face* root; + U nfaces; + U iterations; + Vector3 features[2][3]; + Vector3 nearest[2]; + Vector3 normal; + F depth; + Z failed; + // + EPA(GJK* pgjk) + { + gjk = pgjk; + sa = pgjk->sa; + } + // + ~EPA() + { + } + // + inline Vector3 GetCoordinates(const Face* face) const + { + const Vector3 o(face->n*-face->d); + const F a[]={ cross(face->v[0]->w-o,face->v[1]->w-o).length(), + cross(face->v[1]->w-o,face->v[2]->w-o).length(), + cross(face->v[2]->w-o,face->v[0]->w-o).length()}; + const F sm(a[0]+a[1]+a[2]); + return(Vector3(a[1],a[2],a[0])/(sm>0?sm:1)); + } + // + inline Face* FindBest() const + { + Face* bf = 0; + if(root) + { + Face* cf = root; + F bd(cstInf); + do { + if(cf->dd;bf=cf; } + } while(0!=(cf=cf->next)); + } + return(bf); + } + // + inline Z Set(Face* f,const GJK::Mkv* a,const GJK::Mkv* b,const GJK::Mkv* +c) const + { + const Vector3 nrm(cross(b->w-a->w,c->w-a->w)); + const F len(nrm.length()); + const Z valid( (cross(a->w,b->w).dot(nrm)>=-EPA_inface_eps)&& + (cross(b->w,c->w).dot(nrm)>=-EPA_inface_eps)&& + (cross(c->w,a->w).dot(nrm)>=-EPA_inface_eps)); + f->v[0] = a; + f->v[1] = b; + f->v[2] = c; + f->mark = 0; + f->n = nrm/(len>0?len:cstInf); + f->d = Max(0,-f->n.dot(a->w)); + return(valid); + } + // + inline Face* NewFace(const GJK::Mkv* a,const GJK::Mkv* b,const GJK::Mkv* c) + { + Face* pf = (Face*)sa->allocate(sizeof(Face)); + if(Set(pf,a,b,c)) + { + if(root) root->prev=pf; + pf->prev=0; + pf->next=root; + root =pf; + ++nfaces; + } + else + { + pf->prev=pf->next=0; + } + return(pf); + } + // + inline void Detach(Face* face) + { + if(face->prev||face->next) + { + --nfaces; + if(face==root) + { root=face->next;root->prev=0; } + else + { + if(face->next==0) + { face->prev->next=0; } + else + { face->prev->next=face->next;face->next->prev=face->prev; } + } + face->prev=face->next=0; + } + } + // + inline void Link(Face* f0,U e0,Face* f1,U e1) const + { + f0->f[e0]=f1;f1->e[e1]=e0; + f1->f[e1]=f0;f0->e[e0]=e1; + } + // + GJK::Mkv* Support(const Vector3& w) const + { + GJK::Mkv* v =(GJK::Mkv*)sa->allocate(sizeof(GJK::Mkv)); + gjk->Support(w,*v); + return(v); + } + // + U BuildHorizon(U markid,const GJK::Mkv* w,Face& f,U e,Face*& cf,Face*& +ff) + { + static const U mod3[]={0,1,2,0,1}; + U ne(0); + if(f.mark!=markid) + { + const U e1(mod3[e+1]); + if((f.n.dot(w->w)+f.d)>0) + { + Face* nf = NewFace(f.v[e1],f.v[e],w); + Link(nf,0,&f,e); + if(cf) Link(cf,1,nf,2); else ff=nf; + cf=nf;ne=1; + } + else + { + const U e2(mod3[e+2]); + Detach(&f); + f.mark = markid; + ne += BuildHorizon(markid,w,*f.f[e1],f.e[e1],cf,ff); + ne += BuildHorizon(markid,w,*f.f[e2],f.e[e2],cf,ff); + } + } + return(ne); + } + // + inline F EvaluatePD(F accuracy=EPA_accuracy) + { + btBlock* sablock = sa->beginBlock(); + Face* bestface = 0; + U markid(1); + depth = -cstInf; + normal = Vector3(0,0,0); + root = 0; + nfaces = 0; + iterations = 0; + failed = false; + /* Prepare hull */ + if(gjk->EncloseOrigin()) + { + const U* pfidx = 0; + U nfidx= 0; + const U* peidx = 0; + U neidx = 0; + GJK::Mkv* basemkv[5]; + Face* basefaces[6]; + switch(gjk->order) + { + /* Tetrahedron */ + case 3: { + static const U fidx[4][3]={{2,1,0},{3,0,1},{3,1,2},{3,2,0}}; + static const +U eidx[6][4]={{0,0,2,1},{0,1,1,1},{0,2,3,1},{1,0,3,2},{2,0,1,2},{3,0,2,2}}; + pfidx=(const U*)fidx;nfidx=4;peidx=(const U*)eidx;neidx=6; + } break; + /* Hexahedron */ + case 4: { + static const +U fidx[6][3]={{2,0,4},{4,1,2},{1,4,0},{0,3,1},{0,2,3},{1,3,2}}; + static const +U eidx[9][4]={{0,0,4,0},{0,1,2,1},{0,2,1,2},{1,1,5,2},{1,0,2,0},{2,2,3,2},{3,1,5,0},{3,0,4,2},{5,1,4,1}}; + pfidx=(const U*)fidx;nfidx=6;peidx=(const U*)eidx;neidx=9; + } break; + } + U i; + + for( i=0;i<=gjk->order;++i) { +basemkv[i]=(GJK::Mkv*)sa->allocate(sizeof(GJK::Mkv));*basemkv[i]=gjk->simplex[i]; +} + for( i=0;iendBlock(sablock); + return(depth); + } + /* Expand hull */ + for(;iterationsn); + const F d(bf->n.dot(w->w)+bf->d); + bestface = bf; + if(d<-accuracy) + { + Face* cf =0; + Face* ff =0; + U nf = 0; + Detach(bf); + bf->mark=++markid; + for(U i=0;i<3;++i) { +nf+=BuildHorizon(markid,w,*bf->f[i],bf->e[i],cf,ff); } + if(nf<=2) { break; } + Link(cf,1,ff,2); + } else break; + } else break; + } + /* Extract contact */ + if(bestface) + { + const Vector3 b(GetCoordinates(bestface)); + normal = bestface->n; + depth = Max(0,bestface->d); + for(U i=0;i<2;++i) + { + const F s(F(i?-1:1)); + for(U j=0;j<3;++j) + { + features[i][j]=gjk->LocalSupport(s*bestface->v[j]->r,i); + } + } + nearest[0] = features[0][0]*b.x()+features[0][1]*b.y()+features[0][2]*b.z(); + nearest[1] = features[1][0]*b.x()+features[1][1]*b.y()+features[1][2]*b.z(); + } else failed=true; + sa->endBlock(sablock); + return(depth); + } + }; +} + +// +// Api +// + +using namespace gjkepa_impl; + + + +// +bool btGjkEpaSolver::Collide(btConvexShape *shape0,const btTransform &wtrs0, + btConvexShape *shape1,const btTransform &wtrs1, + btScalar radialmargin, + btStackAlloc* stackAlloc, + sResults& results) +{ + + +/* Initialize */ +results.witnesses[0] = +results.witnesses[1] = +results.normal = Vector3(0,0,0); +results.depth = 0; +results.status = sResults::Separated; +results.epa_iterations = 0; +results.gjk_iterations = 0; +/* Use GJK to locate origin */ +GJK gjk(stackAlloc, + wtrs0.getBasis(),wtrs0.getOrigin(),shape0, + wtrs1.getBasis(),wtrs1.getOrigin(),shape1, + radialmargin+EPA_accuracy); +const Z collide(gjk.SearchOrigin()); +results.gjk_iterations = gjk.iterations+1; +if(collide) + { + /* Then EPA for penetration depth */ + EPA epa(&gjk); + const F pd(epa.EvaluatePD()); + results.epa_iterations = epa.iterations+1; + if(pd>0) + { + results.status = sResults::Penetrating; + results.normal = epa.normal; + results.depth = pd; + results.witnesses[0] = epa.nearest[0]; + results.witnesses[1] = epa.nearest[1]; + return(true); + } else { if(epa.failed) results.status=sResults::EPA_Failed; } + } else { if(gjk.failed) results.status=sResults::GJK_Failed; } +return(false); +} + + + + + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h new file mode 100644 index 00000000000..759b30bb17f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h @@ -0,0 +1,53 @@ +/* +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. +*/ + +/* +GJK-EPA collision solver by Nathanael Presson +Nov.2006 +*/ + + +#ifndef _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ +#define _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ +#include "../CollisionShapes/btConvexShape.h" + +class btStackAlloc; + +///btGjkEpaSolver contributed under zlib by Nathanael Presson +struct btGjkEpaSolver +{ +struct sResults + { + enum eStatus + { + Separated, /* Shapes doesnt penetrate */ + Penetrating, /* Shapes are penetrating */ + GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ + EPA_Failed, /* EPA phase fail, bigger problem, need to save parameters, and debug */ + } status; + btVector3 witnesses[2]; + btVector3 normal; + btScalar depth; + int epa_iterations; + int gjk_iterations; + }; +static bool Collide(btConvexShape* shape0,const btTransform& wtrs0, + btConvexShape* shape1,const btTransform& wtrs1, + btScalar radialmargin, + btStackAlloc* stackAlloc, + sResults& results); +}; + +#endif diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp new file mode 100644 index 00000000000..87330493b60 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp @@ -0,0 +1,50 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +EPA Copyright (c) Ricardo Padrela 2006 + +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. +*/ + +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" + +bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver, + btConvexShape* pConvexA, btConvexShape* pConvexB, + const btTransform& transformA, const btTransform& transformB, + btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, + class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc ) +{ + + (void)debugDraw; + (void)v; + (void)simplexSolver; + + const btScalar radialmargin(btScalar(0.)); + + btGjkEpaSolver::sResults results; + if(btGjkEpaSolver::Collide( pConvexA,transformA, + pConvexB,transformB, + radialmargin,stackAlloc,results)) + { + // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); + //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); + wWitnessOnA = results.witnesses[0]; + wWitnessOnB = results.witnesses[1]; + return true; + } + + return false; +} + + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h new file mode 100644 index 00000000000..3916ba0776c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h @@ -0,0 +1,39 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +EPA Copyright (c) Ricardo Padrela 2006 + +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. +*/ +#ifndef BT_GJP_EPA_PENETRATION_DEPTH_H +#define BT_GJP_EPA_PENETRATION_DEPTH_H + +#include "btConvexPenetrationDepthSolver.h" + +///EpaPenetrationDepthSolver uses the Expanding Polytope Algorithm to +///calculate the penetration depth between two convex shapes. +class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver +{ + public : + + bool calcPenDepth( btSimplexSolverInterface& simplexSolver, + btConvexShape* pConvexA, btConvexShape* pConvexB, + const btTransform& transformA, const btTransform& transformB, + btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, + class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc ); + + private : + +}; + +#endif // BT_GJP_EPA_PENETRATION_DEPTH_H + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp new file mode 100644 index 00000000000..f1f3f7f7f6c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp @@ -0,0 +1,299 @@ +/* +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. +*/ + +#include "btGjkPairDetector.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h" + +#if defined(DEBUG) || defined (_DEBUG) +#include //for debug printf +#ifdef __SPU__ +#include +#define printf spu_printf +#endif //__SPU__ +#endif + +//must be above the machine epsilon +#define REL_ERROR2 btScalar(1.0e-6) + +//temp globals, to improve GJK/EPA/penetration calculations +int gNumDeepPenetrationChecks = 0; +int gNumGjkChecks = 0; + + + +btGjkPairDetector::btGjkPairDetector(btConvexShape* objectA,btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) +:m_cachedSeparatingAxis(btScalar(0.),btScalar(0.),btScalar(1.)), +m_penetrationDepthSolver(penetrationDepthSolver), +m_simplexSolver(simplexSolver), +m_minkowskiA(objectA), +m_minkowskiB(objectB), +m_ignoreMargin(false), +m_lastUsedMethod(-1), +m_catchDegeneracies(1) +{ +} + +void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) +{ + btScalar distance=btScalar(0.); + btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 pointOnA,pointOnB; + btTransform localTransA = input.m_transformA; + btTransform localTransB = input.m_transformB; + btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5); + localTransA.getOrigin() -= positionOffset; + localTransB.getOrigin() -= positionOffset; + + btScalar marginA = m_minkowskiA->getMargin(); + btScalar marginB = m_minkowskiB->getMargin(); + + gNumGjkChecks++; + + //for CCD we don't use margins + if (m_ignoreMargin) + { + marginA = btScalar(0.); + marginB = btScalar(0.); + } + + m_curIter = 0; + int gGjkMaxIter = 1000;//this is to catch invalid input, perhaps check for #NaN? + m_cachedSeparatingAxis.setValue(0,1,0); + + bool isValid = false; + bool checkSimplex = false; + bool checkPenetration = true; + m_degenerateSimplex = 0; + + m_lastUsedMethod = -1; + + { + btScalar squaredDistance = SIMD_INFINITY; + btScalar delta = btScalar(0.); + + btScalar margin = marginA + marginB; + + + + m_simplexSolver->reset(); + + for ( ; ; ) + //while (true) + { + + btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* input.m_transformA.getBasis(); + btVector3 seperatingAxisInB = m_cachedSeparatingAxis* input.m_transformB.getBasis(); + + btVector3 pInA = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA); + btVector3 qInB = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); + btPoint3 pWorld = localTransA(pInA); + btPoint3 qWorld = localTransB(qInB); + + btVector3 w = pWorld - qWorld; + delta = m_cachedSeparatingAxis.dot(w); + + // potential exit, they don't overlap + if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared)) + { + checkPenetration = false; + break; + } + + //exit 0: the new point is already in the simplex, or we didn't come any closer + if (m_simplexSolver->inSimplex(w)) + { + m_degenerateSimplex = 1; + checkSimplex = true; + break; + } + // are we getting any closer ? + btScalar f0 = squaredDistance - delta; + btScalar f1 = squaredDistance * REL_ERROR2; + + if (f0 <= f1) + { + if (f0 <= btScalar(0.)) + { + m_degenerateSimplex = 2; + } + checkSimplex = true; + break; + } + //add current vertex to simplex + m_simplexSolver->addVertex(w, pWorld, qWorld); + + //calculate the closest point to the origin (update vector v) + if (!m_simplexSolver->closest(m_cachedSeparatingAxis)) + { + m_degenerateSimplex = 3; + checkSimplex = true; + break; + } + + btScalar previousSquaredDistance = squaredDistance; + squaredDistance = m_cachedSeparatingAxis.length2(); + + //redundant m_simplexSolver->compute_points(pointOnA, pointOnB); + + //are we getting any closer ? + if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance) + { + m_simplexSolver->backup_closest(m_cachedSeparatingAxis); + checkSimplex = true; + break; + } + + //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject + if (m_curIter++ > gGjkMaxIter) + { + #if defined(DEBUG) || defined (_DEBUG) + + printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter); + printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n", + m_cachedSeparatingAxis.getX(), + m_cachedSeparatingAxis.getY(), + m_cachedSeparatingAxis.getZ(), + squaredDistance, + m_minkowskiA->getShapeType(), + m_minkowskiB->getShapeType()); + + #endif + break; + + } + + + bool check = (!m_simplexSolver->fullSimplex()); + //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex()); + + if (!check) + { + //do we need this backup_closest here ? + m_simplexSolver->backup_closest(m_cachedSeparatingAxis); + break; + } + } + + if (checkSimplex) + { + m_simplexSolver->compute_points(pointOnA, pointOnB); + normalInB = pointOnA-pointOnB; + btScalar lenSqr = m_cachedSeparatingAxis.length2(); + //valid normal + if (lenSqr < 0.0001) + { + m_degenerateSimplex = 5; + } + if (lenSqr > SIMD_EPSILON*SIMD_EPSILON) + { + btScalar rlen = btScalar(1.) / btSqrt(lenSqr ); + normalInB *= rlen; //normalize + btScalar s = btSqrt(squaredDistance); + + btAssert(s > btScalar(0.0)); + pointOnA -= m_cachedSeparatingAxis * (marginA / s); + pointOnB += m_cachedSeparatingAxis * (marginB / s); + distance = ((btScalar(1.)/rlen) - margin); + isValid = true; + + m_lastUsedMethod = 1; + } else + { + m_lastUsedMethod = 2; + } + } + + bool catchDegeneratePenetrationCase = + (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance+margin) < 0.01)); + + //if (checkPenetration && !isValid) + if (checkPenetration && (!isValid || catchDegeneratePenetrationCase )) + { + //penetration case + + //if there is no way to handle penetrations, bail out + if (m_penetrationDepthSolver) + { + // Penetration depth case. + btVector3 tmpPointOnA,tmpPointOnB; + + gNumDeepPenetrationChecks++; + + bool isValid2 = m_penetrationDepthSolver->calcPenDepth( + *m_simplexSolver, + m_minkowskiA,m_minkowskiB, + localTransA,localTransB, + m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB, + debugDraw,input.m_stackAlloc + ); + + if (isValid2) + { + btVector3 tmpNormalInB = tmpPointOnB-tmpPointOnA; + btScalar lenSqr = tmpNormalInB.length2(); + if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON)) + { + tmpNormalInB /= btSqrt(lenSqr); + btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length(); + //only replace valid penetrations when the result is deeper (check) + if (!isValid || (distance2 < distance)) + { + distance = distance2; + pointOnA = tmpPointOnA; + pointOnB = tmpPointOnB; + normalInB = tmpNormalInB; + isValid = true; + m_lastUsedMethod = 3; + } else + { + + } + } else + { + //isValid = false; + m_lastUsedMethod = 4; + } + } else + { + m_lastUsedMethod = 5; + } + + } + } + } + + if (isValid) + { +#ifdef __SPU__ + //spu_printf("distance\n"); +#endif //__CELLOS_LV2__ + + + output.addContactPoint( + normalInB, + pointOnB+positionOffset, + distance); + //printf("gjk add:%f",distance); + } + + +} + + + + + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h new file mode 100644 index 00000000000..af0fe32f6c7 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h @@ -0,0 +1,85 @@ +/* +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. +*/ + + + + +#ifndef GJK_PAIR_DETECTOR_H +#define GJK_PAIR_DETECTOR_H + +#include "btDiscreteCollisionDetectorInterface.h" +#include "../../LinearMath/btPoint3.h" +#include "../CollisionShapes/btCollisionMargin.h" + +class btConvexShape; +#include "btSimplexSolverInterface.h" +class btConvexPenetrationDepthSolver; + +/// btGjkPairDetector uses GJK to implement the btDiscreteCollisionDetectorInterface +class btGjkPairDetector : public btDiscreteCollisionDetectorInterface +{ + + + btVector3 m_cachedSeparatingAxis; + btConvexPenetrationDepthSolver* m_penetrationDepthSolver; + btSimplexSolverInterface* m_simplexSolver; + btConvexShape* m_minkowskiA; + btConvexShape* m_minkowskiB; + bool m_ignoreMargin; + + +public: + + //some debugging to fix degeneracy problems + int m_lastUsedMethod; + int m_curIter; + int m_degenerateSimplex; + int m_catchDegeneracies; + + + btGjkPairDetector(btConvexShape* objectA,btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + virtual ~btGjkPairDetector() {}; + + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw); + + void setMinkowskiA(btConvexShape* minkA) + { + m_minkowskiA = minkA; + } + + void setMinkowskiB(btConvexShape* minkB) + { + m_minkowskiB = minkB; + } + void setCachedSeperatingAxis(const btVector3& seperatingAxis) + { + m_cachedSeparatingAxis = seperatingAxis; + } + + void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver) + { + m_penetrationDepthSolver = penetrationDepthSolver; + } + + ///don't use setIgnoreMargin, it's for Bullet's internal use + void setIgnoreMargin(bool ignoreMargin) + { + m_ignoreMargin = ignoreMargin; + } + + +}; + +#endif //GJK_PAIR_DETECTOR_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h new file mode 100644 index 00000000000..f6a893151da --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h @@ -0,0 +1,99 @@ +/* +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. +*/ + +#ifndef MANIFOLD_CONTACT_POINT_H +#define MANIFOLD_CONTACT_POINT_H + +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btTransformUtil.h" + + + + + +/// ManifoldContactPoint collects and maintains persistent contactpoints. +/// used to improve stability and performance of rigidbody dynamics response. +class btManifoldPoint + { + public: + btManifoldPoint() + :m_userPersistentData(0), + m_lifeTime(0) + { + } + + btManifoldPoint( const btVector3 &pointA, const btVector3 &pointB, + const btVector3 &normal, + btScalar distance ) : + m_localPointA( pointA ), + m_localPointB( pointB ), + m_normalWorldOnB( normal ), + m_distance1( distance ), + m_combinedFriction(btScalar(0.)), + m_combinedRestitution(btScalar(0.)), + m_userPersistentData(0), + m_lifeTime(0) + { + + + } + + + + btVector3 m_localPointA; + btVector3 m_localPointB; + btVector3 m_positionWorldOnB; + ///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity + btVector3 m_positionWorldOnA; + btVector3 m_normalWorldOnB; + + btScalar m_distance1; + btScalar m_combinedFriction; + btScalar m_combinedRestitution; + + + mutable void* m_userPersistentData; + + int m_lifeTime;//lifetime of the contactpoint in frames + + btScalar getDistance() const + { + return m_distance1; + } + int getLifeTime() const + { + return m_lifeTime; + } + + const btVector3& getPositionWorldOnA() const { + return m_positionWorldOnA; +// return m_positionWorldOnB + m_normalWorldOnB * m_distance1; + } + + const btVector3& getPositionWorldOnB() const + { + return m_positionWorldOnB; + } + + void setDistance(btScalar dist) + { + m_distance1 = dist; + } + + + + }; + +#endif //MANIFOLD_CONTACT_POINT_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp new file mode 100644 index 00000000000..c4bab3a134a --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp @@ -0,0 +1,334 @@ +/* +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. +*/ + +#include "btMinkowskiPenetrationDepthSolver.h" +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" + + + + +#define NUM_UNITSPHERE_POINTS 42 +static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = +{ +btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), +btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), +btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), +btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), +btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), +btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), +btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), +btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), +btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), +btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), +btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), +btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), +btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), +btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), +btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), +btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), +btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), +btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), +btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), +btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), +btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), +btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), +btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), +btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), +btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), +btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), +btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), +btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), +btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), +btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), +btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), +btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), +btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), +btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), +btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), +btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), +btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), +btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), +btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), +btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), +btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), +btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) +}; + + +bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver, + btConvexShape* convexA,btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btPoint3& pa, btPoint3& pb, + class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc + ) +{ + + (void)stackAlloc; + (void)v; + + + struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result + { + + btIntermediateResult():m_hasResult(false) + { + } + + btVector3 m_normalOnBInWorld; + btVector3 m_pointInWorld; + btScalar m_depth; + bool m_hasResult; + + virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1) + { + (void)partId0; + (void)index0; + (void)partId1; + (void)index1; + } + void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + m_normalOnBInWorld = normalOnBInWorld; + m_pointInWorld = pointInWorld; + m_depth = depth; + m_hasResult = true; + } + }; + + //just take fixed number of orientation, and sample the penetration depth in that direction + btScalar minProj = btScalar(1e30); + btVector3 minNorm; + btVector3 minVertex; + btVector3 minA,minB; + btVector3 seperatingAxisInA,seperatingAxisInB; + btVector3 pInA,qInB,pWorld,qWorld,w; + +#define USE_BATCHED_SUPPORT 1 +#ifdef USE_BATCHED_SUPPORT + + btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + btVector3 seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + int i; + + int numSampleDirections = NUM_UNITSPHERE_POINTS; + + for (i=0;igetNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transA.getBasis() * norm; + sPenetrationDirections[numSampleDirections] = norm; + seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); + seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); + numSampleDirections++; + } + } + } + + { + int numPDB = convexB->getNumPreferredPenetrationDirections(); + if (numPDB) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transB.getBasis() * norm; + sPenetrationDirections[numSampleDirections] = norm; + seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis(); + seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis(); + numSampleDirections++; + } + } + } + + + + convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections); + convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections); + + for (i=0;igetNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transA.getBasis() * norm; + sPenetrationDirections[numSampleDirections] = norm; + numSampleDirections++; + } + } + } + + { + int numPDB = convexB->getNumPreferredPenetrationDirections(); + if (numPDB) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + norm = transB.getBasis() * norm; + sPenetrationDirections[numSampleDirections] = norm; + numSampleDirections++; + } + } + } + + for (int i=0;ilocalGetSupportingVertexWithoutMargin(seperatingAxisInA); + qInB = convexB->localGetSupportingVertexWithoutMargin(seperatingAxisInB); + pWorld = transA(pInA); + qWorld = transB(qInB); + w = qWorld - pWorld; + btScalar delta = norm.dot(w); + //find smallest delta + if (delta < minProj) + { + minProj = delta; + minNorm = norm; + minA = pWorld; + minB = qWorld; + } + } +#endif //USE_BATCHED_SUPPORT + + //add the margins + + minA += minNorm*convexA->getMargin(); + minB -= minNorm*convexB->getMargin(); + //no penetration + if (minProj < btScalar(0.)) + return false; + + minProj += (convexA->getMargin() + convexB->getMargin()); + + + + + +//#define DEBUG_DRAW 1 +#ifdef DEBUG_DRAW + if (debugDraw) + { + btVector3 color(0,1,0); + debugDraw->drawLine(minA,minB,color); + color = btVector3 (1,1,1); + btVector3 vec = minB-minA; + btScalar prj2 = minNorm.dot(vec); + debugDraw->drawLine(minA,minA+(minNorm*minProj),color); + + } +#endif //DEBUG_DRAW + + + + btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0); + + btScalar offsetDist = minProj; + btVector3 offset = minNorm * offsetDist; + + + + btGjkPairDetector::ClosestPointInput input; + + btVector3 newOrg = transA.getOrigin() + offset; + + btTransform displacedTrans = transA; + displacedTrans.setOrigin(newOrg); + + input.m_transformA = displacedTrans; + input.m_transformB = transB; + input.m_maximumDistanceSquared = btScalar(1e30);//minProj; + + btIntermediateResult res; + gjkdet.getClosestPoints(input,res,debugDraw); + + btScalar correctedMinNorm = minProj - res.m_depth; + + + //the penetration depth is over-estimated, relax it + btScalar penetration_relaxation= btScalar(1.); + minNorm*=penetration_relaxation; + + if (res.m_hasResult) + { + + pa = res.m_pointInWorld - minNorm * correctedMinNorm; + pb = res.m_pointInWorld; + +#ifdef DEBUG_DRAW + if (debugDraw) + { + btVector3 color(1,0,0); + debugDraw->drawLine(pa,pb,color); + } +#endif//DEBUG_DRAW + + + } + return res.m_hasResult; +} + + + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h new file mode 100644 index 00000000000..b348b21b52a --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h @@ -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. +*/ + +#ifndef MINKOWSKI_PENETRATION_DEPTH_SOLVER_H +#define MINKOWSKI_PENETRATION_DEPTH_SOLVER_H + +#include "btConvexPenetrationDepthSolver.h" + +///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation. +///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points. +class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver +{ +public: + + virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, + btConvexShape* convexA,btConvexShape* convexB, + const btTransform& transA,const btTransform& transB, + btVector3& v, btPoint3& pa, btPoint3& pb, + class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc + ); + +}; + +#endif //MINKOWSKI_PENETRATION_DEPTH_SOLVER_H + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp new file mode 100644 index 00000000000..08cb3ed334d --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp @@ -0,0 +1,246 @@ +/* +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. +*/ + + +#include "btPersistentManifold.h" +#include "LinearMath/btTransform.h" +#include + +btScalar gContactBreakingThreshold = btScalar(0.02); +ContactDestroyedCallback gContactDestroyedCallback = 0; + + + +btPersistentManifold::btPersistentManifold() +:m_body0(0), +m_body1(0), +m_cachedPoints (0), +m_index1(0) +{ +} + + +void btPersistentManifold::clearManifold() +{ + int i; + for (i=0;i +void btPersistentManifold::DebugPersistency() +{ + int i; + printf("DebugPersistency : numPoints %d\n",m_cachedPoints); + for (i=0;i1) + printf("error in clearUserCache\n"); + } + } + assert(occurance<=0); +#endif //DEBUG_PERSISTENCY + + if (pt.m_userPersistentData && gContactDestroyedCallback) + { + (*gContactDestroyedCallback)(pt.m_userPersistentData); + pt.m_userPersistentData = 0; + } + +#ifdef DEBUG_PERSISTENCY + DebugPersistency(); +#endif + } + + +} + + +int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt) +{ + + //calculate 4 possible cases areas, and take biggest area + //also need to keep 'deepest' + + int maxPenetrationIndex = -1; +#define KEEP_DEEPEST_POINT 1 +#ifdef KEEP_DEEPEST_POINT + btScalar maxPenetration = pt.getDistance(); + for (int i=0;i<4;i++) + { + if (m_pointCache[i].getDistance() < maxPenetration) + { + maxPenetrationIndex = i; + maxPenetration = m_pointCache[i].getDistance(); + } + } +#endif //KEEP_DEEPEST_POINT + + btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.)); + if (maxPenetrationIndex != 0) + { + btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA; + btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA; + btVector3 cross = a0.cross(b0); + res0 = cross.length2(); + } + if (maxPenetrationIndex != 1) + { + btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA; + btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA; + btVector3 cross = a1.cross(b1); + res1 = cross.length2(); + } + + if (maxPenetrationIndex != 2) + { + btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA; + btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA; + btVector3 cross = a2.cross(b2); + res2 = cross.length2(); + } + + if (maxPenetrationIndex != 3) + { + btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA; + btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA; + btVector3 cross = a3.cross(b3); + res3 = cross.length2(); + } + + btVector4 maxvec(res0,res1,res2,res3); + int biggestarea = maxvec.closestAxis4(); + return biggestarea; +} + + +int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const +{ + btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold(); + int size = getNumContacts(); + int nearestPoint = -1; + for( int i = 0; i < size; i++ ) + { + const btManifoldPoint &mp = m_pointCache[i]; + + btVector3 diffA = mp.m_localPointA- newPoint.m_localPointA; + const btScalar distToManiPoint = diffA.dot(diffA); + if( distToManiPoint < shortestDist ) + { + shortestDist = distToManiPoint; + nearestPoint = i; + } + } + return nearestPoint; +} + +void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint) +{ + assert(validContactDistance(newPoint)); + + int insertIndex = getNumContacts(); + if (insertIndex == MANIFOLD_CACHE_SIZE) + { +#if MANIFOLD_CACHE_SIZE >= 4 + //sort cache so best points come first, based on area + insertIndex = sortCachedPoints(newPoint); +#else + insertIndex = 0; +#endif + + + } else + { + m_cachedPoints++; + + + } + replaceContactPoint(newPoint,insertIndex); +} + +btScalar btPersistentManifold::getContactBreakingThreshold() const +{ + return gContactBreakingThreshold; +} + +void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB) +{ + int i; + + /// first refresh worldspace positions and distance + for (i=getNumContacts()-1;i>=0;i--) + { + btManifoldPoint &manifoldPoint = m_pointCache[i]; + manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA ); + manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB ); + manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB); + manifoldPoint.m_lifeTime++; + } + + /// then + btScalar distance2d; + btVector3 projectedDifference,projectedPoint; + for (i=getNumContacts()-1;i>=0;i--) + { + + btManifoldPoint &manifoldPoint = m_pointCache[i]; + //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction) + if (!validContactDistance(manifoldPoint)) + { + removeContactPoint(i); + } else + { + //contact also becomes invalid when relative movement orthogonal to normal exceeds margin + projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1; + projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint; + distance2d = projectedDifference.dot(projectedDifference); + if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() ) + { + removeContactPoint(i); + } + } + } +#ifdef DEBUG_PERSISTENCY + DebugPersistency(); +#endif // +} + + + + + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h new file mode 100644 index 00000000000..a5918b84db3 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h @@ -0,0 +1,161 @@ +/* +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. +*/ + +#ifndef PERSISTENT_MANIFOLD_H +#define PERSISTENT_MANIFOLD_H + + +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btTransform.h" +#include "btManifoldPoint.h" + +struct btCollisionResult; + +///contact breaking and merging threshold +extern btScalar gContactBreakingThreshold; + +typedef bool (*ContactDestroyedCallback)(void* userPersistentData); +extern ContactDestroyedCallback gContactDestroyedCallback; + + + + +#define MANIFOLD_CACHE_SIZE 4 + +///btPersistentManifold maintains contact points, and reduces them to 4. +///It does contact filtering/contact reduction. +ATTRIBUTE_ALIGNED16( class) btPersistentManifold +{ + + btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE]; + + /// this two body pointers can point to the physics rigidbody class. + /// void* will allow any rigidbody class + void* m_body0; + void* m_body1; + int m_cachedPoints; + + + /// sort cached points so most isolated points come first + int sortCachedPoints(const btManifoldPoint& pt); + + int findContactPoint(const btManifoldPoint* unUsed, int numUnused,const btManifoldPoint& pt); + +public: + + int m_index1; + + btPersistentManifold(); + + btPersistentManifold(void* body0,void* body1) + : m_body0(body0),m_body1(body1),m_cachedPoints(0) + { + } + + inline void* getBody0() { return m_body0;} + inline void* getBody1() { return m_body1;} + + inline const void* getBody0() const { return m_body0;} + inline const void* getBody1() const { return m_body1;} + + void setBodies(void* body0,void* body1) + { + m_body0 = body0; + m_body1 = body1; + } + + void clearUserCache(btManifoldPoint& pt); + +#ifdef DEBUG_PERSISTENCY + void DebugPersistency(); +#endif // + + inline int getNumContacts() const { return m_cachedPoints;} + + inline const btManifoldPoint& getContactPoint(int index) const + { + btAssert(index < m_cachedPoints); + return m_pointCache[index]; + } + + inline btManifoldPoint& getContactPoint(int index) + { + btAssert(index < m_cachedPoints); + return m_pointCache[index]; + } + + /// todo: get this margin from the current physics / collision environment + btScalar getContactBreakingThreshold() const; + + int getCacheEntry(const btManifoldPoint& newPoint) const; + + void AddManifoldPoint( const btManifoldPoint& newPoint); + + void removeContactPoint (int index) + { + clearUserCache(m_pointCache[index]); + + int lastUsedIndex = getNumContacts() - 1; +// m_pointCache[index] = m_pointCache[lastUsedIndex]; + if(index != lastUsedIndex) + { + m_pointCache[index] = m_pointCache[lastUsedIndex]; + //get rid of duplicated userPersistentData pointer + m_pointCache[lastUsedIndex].m_userPersistentData = 0; + } + + btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0); + m_cachedPoints--; + } + void replaceContactPoint(const btManifoldPoint& newPoint,int insertIndex) + { + btAssert(validContactDistance(newPoint)); + +#define MAINTAIN_PERSISTENCY 1 +#ifdef MAINTAIN_PERSISTENCY + int lifeTime = m_pointCache[insertIndex].getLifeTime(); + btAssert(lifeTime>=0); + void* cache = m_pointCache[insertIndex].m_userPersistentData; + + m_pointCache[insertIndex] = newPoint; + + m_pointCache[insertIndex].m_userPersistentData = cache; + m_pointCache[insertIndex].m_lifeTime = lifeTime; +#else + clearUserCache(m_pointCache[insertIndex]); + m_pointCache[insertIndex] = newPoint; + +#endif + } + + bool validContactDistance(const btManifoldPoint& pt) const + { + return pt.m_distance1 <= getContactBreakingThreshold(); + } + /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin + void refreshContactPoints( const btTransform& trA,const btTransform& trB); + + void clearManifold(); + + + +} +; + + + + + +#endif //PERSISTENT_MANIFOLD_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h new file mode 100644 index 00000000000..6262f44b9f1 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPointCollector.h @@ -0,0 +1,61 @@ +/* +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. +*/ + +#ifndef POINT_COLLECTOR_H +#define POINT_COLLECTOR_H + +#include "btDiscreteCollisionDetectorInterface.h" + + + +struct btPointCollector : public btDiscreteCollisionDetectorInterface::Result +{ + + + btVector3 m_normalOnBInWorld; + btVector3 m_pointInWorld; + btScalar m_distance;//negative means penetration + + bool m_hasResult; + + btPointCollector () + : m_distance(btScalar(1e30)),m_hasResult(false) + { + } + + virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1) + { + (void)partId0; + (void)index0; + (void)partId1; + (void)index1; + //?? + } + + virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) + { + if (depth< m_distance) + { + m_hasResult = true; + m_normalOnBInWorld = normalOnBInWorld; + m_pointInWorld = pointInWorld; + //negative means penetration + m_distance = depth; + } + } +}; + +#endif //POINT_COLLECTOR_H + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp new file mode 100644 index 00000000000..31b91467777 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp @@ -0,0 +1,101 @@ +/* +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. +*/ + + +#include "btRaycastCallback.h" + +btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to) + : + m_from(from), + m_to(to), + m_hitFraction(btScalar(1.)) +{ + +} + + + +void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) +{ + + + const btVector3 &vert0=triangle[0]; + const btVector3 &vert1=triangle[1]; + const btVector3 &vert2=triangle[2]; + + btVector3 v10; v10 = vert1 - vert0 ; + btVector3 v20; v20 = vert2 - vert0 ; + + btVector3 triangleNormal; triangleNormal = v10.cross( v20 ); + + const btScalar dist = vert0.dot(triangleNormal); + btScalar dist_a = triangleNormal.dot(m_from) ; + dist_a-= dist; + btScalar dist_b = triangleNormal.dot(m_to); + dist_b -= dist; + + if ( dist_a * dist_b >= btScalar(0.0) ) + { + return ; // same sign + } + + const btScalar proj_length=dist_a-dist_b; + const btScalar distance = (dist_a)/(proj_length); + // Now we have the intersection point on the plane, we'll see if it's inside the triangle + // Add an epsilon as a tolerance for the raycast, + // in case the ray hits exacly on the edge of the triangle. + // It must be scaled for the triangle size. + + if(distance < m_hitFraction) + { + + + btScalar edge_tolerance =triangleNormal.length2(); + edge_tolerance *= btScalar(-0.0001); + btVector3 point; point.setInterpolate3( m_from, m_to, distance); + { + btVector3 v0p; v0p = vert0 - point; + btVector3 v1p; v1p = vert1 - point; + btVector3 cp0; cp0 = v0p.cross( v1p ); + + if ( (btScalar)(cp0.dot(triangleNormal)) >=edge_tolerance) + { + + + btVector3 v2p; v2p = vert2 - point; + btVector3 cp1; + cp1 = v1p.cross( v2p); + if ( (btScalar)(cp1.dot(triangleNormal)) >=edge_tolerance) + { + btVector3 cp2; + cp2 = v2p.cross(v0p); + + if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) + { + + if ( dist_a > 0 ) + { + m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex); + } + else + { + m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex); + } + } + } + } + } + } +} diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h new file mode 100644 index 00000000000..a0bbc9f8fe9 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h @@ -0,0 +1,42 @@ +/* +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. +*/ + +#ifndef RAYCAST_TRI_CALLBACK_H +#define RAYCAST_TRI_CALLBACK_H + +#include "../CollisionShapes/btTriangleCallback.h" +struct btBroadphaseProxy; + + +class btTriangleRaycastCallback: public btTriangleCallback +{ +public: + + //input + btVector3 m_from; + btVector3 m_to; + + btScalar m_hitFraction; + + btTriangleRaycastCallback(const btVector3& from,const btVector3& to); + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) = 0; + +}; + +#endif //RAYCAST_TRI_CALLBACK_H + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h new file mode 100644 index 00000000000..58393b2eab9 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h @@ -0,0 +1,64 @@ +/* +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. +*/ + + + +#ifndef SIMPLEX_SOLVER_INTERFACE_H +#define SIMPLEX_SOLVER_INTERFACE_H + +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btPoint3.h" + +#define NO_VIRTUAL_INTERFACE 1 +#ifdef NO_VIRTUAL_INTERFACE +#include "btVoronoiSimplexSolver.h" +#define btSimplexSolverInterface btVoronoiSimplexSolver +#else + +/// btSimplexSolverInterface can incrementally calculate distance between origin and up to 4 vertices +/// Used by GJK or Linear Casting. Can be implemented by the Johnson-algorithm or alternative approaches based on +/// voronoi regions or barycentric coordinates +class btSimplexSolverInterface +{ + public: + virtual ~btSimplexSolverInterface() {}; + + virtual void reset() = 0; + + virtual void addVertex(const btVector3& w, const btPoint3& p, const btPoint3& q) = 0; + + virtual bool closest(btVector3& v) = 0; + + virtual btScalar maxVertex() = 0; + + virtual bool fullSimplex() const = 0; + + virtual int getSimplex(btPoint3 *pBuf, btPoint3 *qBuf, btVector3 *yBuf) const = 0; + + virtual bool inSimplex(const btVector3& w) = 0; + + virtual void backup_closest(btVector3& v) = 0; + + virtual bool emptySimplex() const = 0; + + virtual void compute_points(btPoint3& p1, btPoint3& p2) = 0; + + virtual int numVertices() const =0; + + +}; +#endif +#endif //SIMPLEX_SOLVER_INTERFACE_H + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp new file mode 100644 index 00000000000..687738b7fa9 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp @@ -0,0 +1,139 @@ +/* +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. +*/ + + +#include "btSubSimplexConvexCast.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" + + +btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) +:m_simplexSolver(simplexSolver), +m_convexA(convexA),m_convexB(convexB) +{ +} + +///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases. +///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565 +#ifdef BT_USE_DOUBLE_PRECISION +#define MAX_ITERATIONS 64 +#else +#define MAX_ITERATIONS 32 +#endif +bool btSubsimplexConvexCast::calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result) +{ + + btMinkowskiSumShape combi(m_convexA,m_convexB); + btMinkowskiSumShape* convex = &combi; + + btTransform rayFromLocalA; + btTransform rayToLocalA; + + rayFromLocalA = fromA.inverse()* fromB; + rayToLocalA = toA.inverse()* toB; + + + m_simplexSolver->reset(); + + convex->setTransformB(btTransform(rayFromLocalA.getBasis())); + + //btScalar radius = btScalar(0.01); + + btScalar lambda = btScalar(0.); + //todo: need to verify this: + //because of minkowski difference, we need the inverse direction + + btVector3 s = -rayFromLocalA.getOrigin(); + btVector3 r = -(rayToLocalA.getOrigin()-rayFromLocalA.getOrigin()); + btVector3 x = s; + btVector3 v; + btVector3 arbitraryPoint = convex->localGetSupportingVertex(r); + + v = x - arbitraryPoint; + + int maxIter = MAX_ITERATIONS; + + btVector3 n; + n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + bool hasResult = false; + btVector3 c; + + btScalar lastLambda = lambda; + + + btScalar dist2 = v.length2(); +#ifdef BT_USE_DOUBLE_PRECISION + btScalar epsilon = btScalar(0.0001); +#else + btScalar epsilon = btScalar(0.0001); +#endif //BT_USE_DOUBLE_PRECISION + btVector3 w,p; + btScalar VdotR; + + while ( (dist2 > epsilon) && maxIter--) + { + p = convex->localGetSupportingVertex( v); + w = x - p; + + btScalar VdotW = v.dot(w); + + if ( VdotW > btScalar(0.)) + { + VdotR = v.dot(r); + + if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON)) + return false; + else + { + lambda = lambda - VdotW / VdotR; + x = s + lambda * r; + m_simplexSolver->reset(); + //check next line + w = x-p; + lastLambda = lambda; + n = v; + hasResult = true; + } + } + m_simplexSolver->addVertex( w, x , p); + if (m_simplexSolver->closest(v)) + { + dist2 = v.length2(); + hasResult = true; + //printf("V=%f , %f, %f\n",v[0],v[1],v[2]); + //printf("DIST2=%f\n",dist2); + //printf("numverts = %i\n",m_simplexSolver->numVertices()); + } else + { + dist2 = btScalar(0.); + } + } + + //int numiter = MAX_ITERATIONS - maxIter; +// printf("number of iterations: %d", numiter); + result.m_fraction = lambda; + result.m_normal = n; + + return true; +} + + + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h new file mode 100644 index 00000000000..05662db5d23 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h @@ -0,0 +1,50 @@ +/* +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. +*/ + + +#ifndef SUBSIMPLEX_CONVEX_CAST_H +#define SUBSIMPLEX_CONVEX_CAST_H + +#include "btConvexCast.h" +#include "btSimplexSolverInterface.h" +class btConvexShape; + +/// btSubsimplexConvexCast implements Gino van den Bergens' paper +///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection" +/// GJK based Ray Cast, optimized version +/// Objects should not start in overlap, otherwise results are not defined. +class btSubsimplexConvexCast : public btConvexCast +{ + btSimplexSolverInterface* m_simplexSolver; + const btConvexShape* m_convexA; + const btConvexShape* m_convexB; + +public: + + btSubsimplexConvexCast (const btConvexShape* shapeA,const btConvexShape* shapeB,btSimplexSolverInterface* simplexSolver); + + //virtual ~btSubsimplexConvexCast(); + ///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects. + ///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector. + virtual bool calcTimeOfImpact( + const btTransform& fromA, + const btTransform& toA, + const btTransform& fromB, + const btTransform& toB, + CastResult& result); + +}; + +#endif //SUBSIMPLEX_CONVEX_CAST_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp new file mode 100644 index 00000000000..105b7eccefa --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp @@ -0,0 +1,607 @@ + +/* +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. + + Elsevier CDROM license agreements grants nonexclusive license to use the software + for any purpose, commercial or non-commercial as long as the following credit is included + identifying the original source of the software: + + Parts of the source are "from the book Real-Time Collision Detection by + Christer Ericson, published by Morgan Kaufmann Publishers, + (c) 2005 Elsevier Inc." + +*/ + + +#include "btVoronoiSimplexSolver.h" +#include +#include + +#define VERTA 0 +#define VERTB 1 +#define VERTC 2 +#define VERTD 3 + +#define CATCH_DEGENERATE_TETRAHEDRON 1 +void btVoronoiSimplexSolver::removeVertex(int index) +{ + + assert(m_numVertices>0); + m_numVertices--; + m_simplexVectorW[index] = m_simplexVectorW[m_numVertices]; + m_simplexPointsP[index] = m_simplexPointsP[m_numVertices]; + m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices]; +} + +void btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts) +{ + if ((numVertices() >= 4) && (!usedVerts.usedVertexD)) + removeVertex(3); + + if ((numVertices() >= 3) && (!usedVerts.usedVertexC)) + removeVertex(2); + + if ((numVertices() >= 2) && (!usedVerts.usedVertexB)) + removeVertex(1); + + if ((numVertices() >= 1) && (!usedVerts.usedVertexA)) + removeVertex(0); + +} + + + + + +//clear the simplex, remove all the vertices +void btVoronoiSimplexSolver::reset() +{ + m_cachedValidClosest = false; + m_numVertices = 0; + m_needsUpdate = true; + m_lastW = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + m_cachedBC.reset(); +} + + + + //add a vertex +void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btPoint3& p, const btPoint3& q) +{ + m_lastW = w; + m_needsUpdate = true; + + m_simplexVectorW[m_numVertices] = w; + m_simplexPointsP[m_numVertices] = p; + m_simplexPointsQ[m_numVertices] = q; + + m_numVertices++; +} + +bool btVoronoiSimplexSolver::updateClosestVectorAndPoints() +{ + + if (m_needsUpdate) + { + m_cachedBC.reset(); + + m_needsUpdate = false; + + switch (numVertices()) + { + case 0: + m_cachedValidClosest = false; + break; + case 1: + { + m_cachedP1 = m_simplexPointsP[0]; + m_cachedP2 = m_simplexPointsQ[0]; + m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0] + m_cachedBC.reset(); + m_cachedBC.setBarycentricCoordinates(btScalar(1.),btScalar(0.),btScalar(0.),btScalar(0.)); + m_cachedValidClosest = m_cachedBC.isValid(); + break; + }; + case 2: + { + //closest point origin from line segment + const btVector3& from = m_simplexVectorW[0]; + const btVector3& to = m_simplexVectorW[1]; + btVector3 nearest; + + btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 diff = p - from; + btVector3 v = to - from; + btScalar t = v.dot(diff); + + if (t > 0) { + btScalar dotVV = v.dot(v); + if (t < dotVV) { + t /= dotVV; + diff -= t*v; + m_cachedBC.m_usedVertices.usedVertexA = true; + m_cachedBC.m_usedVertices.usedVertexB = true; + } else { + t = 1; + diff -= v; + //reduce to 1 point + m_cachedBC.m_usedVertices.usedVertexB = true; + } + } else + { + t = 0; + //reduce to 1 point + m_cachedBC.m_usedVertices.usedVertexA = true; + } + m_cachedBC.setBarycentricCoordinates(1-t,t); + nearest = from + t*v; + + m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]); + m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]); + m_cachedV = m_cachedP1 - m_cachedP2; + + reduceVertices(m_cachedBC.m_usedVertices); + + m_cachedValidClosest = m_cachedBC.isValid(); + break; + } + case 3: + { + //closest point origin from triangle + btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); + + const btVector3& a = m_simplexVectorW[0]; + const btVector3& b = m_simplexVectorW[1]; + const btVector3& c = m_simplexVectorW[2]; + + closestPtPointTriangle(p,a,b,c,m_cachedBC); + m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2]; + + m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2]; + + m_cachedV = m_cachedP1-m_cachedP2; + + reduceVertices (m_cachedBC.m_usedVertices); + m_cachedValidClosest = m_cachedBC.isValid(); + + break; + } + case 4: + { + + + btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); + + const btVector3& a = m_simplexVectorW[0]; + const btVector3& b = m_simplexVectorW[1]; + const btVector3& c = m_simplexVectorW[2]; + const btVector3& d = m_simplexVectorW[3]; + + bool hasSeperation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC); + + if (hasSeperation) + { + + m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] + + m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3]; + + m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] + + m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] + + m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] + + m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3]; + + m_cachedV = m_cachedP1-m_cachedP2; + reduceVertices (m_cachedBC.m_usedVertices); + } else + { +// printf("sub distance got penetration\n"); + + if (m_cachedBC.m_degenerate) + { + m_cachedValidClosest = false; + } else + { + m_cachedValidClosest = true; + //degenerate case == false, penetration = true + zero + m_cachedV.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + break; + } + + m_cachedValidClosest = m_cachedBC.isValid(); + + //closest point origin from tetrahedron + break; + } + default: + { + m_cachedValidClosest = false; + } + }; + } + + return m_cachedValidClosest; + +} + +//return/calculate the closest vertex +bool btVoronoiSimplexSolver::closest(btVector3& v) +{ + bool succes = updateClosestVectorAndPoints(); + v = m_cachedV; + return succes; +} + + + +btScalar btVoronoiSimplexSolver::maxVertex() +{ + int i, numverts = numVertices(); + btScalar maxV = btScalar(0.); + for (i=0;i= btScalar(0.0) && d4 <= d3) + { + result.m_closestPointOnSimplex = b; + result.m_usedVertices.usedVertexB = true; + result.setBarycentricCoordinates(0,1,0); + + return true; // b; // barycentric coordinates (0,1,0) + } + // Check if P in edge region of AB, if so return projection of P onto AB + btScalar vc = d1*d4 - d3*d2; + if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0)) { + btScalar v = d1 / (d1 - d3); + result.m_closestPointOnSimplex = a + v * ab; + result.m_usedVertices.usedVertexA = true; + result.m_usedVertices.usedVertexB = true; + result.setBarycentricCoordinates(1-v,v,0); + return true; + //return a + v * ab; // barycentric coordinates (1-v,v,0) + } + + // Check if P in vertex region outside C + btVector3 cp = p - c; + btScalar d5 = ab.dot(cp); + btScalar d6 = ac.dot(cp); + if (d6 >= btScalar(0.0) && d5 <= d6) + { + result.m_closestPointOnSimplex = c; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(0,0,1); + return true;//c; // barycentric coordinates (0,0,1) + } + + // Check if P in edge region of AC, if so return projection of P onto AC + btScalar vb = d5*d2 - d1*d6; + if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0)) { + btScalar w = d2 / (d2 - d6); + result.m_closestPointOnSimplex = a + w * ac; + result.m_usedVertices.usedVertexA = true; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(1-w,0,w); + return true; + //return a + w * ac; // barycentric coordinates (1-w,0,w) + } + + // Check if P in edge region of BC, if so return projection of P onto BC + btScalar va = d3*d6 - d5*d4; + if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0)) { + btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); + + result.m_closestPointOnSimplex = b + w * (c - b); + result.m_usedVertices.usedVertexB = true; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(0,1-w,w); + return true; + // return b + w * (c - b); // barycentric coordinates (0,1-w,w) + } + + // P inside face region. Compute Q through its barycentric coordinates (u,v,w) + btScalar denom = btScalar(1.0) / (va + vb + vc); + btScalar v = vb * denom; + btScalar w = vc * denom; + + result.m_closestPointOnSimplex = a + ab * v + ac * w; + result.m_usedVertices.usedVertexA = true; + result.m_usedVertices.usedVertexB = true; + result.m_usedVertices.usedVertexC = true; + result.setBarycentricCoordinates(1-v-w,v,w); + + return true; +// return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w + +} + + + + + +/// Test if point p and d lie on opposite sides of plane through abc +int btVoronoiSimplexSolver::pointOutsideOfPlane(const btPoint3& p, const btPoint3& a, const btPoint3& b, const btPoint3& c, const btPoint3& d) +{ + btVector3 normal = (b-a).cross(c-a); + + btScalar signp = (p - a).dot(normal); // [AP AB AC] + btScalar signd = (d - a).dot( normal); // [AD AB AC] + +#ifdef CATCH_DEGENERATE_TETRAHEDRON +#ifdef BT_USE_DOUBLE_PRECISION +if (signd * signd < (btScalar(1e-8) * btScalar(1e-8))) + { + return -1; + } +#else + if (signd * signd < (btScalar(1e-4) * btScalar(1e-4))) + { +// printf("affine dependent/degenerate\n");// + return -1; + } +#endif + +#endif + // Points on opposite sides if expression signs are opposite + return signp * signd < btScalar(0.); +} + + +bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btPoint3& p, const btPoint3& a, const btPoint3& b, const btPoint3& c, const btPoint3& d, btSubSimplexClosestResult& finalResult) +{ + btSubSimplexClosestResult tempResult; + + // Start out assuming point inside all halfspaces, so closest to itself + finalResult.m_closestPointOnSimplex = p; + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = true; + finalResult.m_usedVertices.usedVertexB = true; + finalResult.m_usedVertices.usedVertexC = true; + finalResult.m_usedVertices.usedVertexD = true; + + int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d); + int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b); + int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c); + int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a); + + if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0) + { + finalResult.m_degenerate = true; + return false; + } + + if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC) + { + return false; + } + + + btScalar bestSqDist = FLT_MAX; + // If point outside face abc then compute closest point on abc + if (pointOutsideABC) + { + closestPtPointTriangle(p, a, b, c,tempResult); + btPoint3 q = tempResult.m_closestPointOnSimplex; + + btScalar sqDist = (q - p).dot( q - p); + // Update best closest point if (squared) distance is less than current best + if (sqDist < bestSqDist) { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + //convert result bitmask! + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; + finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB; + finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC; + finalResult.setBarycentricCoordinates( + tempResult.m_barycentricCoords[VERTA], + tempResult.m_barycentricCoords[VERTB], + tempResult.m_barycentricCoords[VERTC], + 0 + ); + + } + } + + + // Repeat test for face acd + if (pointOutsideACD) + { + closestPtPointTriangle(p, a, c, d,tempResult); + btPoint3 q = tempResult.m_closestPointOnSimplex; + //convert result bitmask! + + btScalar sqDist = (q - p).dot( q - p); + if (sqDist < bestSqDist) + { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; + + finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB; + finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC; + finalResult.setBarycentricCoordinates( + tempResult.m_barycentricCoords[VERTA], + 0, + tempResult.m_barycentricCoords[VERTB], + tempResult.m_barycentricCoords[VERTC] + ); + + } + } + // Repeat test for face adb + + + if (pointOutsideADB) + { + closestPtPointTriangle(p, a, d, b,tempResult); + btPoint3 q = tempResult.m_closestPointOnSimplex; + //convert result bitmask! + + btScalar sqDist = (q - p).dot( q - p); + if (sqDist < bestSqDist) + { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + finalResult.m_usedVertices.reset(); + finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA; + finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC; + + finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB; + finalResult.setBarycentricCoordinates( + tempResult.m_barycentricCoords[VERTA], + tempResult.m_barycentricCoords[VERTC], + 0, + tempResult.m_barycentricCoords[VERTB] + ); + + } + } + // Repeat test for face bdc + + + if (pointOutsideBDC) + { + closestPtPointTriangle(p, b, d, c,tempResult); + btPoint3 q = tempResult.m_closestPointOnSimplex; + //convert result bitmask! + btScalar sqDist = (q - p).dot( q - p); + if (sqDist < bestSqDist) + { + bestSqDist = sqDist; + finalResult.m_closestPointOnSimplex = q; + finalResult.m_usedVertices.reset(); + // + finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA; + finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC; + finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB; + + finalResult.setBarycentricCoordinates( + 0, + tempResult.m_barycentricCoords[VERTA], + tempResult.m_barycentricCoords[VERTC], + tempResult.m_barycentricCoords[VERTB] + ); + + } + } + + //help! we ended up full ! + + if (finalResult.m_usedVertices.usedVertexA && + finalResult.m_usedVertices.usedVertexB && + finalResult.m_usedVertices.usedVertexC && + finalResult.m_usedVertices.usedVertexD) + { + return true; + } + + return true; +} + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h new file mode 100644 index 00000000000..356d335bc93 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h @@ -0,0 +1,157 @@ +/* +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. +*/ + + + +#ifndef btVoronoiSimplexSolver_H +#define btVoronoiSimplexSolver_H + +#include "btSimplexSolverInterface.h" + + + +#define VORONOI_SIMPLEX_MAX_VERTS 5 + +struct btUsageBitfield{ + btUsageBitfield() + { + reset(); + } + + void reset() + { + usedVertexA = false; + usedVertexB = false; + usedVertexC = false; + usedVertexD = false; + } + unsigned short usedVertexA : 1; + unsigned short usedVertexB : 1; + unsigned short usedVertexC : 1; + unsigned short usedVertexD : 1; + unsigned short unused1 : 1; + unsigned short unused2 : 1; + unsigned short unused3 : 1; + unsigned short unused4 : 1; +}; + + +struct btSubSimplexClosestResult +{ + btPoint3 m_closestPointOnSimplex; + //MASK for m_usedVertices + //stores the simplex vertex-usage, using the MASK, + // if m_usedVertices & MASK then the related vertex is used + btUsageBitfield m_usedVertices; + btScalar m_barycentricCoords[4]; + bool m_degenerate; + + void reset() + { + m_degenerate = false; + setBarycentricCoordinates(); + m_usedVertices.reset(); + } + bool isValid() + { + bool valid = (m_barycentricCoords[0] >= btScalar(0.)) && + (m_barycentricCoords[1] >= btScalar(0.)) && + (m_barycentricCoords[2] >= btScalar(0.)) && + (m_barycentricCoords[3] >= btScalar(0.)); + + + return valid; + } + void setBarycentricCoordinates(btScalar a=btScalar(0.),btScalar b=btScalar(0.),btScalar c=btScalar(0.),btScalar d=btScalar(0.)) + { + m_barycentricCoords[0] = a; + m_barycentricCoords[1] = b; + m_barycentricCoords[2] = c; + m_barycentricCoords[3] = d; + } + +}; + +/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin. +/// Can be used with GJK, as an alternative to Johnson distance algorithm. +#ifdef NO_VIRTUAL_INTERFACE +class btVoronoiSimplexSolver +#else +class btVoronoiSimplexSolver : public btSimplexSolverInterface +#endif +{ +public: + + int m_numVertices; + + btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS]; + btPoint3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS]; + btPoint3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS]; + + + + btPoint3 m_cachedP1; + btPoint3 m_cachedP2; + btVector3 m_cachedV; + btVector3 m_lastW; + bool m_cachedValidClosest; + + btSubSimplexClosestResult m_cachedBC; + + bool m_needsUpdate; + + void removeVertex(int index); + void reduceVertices (const btUsageBitfield& usedVerts); + bool updateClosestVectorAndPoints(); + + bool closestPtPointTetrahedron(const btPoint3& p, const btPoint3& a, const btPoint3& b, const btPoint3& c, const btPoint3& d, btSubSimplexClosestResult& finalResult); + int pointOutsideOfPlane(const btPoint3& p, const btPoint3& a, const btPoint3& b, const btPoint3& c, const btPoint3& d); + bool closestPtPointTriangle(const btPoint3& p, const btPoint3& a, const btPoint3& b, const btPoint3& c,btSubSimplexClosestResult& result); + +public: + + void reset(); + + void addVertex(const btVector3& w, const btPoint3& p, const btPoint3& q); + + + bool closest(btVector3& v); + + btScalar maxVertex(); + + bool fullSimplex() const + { + return (m_numVertices == 4); + } + + int getSimplex(btPoint3 *pBuf, btPoint3 *qBuf, btVector3 *yBuf) const; + + bool inSimplex(const btVector3& w); + + void backup_closest(btVector3& v) ; + + bool emptySimplex() const ; + + void compute_points(btPoint3& p1, btPoint3& p2) ; + + int numVertices() const + { + return m_numVertices; + } + + +}; + +#endif //VoronoiSimplexSolver diff --git a/extern/bullet2/src/BulletDynamics/CMakeLists.txt b/extern/bullet2/src/BulletDynamics/CMakeLists.txt new file mode 100644 index 00000000000..8598575799a --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/CMakeLists.txt @@ -0,0 +1,20 @@ +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src } +) + +ADD_LIBRARY(LibBulletDynamics + + ConstraintSolver/btContactConstraint.cpp + ConstraintSolver/btGeneric6DofConstraint.cpp + ConstraintSolver/btHingeConstraint.cpp + ConstraintSolver/btPoint2PointConstraint.cpp + ConstraintSolver/btSequentialImpulseConstraintSolver.cpp + ConstraintSolver/btSolve2LinearConstraint.cpp + ConstraintSolver/btTypedConstraint.cpp + Dynamics/btDiscreteDynamicsWorld.cpp + Dynamics/btSimpleDynamicsWorld.cpp + Dynamics/Bullet-C-API.cpp + Dynamics/btRigidBody.cpp + Vehicle/btRaycastVehicle.cpp + Vehicle/btWheelInfo.cpp +) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp new file mode 100644 index 00000000000..2289621e8e3 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp @@ -0,0 +1,285 @@ +/* +Bullet Continuous Collision Detection and Physics Library +btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios + +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. + +Written by: Marcus Hennix +*/ + + +#include "btConeTwistConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btSimdMinMax.h" +#include + +btConeTwistConstraint::btConeTwistConstraint() +{ +} + + +btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, + const btTransform& rbAFrame,const btTransform& rbBFrame) + :btTypedConstraint(rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), + m_angularOnly(false) +{ + // flip axis for correct angles + m_rbBFrame.getBasis()[1][0] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][1] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); + + m_swingSpan1 = btScalar(1e30); + m_swingSpan2 = btScalar(1e30); + m_twistSpan = btScalar(1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + + m_solveTwistLimit = false; + m_solveSwingLimit = false; + +} + +btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) + :btTypedConstraint(rbA),m_rbAFrame(rbAFrame), + m_angularOnly(false) +{ + m_rbBFrame = m_rbAFrame; + + // flip axis for correct angles + m_rbBFrame.getBasis()[1][0] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][1] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); + + m_rbBFrame.getBasis()[2][0] *= btScalar(-1.); + m_rbBFrame.getBasis()[2][1] *= btScalar(-1.); + m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); + + m_swingSpan1 = btScalar(1e30); + m_swingSpan2 = btScalar(1e30); + m_twistSpan = btScalar(1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + + m_solveTwistLimit = false; + m_solveSwingLimit = false; + +} + +void btConeTwistConstraint::buildJacobian() +{ + m_appliedImpulse = btScalar(0.); + + //set bias, sign, clear accumulator + m_swingCorrection = btScalar(0.); + m_twistLimitSign = btScalar(0.); + m_solveTwistLimit = false; + m_solveSwingLimit = false; + m_accTwistLimitImpulse = btScalar(0.); + m_accSwingLimitImpulse = btScalar(0.); + + if (!m_angularOnly) + { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 relPos = pivotBInW - pivotAInW; + + btVector3 normal[3]; + if (relPos.length2() > SIMD_EPSILON) + { + normal[0] = relPos.normalized(); + } + else + { + normal[0].setValue(btScalar(1.0),0,0); + } + + btPlaneSpace1(normal[0], normal[1], normal[2]); + + for (int i=0;i<3;i++) + { + new (&m_jac[i]) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normal[i], + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + } + } + + btVector3 b1Axis1,b1Axis2,b1Axis3; + btVector3 b2Axis1,b2Axis2; + + b1Axis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(0); + b2Axis1 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(0); + + btScalar swing1=btScalar(0.),swing2 = btScalar(0.); + + // Get Frame into world space + if (m_swingSpan1 >= btScalar(0.05f)) + { + b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1); + swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); + } + + if (m_swingSpan2 >= btScalar(0.05f)) + { + b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2); + swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); + } + + btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1); + btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2); + btScalar EllipseAngle = btFabs(swing1)* RMaxAngle1Sq + btFabs(swing2) * RMaxAngle2Sq; + + if (EllipseAngle > 1.0f) + { + m_swingCorrection = EllipseAngle-1.0f; + m_solveSwingLimit = true; + + // Calculate necessary axis & factors + m_swingAxis = b2Axis1.cross(b1Axis2* b2Axis1.dot(b1Axis2) + b1Axis3* b2Axis1.dot(b1Axis3)); + m_swingAxis.normalize(); + + btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f; + m_swingAxis *= swingAxisSign; + + m_kSwing = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_swingAxis) + + getRigidBodyB().computeAngularImpulseDenominator(m_swingAxis)); + + } + + // Twist limits + if (m_twistSpan >= btScalar(0.)) + { + btVector3 b2Axis2 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(1); + btQuaternion rotationArc = shortestArcQuat(b2Axis1,b1Axis1); + btVector3 TwistRef = quatRotate(rotationArc,b2Axis2); + btScalar twist = btAtan2Fast( TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2) ); + + btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.); + if (twist <= -m_twistSpan*lockedFreeFactor) + { + m_twistCorrection = -(twist + m_twistSpan); + m_solveTwistLimit = true; + + m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; + m_twistAxis.normalize(); + m_twistAxis *= -1.0f; + + m_kTwist = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_twistAxis) + + getRigidBodyB().computeAngularImpulseDenominator(m_twistAxis)); + + } else + if (twist > m_twistSpan*lockedFreeFactor) + { + m_twistCorrection = (twist - m_twistSpan); + m_solveTwistLimit = true; + + m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; + m_twistAxis.normalize(); + + m_kTwist = btScalar(1.) / (getRigidBodyA().computeAngularImpulseDenominator(m_twistAxis) + + getRigidBodyB().computeAngularImpulseDenominator(m_twistAxis)); + + } + } +} + +void btConeTwistConstraint::solveConstraint(btScalar timeStep) +{ + + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + + btScalar tau = btScalar(0.3); + + //linear part + if (!m_angularOnly) + { + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + for (int i=0;i<3;i++) + { + const btVector3& normal = m_jac[i].m_linearJointAxis; + btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); + + btScalar rel_vel; + rel_vel = normal.dot(vel); + //positional error (zeroth order error) + btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal + btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; + m_appliedImpulse += impulse; + btVector3 impulse_vector = normal * impulse; + m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); + m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); + } + } + + { + ///solve angular part + const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); + const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); + + // solve swing limit + if (m_solveSwingLimit) + { + btScalar amplitude = ((angVelB - angVelA).dot( m_swingAxis )*m_relaxationFactor*m_relaxationFactor + m_swingCorrection*(btScalar(1.)/timeStep)*m_biasFactor); + btScalar impulseMag = amplitude * m_kSwing; + + // Clamp the accumulated impulse + btScalar temp = m_accSwingLimitImpulse; + m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, 0.0f ); + impulseMag = m_accSwingLimitImpulse - temp; + + btVector3 impulse = m_swingAxis * impulseMag; + + m_rbA.applyTorqueImpulse(impulse); + m_rbB.applyTorqueImpulse(-impulse); + + } + + // solve twist limit + if (m_solveTwistLimit) + { + btScalar amplitude = ((angVelB - angVelA).dot( m_twistAxis )*m_relaxationFactor*m_relaxationFactor + m_twistCorrection*(btScalar(1.)/timeStep)*m_biasFactor ); + btScalar impulseMag = amplitude * m_kTwist; + + // Clamp the accumulated impulse + btScalar temp = m_accTwistLimitImpulse; + m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, 0.0f ); + impulseMag = m_accTwistLimitImpulse - temp; + + btVector3 impulse = m_twistAxis * impulseMag; + + m_rbA.applyTorqueImpulse(impulse); + m_rbB.applyTorqueImpulse(-impulse); + + } + + } + +} + +void btConeTwistConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h new file mode 100644 index 00000000000..874669c80b3 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -0,0 +1,123 @@ +/* +Bullet Continuous Collision Detection and Physics Library +btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios + +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. + +Written by: Marcus Hennix +*/ + + + +#ifndef CONETWISTCONSTRAINT_H +#define CONETWISTCONSTRAINT_H + +#include "../../LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +class btRigidBody; + + +///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc) +class btConeTwistConstraint : public btTypedConstraint +{ + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + + btTransform m_rbAFrame; + btTransform m_rbBFrame; + + btScalar m_limitSoftness; + btScalar m_biasFactor; + btScalar m_relaxationFactor; + + btScalar m_swingSpan1; + btScalar m_swingSpan2; + btScalar m_twistSpan; + + btVector3 m_swingAxis; + btVector3 m_twistAxis; + + btScalar m_kSwing; + btScalar m_kTwist; + + btScalar m_twistLimitSign; + btScalar m_swingCorrection; + btScalar m_twistCorrection; + + btScalar m_accSwingLimitImpulse; + btScalar m_accTwistLimitImpulse; + + bool m_angularOnly; + bool m_solveTwistLimit; + bool m_solveSwingLimit; + + +public: + + btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame); + + btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame); + + btConeTwistConstraint(); + + virtual void buildJacobian(); + + virtual void solveConstraint(btScalar timeStep); + + void updateRHS(btScalar timeStep); + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + void setAngularOnly(bool angularOnly) + { + m_angularOnly = angularOnly; + } + + void setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 0.8f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) + { + m_swingSpan1 = _swingSpan1; + m_swingSpan2 = _swingSpan2; + m_twistSpan = _twistSpan; + + m_limitSoftness = _softness; + m_biasFactor = _biasFactor; + m_relaxationFactor = _relaxationFactor; + } + + const btTransform& getAFrame() { return m_rbAFrame; }; + const btTransform& getBFrame() { return m_rbBFrame; }; + + inline int getSolveTwistLimit() + { + return m_solveTwistLimit; + } + + inline int getSolveSwingLimit() + { + return m_solveTwistLimit; + } + + inline btScalar getTwistLimitSign() + { + return m_twistLimitSign; + } + +}; + +#endif //CONETWISTCONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h new file mode 100644 index 00000000000..7e8458c2c7b --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h @@ -0,0 +1,45 @@ +/* +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. +*/ + +#ifndef CONSTRAINT_SOLVER_H +#define CONSTRAINT_SOLVER_H + +#include "../../LinearMath/btScalar.h" + +class btPersistentManifold; +class btRigidBody; +class btCollisionObject; +class btTypedConstraint; +struct btContactSolverInfo; +struct btBroadphaseProxy; +class btIDebugDraw; +class btStackAlloc; + +/// btConstraintSolver provides solver interface +class btConstraintSolver +{ + +public: + + virtual ~btConstraintSolver() {} + + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) = 0; + +}; + + + + +#endif //CONSTRAINT_SOLVER_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp new file mode 100644 index 00000000000..bb3fe832592 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp @@ -0,0 +1,417 @@ +/* +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. +*/ + + +#include "btContactConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btContactSolverInfo.h" +#include "LinearMath/btMinMax.h" +#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h" + +#define ASSERT2 assert + +#define USE_INTERNAL_APPLY_IMPULSE 1 + + +//bilateral constraint between two dynamic objects +void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, + btRigidBody& body2, const btVector3& pos2, + btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep) +{ + (void)timeStep; + (void)distance; + + + btScalar normalLenSqr = normal.length2(); + ASSERT2(btFabs(normalLenSqr) < btScalar(1.1)); + if (normalLenSqr > btScalar(1.1)) + { + impulse = btScalar(0.); + return; + } + btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); + //this jacobian entry could be re-used for all iterations + + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + + btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(), + body2.getCenterOfMassTransform().getBasis().transpose(), + rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(), + body2.getInvInertiaDiagLocal(),body2.getInvMass()); + + btScalar jacDiagAB = jac.getDiagonal(); + btScalar jacDiagABInv = btScalar(1.) / jacDiagAB; + + btScalar rel_vel = jac.getRelativeVelocity( + body1.getLinearVelocity(), + body1.getCenterOfMassTransform().getBasis().transpose() * body1.getAngularVelocity(), + body2.getLinearVelocity(), + body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity()); + btScalar a; + a=jacDiagABInv; + + + rel_vel = normal.dot(vel); + + //todo: move this into proper structure + btScalar contactDamping = btScalar(0.2); + +#ifdef ONLY_USE_LINEAR_MASS + btScalar massTerm = btScalar(1.) / (body1.getInvMass() + body2.getInvMass()); + impulse = - contactDamping * rel_vel * massTerm; +#else + btScalar velocityImpulse = -contactDamping * rel_vel * jacDiagABInv; + impulse = velocityImpulse; +#endif +} + + + +//response between two dynamic objects with friction +btScalar resolveSingleCollision( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& solverInfo) +{ + + const btVector3& pos1_ = contactPoint.getPositionWorldOnA(); + const btVector3& pos2_ = contactPoint.getPositionWorldOnB(); + const btVector3& normal = contactPoint.m_normalWorldOnB; + + //constant over all iterations + btVector3 rel_pos1 = pos1_ - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = pos2_ - body2.getCenterOfMassPosition(); + + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + btScalar rel_vel; + rel_vel = normal.dot(vel); + + btScalar Kfps = btScalar(1.) / solverInfo.m_timeStep ; + + // btScalar damping = solverInfo.m_damping ; + btScalar Kerp = solverInfo.m_erp; + btScalar Kcor = Kerp *Kfps; + + btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; + assert(cpd); + btScalar distance = cpd->m_penetration; + btScalar positionalError = Kcor *-distance; + btScalar velocityError = cpd->m_restitution - rel_vel;// * damping; + + btScalar penetrationImpulse = positionalError * cpd->m_jacDiagABInv; + + btScalar velocityImpulse = velocityError * cpd->m_jacDiagABInv; + + btScalar normalImpulse = penetrationImpulse+velocityImpulse; + + // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse + btScalar oldNormalImpulse = cpd->m_appliedImpulse; + btScalar sum = oldNormalImpulse + normalImpulse; + cpd->m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; + + normalImpulse = cpd->m_appliedImpulse - oldNormalImpulse; + +#ifdef USE_INTERNAL_APPLY_IMPULSE + if (body1.getInvMass()) + { + body1.internalApplyImpulse(contactPoint.m_normalWorldOnB*body1.getInvMass(),cpd->m_angularComponentA,normalImpulse); + } + if (body2.getInvMass()) + { + body2.internalApplyImpulse(contactPoint.m_normalWorldOnB*body2.getInvMass(),cpd->m_angularComponentB,-normalImpulse); + } +#else //USE_INTERNAL_APPLY_IMPULSE + body1.applyImpulse(normal*(normalImpulse), rel_pos1); + body2.applyImpulse(-normal*(normalImpulse), rel_pos2); +#endif //USE_INTERNAL_APPLY_IMPULSE + + return normalImpulse; +} + + +btScalar resolveSingleFriction( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& solverInfo) +{ + + (void)solverInfo; + + const btVector3& pos1 = contactPoint.getPositionWorldOnA(); + const btVector3& pos2 = contactPoint.getPositionWorldOnB(); + + btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); + + btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; + assert(cpd); + + btScalar combinedFriction = cpd->m_friction; + + btScalar limit = cpd->m_appliedImpulse * combinedFriction; + + if (cpd->m_appliedImpulse>btScalar(0.)) + //friction + { + //apply friction in the 2 tangential directions + + // 1st tangent + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar j1,j2; + + { + + btScalar vrel = cpd->m_frictionWorldTangential0.dot(vel); + + // calculate j that moves us to zero relative velocity + j1 = -vrel * cpd->m_jacDiagABInvTangent0; + btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse0; + cpd->m_accumulatedTangentImpulse0 = oldTangentImpulse + j1; + GEN_set_min(cpd->m_accumulatedTangentImpulse0, limit); + GEN_set_max(cpd->m_accumulatedTangentImpulse0, -limit); + j1 = cpd->m_accumulatedTangentImpulse0 - oldTangentImpulse; + + } + { + // 2nd tangent + + btScalar vrel = cpd->m_frictionWorldTangential1.dot(vel); + + // calculate j that moves us to zero relative velocity + j2 = -vrel * cpd->m_jacDiagABInvTangent1; + btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse1; + cpd->m_accumulatedTangentImpulse1 = oldTangentImpulse + j2; + GEN_set_min(cpd->m_accumulatedTangentImpulse1, limit); + GEN_set_max(cpd->m_accumulatedTangentImpulse1, -limit); + j2 = cpd->m_accumulatedTangentImpulse1 - oldTangentImpulse; + } + +#ifdef USE_INTERNAL_APPLY_IMPULSE + if (body1.getInvMass()) + { + body1.internalApplyImpulse(cpd->m_frictionWorldTangential0*body1.getInvMass(),cpd->m_frictionAngularComponent0A,j1); + body1.internalApplyImpulse(cpd->m_frictionWorldTangential1*body1.getInvMass(),cpd->m_frictionAngularComponent1A,j2); + } + if (body2.getInvMass()) + { + body2.internalApplyImpulse(cpd->m_frictionWorldTangential0*body2.getInvMass(),cpd->m_frictionAngularComponent0B,-j1); + body2.internalApplyImpulse(cpd->m_frictionWorldTangential1*body2.getInvMass(),cpd->m_frictionAngularComponent1B,-j2); + } +#else //USE_INTERNAL_APPLY_IMPULSE + body1.applyImpulse((j1 * cpd->m_frictionWorldTangential0)+(j2 * cpd->m_frictionWorldTangential1), rel_pos1); + body2.applyImpulse((j1 * -cpd->m_frictionWorldTangential0)+(j2 * -cpd->m_frictionWorldTangential1), rel_pos2); +#endif //USE_INTERNAL_APPLY_IMPULSE + + + } + return cpd->m_appliedImpulse; +} + + +btScalar resolveSingleFrictionOriginal( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& solverInfo) +{ + + (void)solverInfo; + + const btVector3& pos1 = contactPoint.getPositionWorldOnA(); + const btVector3& pos2 = contactPoint.getPositionWorldOnB(); + + btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); + + btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; + assert(cpd); + + btScalar combinedFriction = cpd->m_friction; + + btScalar limit = cpd->m_appliedImpulse * combinedFriction; + //if (contactPoint.m_appliedImpulse>btScalar(0.)) + //friction + { + //apply friction in the 2 tangential directions + + { + // 1st tangent + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar vrel = cpd->m_frictionWorldTangential0.dot(vel); + + // calculate j that moves us to zero relative velocity + btScalar j = -vrel * cpd->m_jacDiagABInvTangent0; + btScalar total = cpd->m_accumulatedTangentImpulse0 + j; + GEN_set_min(total, limit); + GEN_set_max(total, -limit); + j = total - cpd->m_accumulatedTangentImpulse0; + cpd->m_accumulatedTangentImpulse0 = total; + body1.applyImpulse(j * cpd->m_frictionWorldTangential0, rel_pos1); + body2.applyImpulse(j * -cpd->m_frictionWorldTangential0, rel_pos2); + } + + + { + // 2nd tangent + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar vrel = cpd->m_frictionWorldTangential1.dot(vel); + + // calculate j that moves us to zero relative velocity + btScalar j = -vrel * cpd->m_jacDiagABInvTangent1; + btScalar total = cpd->m_accumulatedTangentImpulse1 + j; + GEN_set_min(total, limit); + GEN_set_max(total, -limit); + j = total - cpd->m_accumulatedTangentImpulse1; + cpd->m_accumulatedTangentImpulse1 = total; + body1.applyImpulse(j * cpd->m_frictionWorldTangential1, rel_pos1); + body2.applyImpulse(j * -cpd->m_frictionWorldTangential1, rel_pos2); + } + } + return cpd->m_appliedImpulse; +} + + +//velocity + friction +//response between two dynamic objects with friction +btScalar resolveSingleCollisionCombined( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& solverInfo) +{ + + const btVector3& pos1 = contactPoint.getPositionWorldOnA(); + const btVector3& pos2 = contactPoint.getPositionWorldOnB(); + const btVector3& normal = contactPoint.m_normalWorldOnB; + + btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition(); + + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + btScalar rel_vel; + rel_vel = normal.dot(vel); + + btScalar Kfps = btScalar(1.) / solverInfo.m_timeStep ; + + //btScalar damping = solverInfo.m_damping ; + btScalar Kerp = solverInfo.m_erp; + btScalar Kcor = Kerp *Kfps; + + btConstraintPersistentData* cpd = (btConstraintPersistentData*) contactPoint.m_userPersistentData; + assert(cpd); + btScalar distance = cpd->m_penetration; + btScalar positionalError = Kcor *-distance; + btScalar velocityError = cpd->m_restitution - rel_vel;// * damping; + + btScalar penetrationImpulse = positionalError * cpd->m_jacDiagABInv; + + btScalar velocityImpulse = velocityError * cpd->m_jacDiagABInv; + + btScalar normalImpulse = penetrationImpulse+velocityImpulse; + + // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse + btScalar oldNormalImpulse = cpd->m_appliedImpulse; + btScalar sum = oldNormalImpulse + normalImpulse; + cpd->m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; + + normalImpulse = cpd->m_appliedImpulse - oldNormalImpulse; + + +#ifdef USE_INTERNAL_APPLY_IMPULSE + if (body1.getInvMass()) + { + body1.internalApplyImpulse(contactPoint.m_normalWorldOnB*body1.getInvMass(),cpd->m_angularComponentA,normalImpulse); + } + if (body2.getInvMass()) + { + body2.internalApplyImpulse(contactPoint.m_normalWorldOnB*body2.getInvMass(),cpd->m_angularComponentB,-normalImpulse); + } +#else //USE_INTERNAL_APPLY_IMPULSE + body1.applyImpulse(normal*(normalImpulse), rel_pos1); + body2.applyImpulse(-normal*(normalImpulse), rel_pos2); +#endif //USE_INTERNAL_APPLY_IMPULSE + + { + //friction + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + rel_vel = normal.dot(vel); + + + btVector3 lat_vel = vel - normal * rel_vel; + btScalar lat_rel_vel = lat_vel.length(); + + btScalar combinedFriction = cpd->m_friction; + + if (cpd->m_appliedImpulse > 0) + if (lat_rel_vel > SIMD_EPSILON) + { + lat_vel /= lat_rel_vel; + btVector3 temp1 = body1.getInvInertiaTensorWorld() * rel_pos1.cross(lat_vel); + btVector3 temp2 = body2.getInvInertiaTensorWorld() * rel_pos2.cross(lat_vel); + btScalar friction_impulse = lat_rel_vel / + (body1.getInvMass() + body2.getInvMass() + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); + btScalar normal_impulse = cpd->m_appliedImpulse * combinedFriction; + + GEN_set_min(friction_impulse, normal_impulse); + GEN_set_max(friction_impulse, -normal_impulse); + body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1); + body2.applyImpulse(lat_vel * friction_impulse, rel_pos2); + } + } + + + + return normalImpulse; +} + +btScalar resolveSingleFrictionEmpty( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& solverInfo) +{ + (void)contactPoint; + (void)body1; + (void)body2; + (void)solverInfo; + + + return btScalar(0.); +}; + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h new file mode 100644 index 00000000000..0834deddeac --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h @@ -0,0 +1,122 @@ +/* +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. +*/ + +#ifndef CONTACT_CONSTRAINT_H +#define CONTACT_CONSTRAINT_H + +//todo: make into a proper class working with the iterative constraint solver + +class btRigidBody; +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btScalar.h" +struct btContactSolverInfo; +class btManifoldPoint; + +enum { + DEFAULT_CONTACT_SOLVER_TYPE=0, + CONTACT_SOLVER_TYPE1, + CONTACT_SOLVER_TYPE2, + USER_CONTACT_SOLVER_TYPE1, + MAX_CONTACT_SOLVER_TYPES +}; + + +typedef btScalar (*ContactSolverFunc)(btRigidBody& body1, + btRigidBody& body2, + class btManifoldPoint& contactPoint, + const btContactSolverInfo& info); + +///stores some extra information to each contact point. It is not in the contact point, because that want to keep the collision detection independent from the constraint solver. +struct btConstraintPersistentData +{ + inline btConstraintPersistentData() + :m_appliedImpulse(btScalar(0.)), + m_prevAppliedImpulse(btScalar(0.)), + m_accumulatedTangentImpulse0(btScalar(0.)), + m_accumulatedTangentImpulse1(btScalar(0.)), + m_jacDiagABInv(btScalar(0.)), + m_persistentLifeTime(0), + m_restitution(btScalar(0.)), + m_friction(btScalar(0.)), + m_penetration(btScalar(0.)), + m_contactSolverFunc(0), + m_frictionSolverFunc(0) + { + } + + + /// total applied impulse during most recent frame + btScalar m_appliedImpulse; + btScalar m_prevAppliedImpulse; + btScalar m_accumulatedTangentImpulse0; + btScalar m_accumulatedTangentImpulse1; + + btScalar m_jacDiagABInv; + btScalar m_jacDiagABInvTangent0; + btScalar m_jacDiagABInvTangent1; + int m_persistentLifeTime; + btScalar m_restitution; + btScalar m_friction; + btScalar m_penetration; + btVector3 m_frictionWorldTangential0; + btVector3 m_frictionWorldTangential1; + + btVector3 m_frictionAngularComponent0A; + btVector3 m_frictionAngularComponent0B; + btVector3 m_frictionAngularComponent1A; + btVector3 m_frictionAngularComponent1B; + + //some data doesn't need to be persistent over frames: todo: clean/reuse this + btVector3 m_angularComponentA; + btVector3 m_angularComponentB; + + ContactSolverFunc m_contactSolverFunc; + ContactSolverFunc m_frictionSolverFunc; + +}; + +///bilateral constraint between two dynamic objects +///positive distance = separation, negative distance = penetration +void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1, + btRigidBody& body2, const btVector3& pos2, + btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep); + + +///contact constraint resolution: +///calculate and apply impulse to satisfy non-penetration and non-negative relative velocity constraint +///positive distance = separation, negative distance = penetration +btScalar resolveSingleCollision( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& info); + +btScalar resolveSingleFriction( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& solverInfo + ); + + + +btScalar resolveSingleCollisionCombined( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& solverInfo + ); + +#endif //CONTACT_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h new file mode 100644 index 00000000000..c3c73e300f4 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -0,0 +1,47 @@ +/* +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. +*/ + +#ifndef CONTACT_SOLVER_INFO +#define CONTACT_SOLVER_INFO + + +struct btContactSolverInfo +{ + + inline btContactSolverInfo() + { + m_tau = btScalar(0.6); + m_damping = btScalar(1.0); + m_friction = btScalar(0.3); + m_restitution = btScalar(0.); + m_maxErrorReduction = btScalar(20.); + m_numIterations = 10; + m_erp = btScalar(0.4); + m_sor = btScalar(1.3); + } + + btScalar m_tau; + btScalar m_damping; + btScalar m_friction; + btScalar m_timeStep; + btScalar m_restitution; + int m_numIterations; + btScalar m_maxErrorReduction; + btScalar m_sor; + btScalar m_erp; + +}; + +#endif //CONTACT_SOLVER_INFO diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp new file mode 100644 index 00000000000..747d10d1f8b --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp @@ -0,0 +1,389 @@ +/* +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. +*/ + + +#include "btGeneric6DofConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include + +static const btScalar kSign[] = { btScalar(1.0), btScalar(-1.0), btScalar(1.0) }; +static const int kAxisA[] = { 1, 0, 0 }; +static const int kAxisB[] = { 2, 2, 1 }; +#define GENERIC_D6_DISABLE_WARMSTARTING 1 + +btGeneric6DofConstraint::btGeneric6DofConstraint() +{ +} + +btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB) +: btTypedConstraint(rbA, rbB) +, m_frameInA(frameInA) +, m_frameInB(frameInB) +{ + //free means upper < lower, + //locked means upper == lower + //limited means upper > lower + //so start all locked + for (int i=0; i<6;++i) + { + m_lowerLimit[i] = btScalar(0.0); + m_upperLimit[i] = btScalar(0.0); + m_accumulatedImpulse[i] = btScalar(0.0); + } + +} + + +void btGeneric6DofConstraint::buildJacobian() +{ + btVector3 localNormalInA(0,0,0); + + const btVector3& pivotInA = m_frameInA.getOrigin(); + const btVector3& pivotInB = m_frameInB.getOrigin(); + + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_frameInA.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_frameInB.getOrigin(); + + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + int i; + //linear part + for (i=0;i<3;i++) + { + if (isLimited(i)) + { + localNormalInA[i] = 1; + btVector3 normalWorld = m_rbA.getCenterOfMassTransform().getBasis() * localNormalInA; + + + // Create linear atom + new (&m_jacLinear[i]) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getCenterOfMassTransform()*pivotInA - m_rbA.getCenterOfMassPosition(), + m_rbB.getCenterOfMassTransform()*pivotInB - m_rbB.getCenterOfMassPosition(), + normalWorld, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + + //optionally disable warmstarting +#ifdef GENERIC_D6_DISABLE_WARMSTARTING + m_accumulatedImpulse[i] = btScalar(0.); +#endif //GENERIC_D6_DISABLE_WARMSTARTING + + // Apply accumulated impulse + btVector3 impulse_vector = m_accumulatedImpulse[i] * normalWorld; + + m_rbA.applyImpulse( impulse_vector, rel_pos1); + m_rbB.applyImpulse(-impulse_vector, rel_pos2); + + localNormalInA[i] = 0; + } + } + + // angular part + for (i=0;i<3;i++) + { + if (isLimited(i+3)) + { + btVector3 axisA = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn( kAxisA[i] ); + btVector3 axisB = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn( kAxisB[i] ); + + // Dirk: This is IMO mathematically the correct way, but we should consider axisA and axisB being near parallel maybe + btVector3 axis = kSign[i] * axisA.cross(axisB); + + // Create angular atom + new (&m_jacAng[i]) btJacobianEntry(axis, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + +#ifdef GENERIC_D6_DISABLE_WARMSTARTING + m_accumulatedImpulse[i + 3] = btScalar(0.); +#endif //GENERIC_D6_DISABLE_WARMSTARTING + + // Apply accumulated impulse + btVector3 impulse_vector = m_accumulatedImpulse[i + 3] * axis; + + m_rbA.applyTorqueImpulse( impulse_vector); + m_rbB.applyTorqueImpulse(-impulse_vector); + } + } +} + +btScalar getMatrixElem(const btMatrix3x3& mat,int index) +{ + int row = index%3; + int col = index / 3; + return mat[row][col]; +} + +///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html +bool MatrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) +{ + // rot = cy*cz -cy*sz sy + // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx + // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy + +/// 0..8 + + if (getMatrixElem(mat,2) < btScalar(1.0)) + { + if (getMatrixElem(mat,2) > btScalar(-1.0)) + { + xyz[0] = btAtan2(-getMatrixElem(mat,5),getMatrixElem(mat,8)); + xyz[1] = btAsin(getMatrixElem(mat,2)); + xyz[2] = btAtan2(-getMatrixElem(mat,1),getMatrixElem(mat,0)); + return true; + } + else + { + // WARNING. Not unique. XA - ZA = -atan2(r10,r11) + xyz[0] = -btAtan2(getMatrixElem(mat,3),getMatrixElem(mat,4)); + xyz[1] = -SIMD_HALF_PI; + xyz[2] = btScalar(0.0); + return false; + } + } + else + { + // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) + xyz[0] = btAtan2(getMatrixElem(mat,3),getMatrixElem(mat,4)); + xyz[1] = SIMD_HALF_PI; + xyz[2] = 0.0; + + } + + return false; +} + + +void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) +{ + btScalar tau = btScalar(0.1); + btScalar damping = btScalar(1.0); + + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_frameInA.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_frameInB.getOrigin(); + + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 localNormalInA(0,0,0); + int i; + + // linear + for (i=0;i<3;i++) + { + if (isLimited(i)) + { + btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); + btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); + + localNormalInA.setValue(0,0,0); + localNormalInA[i] = 1; + btVector3 normalWorld = m_rbA.getCenterOfMassTransform().getBasis() * localNormalInA; + + btScalar jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); + + //velocity error (first order error) + btScalar rel_vel = m_jacLinear[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, + m_rbB.getLinearVelocity(),angvelB); + + //positional error (zeroth order error) + btScalar depth = -(pivotAInW - pivotBInW).dot(normalWorld); + btScalar lo = btScalar(-1e30); + btScalar hi = btScalar(1e30); + + //handle the limits + if (m_lowerLimit[i] < m_upperLimit[i]) + { + { + if (depth > m_upperLimit[i]) + { + depth -= m_upperLimit[i]; + lo = btScalar(0.); + + } else + { + if (depth < m_lowerLimit[i]) + { + depth -= m_lowerLimit[i]; + hi = btScalar(0.); + } else + { + continue; + } + } + } + } + + btScalar normalImpulse= (tau*depth/timeStep - damping*rel_vel) * jacDiagABInv; + btScalar oldNormalImpulse = m_accumulatedImpulse[i]; + btScalar sum = oldNormalImpulse + normalImpulse; + m_accumulatedImpulse[i] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + normalImpulse = m_accumulatedImpulse[i] - oldNormalImpulse; + + btVector3 impulse_vector = normalWorld * normalImpulse; + m_rbA.applyImpulse( impulse_vector, rel_pos1); + m_rbB.applyImpulse(-impulse_vector, rel_pos2); + + localNormalInA[i] = 0; + } + } + + btVector3 axis; + btScalar angle; + btTransform frameAWorld = m_rbA.getCenterOfMassTransform() * m_frameInA; + btTransform frameBWorld = m_rbB.getCenterOfMassTransform() * m_frameInB; + + btTransformUtil::calculateDiffAxisAngle(frameAWorld,frameBWorld,axis,angle); + btQuaternion diff(axis,angle); + btMatrix3x3 diffMat (diff); + btVector3 xyz; + ///this is not perfect, we can first check which axis are limited, and choose a more appropriate order + MatrixToEulerXYZ(diffMat,xyz); + + // angular + for (i=0;i<3;i++) + { + if (isLimited(i+3)) + { + btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); + btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); + + btScalar jacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); + + //velocity error (first order error) + btScalar rel_vel = m_jacAng[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, + m_rbB.getLinearVelocity(),angvelB); + + //positional error (zeroth order error) + btVector3 axisA = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn( kAxisA[i] ); + btVector3 axisB = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn( kAxisB[i] ); + + btScalar rel_pos = kSign[i] * axisA.dot(axisB); + + btScalar lo = btScalar(-1e30); + btScalar hi = btScalar(1e30); + + //handle the twist limit + if (m_lowerLimit[i+3] < m_upperLimit[i+3]) + { + //clamp the values + btScalar loLimit = m_lowerLimit[i+3] > -3.1415 ? m_lowerLimit[i+3] : btScalar(-1e30); + btScalar hiLimit = m_upperLimit[i+3] < 3.1415 ? m_upperLimit[i+3] : btScalar(1e30); + + btScalar projAngle = btScalar(-1.)*xyz[i]; + + if (projAngle < loLimit) + { + hi = btScalar(0.); + rel_pos = (loLimit - projAngle); + } else + { + if (projAngle > hiLimit) + { + lo = btScalar(0.); + rel_pos = (hiLimit - projAngle); + } else + { + continue; + } + } + } + + //impulse + + btScalar normalImpulse= -(tau*rel_pos/timeStep + damping*rel_vel) * jacDiagABInv; + btScalar oldNormalImpulse = m_accumulatedImpulse[i+3]; + btScalar sum = oldNormalImpulse + normalImpulse; + m_accumulatedImpulse[i+3] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + normalImpulse = m_accumulatedImpulse[i+3] - oldNormalImpulse; + + // Dirk: Not needed - we could actually project onto Jacobian entry here (same as above) + btVector3 axis = kSign[i] * axisA.cross(axisB); + btVector3 impulse_vector = axis * normalImpulse; + + m_rbA.applyTorqueImpulse( impulse_vector); + m_rbB.applyTorqueImpulse(-impulse_vector); + } + } +} + +void btGeneric6DofConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + +btScalar btGeneric6DofConstraint::computeAngle(int axis) const + { + btScalar angle = btScalar(0.f); + + switch (axis) + { + case 0: + { + btVector3 v1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(1); + btVector3 v2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(1); + btVector3 w2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(2); + + btScalar s = v1.dot(w2); + btScalar c = v1.dot(v2); + + angle = btAtan2( s, c ); + } + break; + + case 1: + { + btVector3 w1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(2); + btVector3 w2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(2); + btVector3 u2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(0); + + btScalar s = w1.dot(u2); + btScalar c = w1.dot(w2); + + angle = btAtan2( s, c ); + } + break; + + case 2: + { + btVector3 u1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(0); + btVector3 u2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(0); + btVector3 v2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(1); + + btScalar s = u1.dot(v2); + btScalar c = u1.dot(u2); + + angle = btAtan2( s, c ); + } + break; + default: + btAssert ( 0 ) ; + + break ; + } + + return angle; + } + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h new file mode 100644 index 00000000000..b114e54fa69 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h @@ -0,0 +1,120 @@ +/* +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. +*/ + +#ifndef GENERIC_6DOF_CONSTRAINT_H +#define GENERIC_6DOF_CONSTRAINT_H + +#include "../../LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +class btRigidBody; + + + +/// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space +/// btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked' +/// Work in progress (is still a Hinge actually) +class btGeneric6DofConstraint : public btTypedConstraint +{ + btJacobianEntry m_jacLinear[3]; // 3 orthogonal linear constraints + btJacobianEntry m_jacAng[3]; // 3 orthogonal angular constraints + + btTransform m_frameInA; // the constraint space w.r.t body A + btTransform m_frameInB; // the constraint space w.r.t body B + + btScalar m_lowerLimit[6]; // the constraint lower limits + btScalar m_upperLimit[6]; // the constraint upper limits + + btScalar m_accumulatedImpulse[6]; + + btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) + { + btAssert(0); + (void) other; + return *this; + } + +public: + btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ); + + btGeneric6DofConstraint(); + + + virtual void buildJacobian(); + + virtual void solveConstraint(btScalar timeStep); + + void updateRHS(btScalar timeStep); + + btScalar computeAngle(int axis) const; + + void setLinearLowerLimit(const btVector3& linearLower) + { + m_lowerLimit[0] = linearLower.getX(); + m_lowerLimit[1] = linearLower.getY(); + m_lowerLimit[2] = linearLower.getZ(); + } + + void setLinearUpperLimit(const btVector3& linearUpper) + { + m_upperLimit[0] = linearUpper.getX(); + m_upperLimit[1] = linearUpper.getY(); + m_upperLimit[2] = linearUpper.getZ(); + } + + void setAngularLowerLimit(const btVector3& angularLower) + { + m_lowerLimit[3] = angularLower.getX(); + m_lowerLimit[4] = angularLower.getY(); + m_lowerLimit[5] = angularLower.getZ(); + } + + void setAngularUpperLimit(const btVector3& angularUpper) + { + m_upperLimit[3] = angularUpper.getX(); + m_upperLimit[4] = angularUpper.getY(); + m_upperLimit[5] = angularUpper.getZ(); + } + + //first 3 are linear, next 3 are angular + void SetLimit(int axis, btScalar lo, btScalar hi) + { + m_lowerLimit[axis] = lo; + m_upperLimit[axis] = hi; + } + + //free means upper < lower, + //locked means upper == lower + //limited means upper > lower + //limitIndex: first 3 are linear, next 3 are angular + bool isLimited(int limitIndex) + { + return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); + } + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + +}; + +#endif //GENERIC_6DOF_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp new file mode 100644 index 00000000000..27e30987549 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -0,0 +1,229 @@ +/* +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. +*/ + + +#include "btHingeConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include + +btHingeConstraint::btHingeConstraint(): +m_enableAngularMotor(false) +{ +} + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, + btVector3& axisInA,btVector3& axisInB) +:btTypedConstraint(rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB), +m_axisInA(axisInA), +m_axisInB(-axisInB), +m_angularOnly(false), +m_enableAngularMotor(false) +{ + +} + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA) +:btTypedConstraint(rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), +m_axisInA(axisInA), +//fixed axis in worldspace +m_axisInB(rbA.getCenterOfMassTransform().getBasis() * -axisInA), +m_angularOnly(false), +m_enableAngularMotor(false) +{ + +} + +void btHingeConstraint::buildJacobian() +{ + m_appliedImpulse = btScalar(0.); + + btVector3 normal(0,0,0); + + if (!m_angularOnly) + { + for (int i=0;i<3;i++) + { + normal[i] = 1; + new (&m_jac[i]) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(), + m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(), + normal, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + normal[i] = 0; + } + } + + //calculate two perpendicular jointAxis, orthogonal to hingeAxis + //these two jointAxis require equal angular velocities for both bodies + + //this is unused for now, it's a todo + btVector3 jointAxis0local; + btVector3 jointAxis1local; + + btPlaneSpace1(m_axisInA,jointAxis0local,jointAxis1local); + + getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; + btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local; + btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local; + btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; + + new (&m_jacAng[0]) btJacobianEntry(jointAxis0, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + + new (&m_jacAng[1]) btJacobianEntry(jointAxis1, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + + new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + + + +} + +void btHingeConstraint::solveConstraint(btScalar timeStep) +{ + + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB; + + btVector3 normal(0,0,0); + btScalar tau = btScalar(0.3); + btScalar damping = btScalar(1.); + +//linear part + if (!m_angularOnly) + { + for (int i=0;i<3;i++) + { + normal[i] = 1; + btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); + + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + btScalar rel_vel; + rel_vel = normal.dot(vel); + //positional error (zeroth order error) + btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal + btScalar impulse = depth*tau/timeStep * jacDiagABInv - damping * rel_vel * jacDiagABInv * damping; + m_appliedImpulse += impulse; + btVector3 impulse_vector = normal * impulse; + m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); + m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); + + normal[i] = 0; + } + } + + + { + ///solve angular part + + // get axes in world space + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; + btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_axisInB; + + const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); + const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); + + btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA); + btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB); + + btVector3 angAorthog = angVelA - angVelAroundHingeAxisA; + btVector3 angBorthog = angVelB - angVelAroundHingeAxisB; + btVector3 velrelOrthog = angAorthog-angBorthog; + { + //solve orthogonal angular velocity correction + btScalar relaxation = btScalar(1.); + btScalar len = velrelOrthog.length(); + if (len > btScalar(0.00001)) + { + btVector3 normal = velrelOrthog.normalized(); + btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) + + getRigidBodyB().computeAngularImpulseDenominator(normal); + // scale for mass and relaxation + //todo: expose this 0.9 factor to developer + velrelOrthog *= (btScalar(1.)/denom) * btScalar(0.9); + } + + //solve angular positional correction + btVector3 angularError = -axisA.cross(axisB) *(btScalar(1.)/timeStep); + btScalar len2 = angularError.length(); + if (len2>btScalar(0.00001)) + { + btVector3 normal2 = angularError.normalized(); + btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) + + getRigidBodyB().computeAngularImpulseDenominator(normal2); + angularError *= (btScalar(1.)/denom2) * relaxation; + } + + m_rbA.applyTorqueImpulse(-velrelOrthog+angularError); + m_rbB.applyTorqueImpulse(velrelOrthog-angularError); + } + + //apply motor + if (m_enableAngularMotor) + { + //todo: add limits too + btVector3 angularLimit(0,0,0); + + btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB; + btScalar projRelVel = velrel.dot(axisA); + + btScalar desiredMotorVel = m_motorTargetVelocity; + btScalar motor_relvel = desiredMotorVel - projRelVel; + + btScalar denom3 = getRigidBodyA().computeAngularImpulseDenominator(axisA) + + getRigidBodyB().computeAngularImpulseDenominator(axisA); + + btScalar unclippedMotorImpulse = (btScalar(1.)/denom3) * motor_relvel;; + //todo: should clip against accumulated impulse + btScalar clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse; + clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse; + btVector3 motorImp = clippedMotorImpulse * axisA; + + m_rbA.applyTorqueImpulse(motorImp+angularLimit); + m_rbB.applyTorqueImpulse(-motorImp-angularLimit); + + } + } + +} + +void btHingeConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h new file mode 100644 index 00000000000..5c1ceafbc5b --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -0,0 +1,81 @@ +/* +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. +*/ + +#ifndef HINGECONSTRAINT_H +#define HINGECONSTRAINT_H + +#include "../../LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +class btRigidBody; + + +/// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space +/// axis defines the orientation of the hinge axis +class btHingeConstraint : public btTypedConstraint +{ + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor + + btVector3 m_pivotInA; + btVector3 m_pivotInB; + btVector3 m_axisInA; + btVector3 m_axisInB; + + bool m_angularOnly; + + btScalar m_motorTargetVelocity; + btScalar m_maxMotorImpulse; + bool m_enableAngularMotor; + +public: + + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,btVector3& axisInA,btVector3& axisInB); + + btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA); + + btHingeConstraint(); + + virtual void buildJacobian(); + + virtual void solveConstraint(btScalar timeStep); + + void updateRHS(btScalar timeStep); + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + void setAngularOnly(bool angularOnly) + { + m_angularOnly = angularOnly; + } + + void enableAngularMotor(bool enableMotor,btScalar targetVelocity,btScalar maxMotorImpulse) + { + m_enableAngularMotor = enableMotor; + m_motorTargetVelocity = targetVelocity; + m_maxMotorImpulse = maxMotorImpulse; + } + +}; + +#endif //HINGECONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h new file mode 100644 index 00000000000..aae3ed0373f --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h @@ -0,0 +1,156 @@ +/* +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. +*/ + +#ifndef JACOBIAN_ENTRY_H +#define JACOBIAN_ENTRY_H + +#include "../../LinearMath/btVector3.h" +#include "../Dynamics/btRigidBody.h" + + +//notes: +// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components +// which makes the btJacobianEntry memory layout 16 bytes +// if you only are interested in angular part, just feed massInvA and massInvB zero + +/// Jacobian entry is an abstraction that allows to describe constraints +/// it can be used in combination with a constraint solver +/// Can be used to relate the effect of an impulse to the constraint error +class btJacobianEntry +{ +public: + btJacobianEntry() {}; + //constraint between two different rigidbodies + btJacobianEntry( + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + const btVector3& rel_pos1,const btVector3& rel_pos2, + const btVector3& jointAxis, + const btVector3& inertiaInvA, + const btScalar massInvA, + const btVector3& inertiaInvB, + const btScalar massInvB) + :m_linearJointAxis(jointAxis) + { + m_aJ = world2A*(rel_pos1.cross(m_linearJointAxis)); + m_bJ = world2B*(rel_pos2.cross(-m_linearJointAxis)); + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + //angular constraint between two different rigidbodies + btJacobianEntry(const btVector3& jointAxis, + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + const btVector3& inertiaInvA, + const btVector3& inertiaInvB) + :m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.))) + { + m_aJ= world2A*jointAxis; + m_bJ = world2B*-jointAxis; + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + //angular constraint between two different rigidbodies + btJacobianEntry(const btVector3& axisInA, + const btVector3& axisInB, + const btVector3& inertiaInvA, + const btVector3& inertiaInvB) + : m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.))) + , m_aJ(axisInA) + , m_bJ(-axisInB) + { + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + //constraint on one rigidbody + btJacobianEntry( + const btMatrix3x3& world2A, + const btVector3& rel_pos1,const btVector3& rel_pos2, + const btVector3& jointAxis, + const btVector3& inertiaInvA, + const btScalar massInvA) + :m_linearJointAxis(jointAxis) + { + m_aJ= world2A*(rel_pos1.cross(jointAxis)); + m_bJ = world2A*(rel_pos2.cross(-jointAxis)); + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = btVector3(btScalar(0.),btScalar(0.),btScalar(0.)); + m_Adiag = massInvA + m_0MinvJt.dot(m_aJ); + + btAssert(m_Adiag > btScalar(0.0)); + } + + btScalar getDiagonal() const { return m_Adiag; } + + // for two constraints on the same rigidbody (for example vehicle friction) + btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const + { + const btJacobianEntry& jacA = *this; + btScalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis); + btScalar ang = jacA.m_0MinvJt.dot(jacB.m_aJ); + return lin + ang; + } + + + + // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies) + btScalar getNonDiagonal(const btJacobianEntry& jacB,const btScalar massInvA,const btScalar massInvB) const + { + const btJacobianEntry& jacA = *this; + btVector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis; + btVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ; + btVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ; + btVector3 lin0 = massInvA * lin ; + btVector3 lin1 = massInvB * lin; + btVector3 sum = ang0+ang1+lin0+lin1; + return sum[0]+sum[1]+sum[2]; + } + + btScalar getRelativeVelocity(const btVector3& linvelA,const btVector3& angvelA,const btVector3& linvelB,const btVector3& angvelB) + { + btVector3 linrel = linvelA - linvelB; + btVector3 angvela = angvelA * m_aJ; + btVector3 angvelb = angvelB * m_bJ; + linrel *= m_linearJointAxis; + angvela += angvelb; + angvela += linrel; + btScalar rel_vel2 = angvela[0]+angvela[1]+angvela[2]; + return rel_vel2 + SIMD_EPSILON; + } +//private: + + btVector3 m_linearJointAxis; + btVector3 m_aJ; + btVector3 m_bJ; + btVector3 m_0MinvJt; + btVector3 m_1MinvJt; + //Optimization: can be stored in the w/last component of one of the vectors + btScalar m_Adiag; + +}; + +#endif //JACOBIAN_ENTRY_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp new file mode 100644 index 00000000000..aacb0a3ea66 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp @@ -0,0 +1,116 @@ +/* +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. +*/ + + +#include "btPoint2PointConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include + + + +btPoint2PointConstraint::btPoint2PointConstraint() +{ +} + +btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB) +:btTypedConstraint(rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB) +{ + +} + + +btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) +:btTypedConstraint(rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) +{ + +} + +void btPoint2PointConstraint::buildJacobian() +{ + m_appliedImpulse = btScalar(0.); + + btVector3 normal(0,0,0); + + for (int i=0;i<3;i++) + { + normal[i] = 1; + new (&m_jac[i]) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(), + m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(), + normal, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + normal[i] = 0; + } + +} + +void btPoint2PointConstraint::solveConstraint(btScalar timeStep) +{ + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB; + + + btVector3 normal(0,0,0); + + +// btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); +// btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); + + for (int i=0;i<3;i++) + { + normal[i] = 1; + btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); + + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + //this jacobian entry could be re-used for all iterations + + btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar rel_vel; + rel_vel = normal.dot(vel); + + /* + //velocity error (first order error) + btScalar rel_vel = m_jac[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, + m_rbB.getLinearVelocity(),angvelB); + */ + + //positional error (zeroth order error) + btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal + + btScalar impulse = depth*m_setting.m_tau/timeStep * jacDiagABInv - m_setting.m_damping * rel_vel * jacDiagABInv; + m_appliedImpulse+=impulse; + btVector3 impulse_vector = normal * impulse; + m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); + m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); + + normal[i] = 0; + } +} + +void btPoint2PointConstraint::updateRHS(btScalar timeStep) +{ + (void)timeStep; + +} + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h new file mode 100644 index 00000000000..71da8ac0347 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -0,0 +1,77 @@ +/* +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. +*/ + +#ifndef POINT2POINTCONSTRAINT_H +#define POINT2POINTCONSTRAINT_H + +#include "../../LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +class btRigidBody; + +struct btConstraintSetting +{ + btConstraintSetting() : + m_tau(btScalar(0.3)), + m_damping(btScalar(1.)) + { + } + btScalar m_tau; + btScalar m_damping; +}; + +/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space +class btPoint2PointConstraint : public btTypedConstraint +{ + btJacobianEntry m_jac[3]; //3 orthogonal linear constraints + + btVector3 m_pivotInA; + btVector3 m_pivotInB; + + + +public: + + btConstraintSetting m_setting; + + btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB); + + btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA); + + btPoint2PointConstraint(); + + virtual void buildJacobian(); + + + virtual void solveConstraint(btScalar timeStep); + + void updateRHS(btScalar timeStep); + + void setPivotA(const btVector3& pivotA) + { + m_pivotInA = pivotA; + } + + void setPivotB(const btVector3& pivotB) + { + m_pivotInB = pivotB; + } + + + +}; + +#endif //POINT2POINTCONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp new file mode 100644 index 00000000000..14b36ad44fd --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -0,0 +1,1158 @@ +/* +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. +*/ + + +#include "btSequentialImpulseConstraintSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "btContactConstraint.h" +#include "btSolve2LinearConstraint.h" +#include "btContactSolverInfo.h" +#include "LinearMath/btIDebugDraw.h" +#include "btJacobianEntry.h" +#include "LinearMath/btMinMax.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include +#include "LinearMath/btStackAlloc.h" +#include "LinearMath/btQuickprof.h" +#include "btSolverBody.h" +#include "btSolverConstraint.h" + +#include "LinearMath/btAlignedObjectArray.h" + +#ifdef USE_PROFILE +#include "LinearMath/btQuickprof.h" +#endif //USE_PROFILE + +int totalCpd = 0; + +int gTotalContactPoints = 0; + +struct btOrderIndex +{ + int m_manifoldIndex; + int m_pointIndex; +}; + + + +#define SEQUENTIAL_IMPULSE_MAX_SOLVER_POINTS 16384 +static btOrderIndex gOrder[SEQUENTIAL_IMPULSE_MAX_SOLVER_POINTS]; + + +unsigned long btSequentialImpulseConstraintSolver::btRand2() +{ + m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff; + return m_btSeed2; +} + + + +//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1) +int btSequentialImpulseConstraintSolver::btRandInt2 (int n) +{ + // seems good; xor-fold and modulus + const unsigned long un = n; + unsigned long r = btRand2(); + + // note: probably more aggressive than it needs to be -- might be + // able to get away without one or two of the innermost branches. + if (un <= 0x00010000UL) { + r ^= (r >> 16); + if (un <= 0x00000100UL) { + r ^= (r >> 8); + if (un <= 0x00000010UL) { + r ^= (r >> 4); + if (un <= 0x00000004UL) { + r ^= (r >> 2); + if (un <= 0x00000002UL) { + r ^= (r >> 1); + } + } + } + } + } + + return (int) (r % un); +} + + + + + +bool MyContactDestroyedCallback(void* userPersistentData) +{ + assert (userPersistentData); + btConstraintPersistentData* cpd = (btConstraintPersistentData*)userPersistentData; + delete cpd; + totalCpd--; + //printf("totalCpd = %i. DELETED Ptr %x\n",totalCpd,userPersistentData); + return true; +} + + + +btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() +:m_solverMode(SOLVER_RANDMIZE_ORDER | SOLVER_CACHE_FRIENDLY), //not using SOLVER_USE_WARMSTARTING, +m_btSeed2(0) +{ + gContactDestroyedCallback = &MyContactDestroyedCallback; + + //initialize default friction/contact funcs + int i,j; + for (i=0;im_angularVelocity = rigidbody->getAngularVelocity(); + solverBody->m_centerOfMassPosition = rigidbody->getCenterOfMassPosition(); + solverBody->m_friction = rigidbody->getFriction(); +// solverBody->m_invInertiaWorld = rigidbody->getInvInertiaTensorWorld(); + solverBody->m_invMass = rigidbody->getInvMass(); + solverBody->m_linearVelocity = rigidbody->getLinearVelocity(); + solverBody->m_originalBody = rigidbody; + solverBody->m_angularFactor = rigidbody->getAngularFactor(); +} + +btScalar penetrationResolveFactor = btScalar(0.9); +btScalar restitutionCurve(btScalar rel_vel, btScalar restitution) +{ + btScalar rest = restitution * -rel_vel; + return rest; +} + + + + + + +//velocity + friction +//response between two dynamic objects with friction +SIMD_FORCE_INLINE btScalar resolveSingleCollisionCombinedCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo) +{ + (void)solverInfo; + + btScalar normalImpulse(0.f); + { + if (contactConstraint.m_penetration < 0.f) + return 0.f; + + // Optimized version of projected relative velocity, use precomputed cross products with normal + // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); + // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); + // btVector3 vel = vel1 - vel2; + // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); + + btScalar rel_vel; + btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) + + contactConstraint.m_relpos1CrossNormal.dot(body1.m_angularVelocity); + btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_linearVelocity) + + contactConstraint.m_relpos2CrossNormal.dot(body2.m_angularVelocity); + + rel_vel = vel1Dotn-vel2Dotn; + + + btScalar positionalError = contactConstraint.m_penetration; + btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; + + btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; + btScalar normalImpulse = penetrationImpulse+velocityImpulse; + + // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse + btScalar oldNormalImpulse = contactConstraint.m_appliedImpulse; + btScalar sum = oldNormalImpulse + normalImpulse; + contactConstraint.m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; + + btScalar oldVelocityImpulse = contactConstraint.m_appliedVelocityImpulse; + btScalar velocitySum = oldVelocityImpulse + velocityImpulse; + contactConstraint.m_appliedVelocityImpulse = btScalar(0.) > velocitySum ? btScalar(0.): velocitySum; + + normalImpulse = contactConstraint.m_appliedImpulse - oldNormalImpulse; + + if (body1.m_invMass) + { + body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, + contactConstraint.m_angularComponentA,normalImpulse); + } + if (body2.m_invMass) + { + body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, + contactConstraint.m_angularComponentB,-normalImpulse); + } + + } + + + + return normalImpulse; +} + + +#ifndef NO_FRICTION_TANGENTIALS + +SIMD_FORCE_INLINE btScalar resolveSingleFrictionCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo, + btScalar appliedNormalImpulse) +{ + (void)solverInfo; + + + const btScalar combinedFriction = contactConstraint.m_friction; + + const btScalar limit = appliedNormalImpulse * combinedFriction; + + if (appliedNormalImpulse>btScalar(0.)) + //friction + { + + btScalar j1; + { + + btScalar rel_vel; + const btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) + + contactConstraint.m_relpos1CrossNormal.dot(body1.m_angularVelocity); + const btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_linearVelocity) + + contactConstraint.m_relpos2CrossNormal.dot(body2.m_angularVelocity); + rel_vel = vel1Dotn-vel2Dotn; + + // calculate j that moves us to zero relative velocity + j1 = -rel_vel * contactConstraint.m_jacDiagABInv; + btScalar oldTangentImpulse = contactConstraint.m_appliedImpulse; + contactConstraint.m_appliedImpulse = oldTangentImpulse + j1; + GEN_set_min(contactConstraint.m_appliedImpulse, limit); + GEN_set_max(contactConstraint.m_appliedImpulse, -limit); + j1 = contactConstraint.m_appliedImpulse - oldTangentImpulse; + + } + + if (body1.m_invMass) + { + body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass,contactConstraint.m_angularComponentA,j1); + } + if (body2.m_invMass) + { + body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass,contactConstraint.m_angularComponentB,-j1); + } + + } + return 0.f; +} + + +#else + +//velocity + friction +//response between two dynamic objects with friction +btScalar resolveSingleFrictionCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo) +{ + + btVector3 vel1; + btVector3 vel2; + btScalar normalImpulse(0.f); + + { + const btVector3& normal = contactConstraint.m_contactNormal; + if (contactConstraint.m_penetration < 0.f) + return 0.f; + + + body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); + body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); + btVector3 vel = vel1 - vel2; + btScalar rel_vel; + rel_vel = normal.dot(vel); + + btVector3 lat_vel = vel - normal * rel_vel; + btScalar lat_rel_vel = lat_vel.length2(); + + btScalar combinedFriction = contactConstraint.m_friction; + const btVector3& rel_pos1 = contactConstraint.m_rel_posA; + const btVector3& rel_pos2 = contactConstraint.m_rel_posB; + + + //if (contactConstraint.m_appliedVelocityImpulse > 0.f) + if (lat_rel_vel > SIMD_EPSILON*SIMD_EPSILON) + { + lat_rel_vel = btSqrt(lat_rel_vel); + + lat_vel /= lat_rel_vel; + btVector3 temp1 = body1.m_invInertiaWorld * rel_pos1.cross(lat_vel); + btVector3 temp2 = body2.m_invInertiaWorld * rel_pos2.cross(lat_vel); + btScalar friction_impulse = lat_rel_vel / + (body1.m_invMass + body2.m_invMass + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); + btScalar normal_impulse = contactConstraint.m_appliedVelocityImpulse * combinedFriction; + + GEN_set_min(friction_impulse, normal_impulse); + GEN_set_max(friction_impulse, -normal_impulse); + body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1); + body2.applyImpulse(lat_vel * friction_impulse, rel_pos2); + } + } + + return normalImpulse; +} + +#endif //NO_FRICTION_TANGENTIALS + +btAlignedObjectArray tmpSolverBodyPool; +btAlignedObjectArray tmpSolverConstraintPool; +btAlignedObjectArray tmpSolverFrictionConstraintPool; + + +btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) +{ + (void)stackAlloc; + (void)debugDrawer; + + if (!(numConstraints + numManifolds)) + { +// printf("empty\n"); + return 0.f; + } + + BEGIN_PROFILE("refreshManifolds"); + + int i; + for (i=0;igetBody0(); + btRigidBody* rb1 = (btRigidBody*)manifold->getBody1(); + + manifold->refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); + + } + + END_PROFILE("refreshManifolds"); + + + BEGIN_PROFILE("gatherSolverData"); + + //int sizeofSB = sizeof(btSolverBody); + //int sizeofSC = sizeof(btSolverConstraint); + + + //if (1) + { + //if m_stackAlloc, try to pack bodies/constraints to speed up solving +// btBlock* sablock; +// sablock = stackAlloc->beginBlock(); + + // int memsize = 16; +// unsigned char* stackMemory = stackAlloc->allocate(memsize); + + + //todo: use stack allocator for this temp memory + int minReservation = numManifolds*2; + + tmpSolverBodyPool.reserve(minReservation); + + { + for (int i=0;igetIslandTag() >= 0)) + { + btAssert(rb->getCompanionId() < 0); + int solverBodyId = tmpSolverBodyPool.size(); + btSolverBody& solverBody = tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,rb); + rb->setCompanionId(solverBodyId); + } + } + } + + + tmpSolverConstraintPool.reserve(minReservation); + tmpSolverFrictionConstraintPool.reserve(minReservation); + { + int i; + + for (i=0;igetBody0(); + btRigidBody* rb1 = (btRigidBody*)manifold->getBody1(); + + + int solverBodyIdA=-1; + int solverBodyIdB=-1; + + if (manifold->getNumContacts()) + { + + + + if (rb0->getIslandTag() >= 0) + { + solverBodyIdA = rb0->getCompanionId(); + } else + { + //create a static body + solverBodyIdA = tmpSolverBodyPool.size(); + btSolverBody& solverBody = tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,rb0); + } + + if (rb1->getIslandTag() >= 0) + { + solverBodyIdB = rb1->getCompanionId(); + } else + { + //create a static body + solverBodyIdB = tmpSolverBodyPool.size(); + btSolverBody& solverBody = tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,rb1); + } + } + + for (int j=0;jgetNumContacts();j++) + { + + btManifoldPoint& cp = manifold->getContactPoint(j); + + int frictionIndex = tmpSolverConstraintPool.size(); + + if (cp.getDistance() <= btScalar(0.)) + { + + const btVector3& pos1 = cp.getPositionWorldOnA(); + const btVector3& pos2 = cp.getPositionWorldOnB(); + + btVector3 rel_pos1 = pos1 - rb0->getCenterOfMassPosition(); + btVector3 rel_pos2 = pos2 - rb1->getCenterOfMassPosition(); + + + btScalar relaxation = 1.f; + + { + btSolverConstraint& solverConstraint = tmpSolverConstraintPool.expand(); + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_CONTACT_1D; + + + + { + //can be optimized, the cross products are already calculated + btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB); + btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB); + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + } + + solverConstraint.m_contactNormal = cp.m_normalWorldOnB; + solverConstraint.m_relpos1CrossNormal = rel_pos1.cross(cp.m_normalWorldOnB); + solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(cp.m_normalWorldOnB); + + + btVector3 vel1 = rb0->getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = rb1->getVelocityInLocalPoint(rel_pos2); + + btVector3 vel = vel1 - vel2; + btScalar rel_vel; + rel_vel = cp.m_normalWorldOnB.dot(vel); + + + solverConstraint.m_penetration = cp.getDistance();///btScalar(infoGlobal.m_numIterations); + solverConstraint.m_friction = cp.m_combinedFriction; + btScalar rest = restitutionCurve(rel_vel, cp.m_combinedRestitution); + if (rest <= btScalar(0.)) + { + rest = 0.f; + }; + + btScalar penVel = -solverConstraint.m_penetration/infoGlobal.m_timeStep; + if (rest > penVel) + { + rest = btScalar(0.); + } + solverConstraint.m_restitution = rest; + + solverConstraint.m_penetration *= -(infoGlobal.m_erp/infoGlobal.m_timeStep); + + solverConstraint.m_appliedImpulse = 0.f; + solverConstraint.m_appliedVelocityImpulse = 0.f; + + + btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*torqueAxis0; + btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*torqueAxis1; + } + + //create 2 '1d axis' constraints for 2 tangential friction directions + + //re-calculate friction direction every frame, todo: check if this is really needed + btVector3 frictionTangential0a, frictionTangential1b; + + btPlaneSpace1(cp.m_normalWorldOnB,frictionTangential0a,frictionTangential1b); + + { + btSolverConstraint& solverConstraint = tmpSolverFrictionConstraintPool.expand(); + solverConstraint.m_contactNormal = frictionTangential0a; + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; + solverConstraint.m_frictionIndex = frictionIndex; + + solverConstraint.m_friction = cp.m_combinedFriction; + + solverConstraint.m_appliedImpulse = btScalar(0.); + solverConstraint.m_appliedVelocityImpulse = 0.f; + + btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); + btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + + { + btVector3 ftorqueAxis0 = rel_pos1.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos1CrossNormal = ftorqueAxis0; + solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis0; + } + { + btVector3 ftorqueAxis0 = rel_pos2.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos2CrossNormal = ftorqueAxis0; + solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis0; + } + + } + + + { + + btSolverConstraint& solverConstraint = tmpSolverFrictionConstraintPool.expand(); + solverConstraint.m_contactNormal = frictionTangential1b; + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; + solverConstraint.m_frictionIndex = frictionIndex; + + solverConstraint.m_friction = cp.m_combinedFriction; + + solverConstraint.m_appliedImpulse = btScalar(0.); + solverConstraint.m_appliedVelocityImpulse = 0.f; + + btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); + btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + { + btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis1; + } + { + btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis1; + } + } + + } + } + } + } + } + END_PROFILE("gatherSolverData"); + + BEGIN_PROFILE("prepareConstraints"); + + btContactSolverInfo info = infoGlobal; + + { + int j; + for (j=0;jbuildJacobian(); + } + } + + btAlignedObjectArray gOrderTmpConstraintPool; + btAlignedObjectArray gOrderFrictionConstraintPool; + + int numConstraintPool = tmpSolverConstraintPool.size(); + int numFrictionPool = tmpSolverFrictionConstraintPool.size(); + + ///todo: use stack allocator for such temporarily memory, same for solver bodies/constraints + gOrderTmpConstraintPool.resize(numConstraintPool); + gOrderFrictionConstraintPool.resize(numFrictionPool); + { + int i; + for (i=0;igetRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) + { + tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].writebackVelocity(); + } + if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) + { + tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); + } + + constraint->solveConstraint(info.m_timeStep); + + if ((constraint->getRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) + { + tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].readVelocity(); + } + if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) + { + tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); + } + + } + + { + int numPoolConstraints = tmpSolverConstraintPool.size(); + for (j=0;jgetNumContacts();p++) + { + gOrder[totalPoints].m_manifoldIndex = j; + gOrder[totalPoints].m_pointIndex = p; + totalPoints++; + } + } + } + + { + int j; + for (j=0;jbuildJacobian(); + } + } + + END_PROFILE("prepareConstraints"); + + + BEGIN_PROFILE("solveConstraints"); + + //should traverse the contacts random order... + int iteration; + + { + for ( iteration = 0;iterationsolveConstraint(info.m_timeStep); + } + + for (j=0;jgetBody0(), + (btRigidBody*)manifold->getBody1() + ,manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); + } + + for (j=0;jgetBody0(), + (btRigidBody*)manifold->getBody1(),manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); + } + } + } + + END_PROFILE("solveConstraints"); + + +#ifdef USE_PROFILE + btProfiler::endBlock("solve"); +#endif //USE_PROFILE + + + + + return btScalar(0.); +} + + + + + + + +void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer) +{ + + (void)debugDrawer; + + btRigidBody* body0 = (btRigidBody*)manifoldPtr->getBody0(); + btRigidBody* body1 = (btRigidBody*)manifoldPtr->getBody1(); + + + //only necessary to refresh the manifold once (first iteration). The integration is done outside the loop + { + manifoldPtr->refreshContactPoints(body0->getCenterOfMassTransform(),body1->getCenterOfMassTransform()); + + int numpoints = manifoldPtr->getNumContacts(); + + gTotalContactPoints += numpoints; + + btVector3 color(0,1,0); + for (int i=0;igetContactPoint(i); + if (cp.getDistance() <= btScalar(0.)) + { + const btVector3& pos1 = cp.getPositionWorldOnA(); + const btVector3& pos2 = cp.getPositionWorldOnB(); + + btVector3 rel_pos1 = pos1 - body0->getCenterOfMassPosition(); + btVector3 rel_pos2 = pos2 - body1->getCenterOfMassPosition(); + + + //this jacobian entry is re-used for all iterations + btJacobianEntry jac(body0->getCenterOfMassTransform().getBasis().transpose(), + body1->getCenterOfMassTransform().getBasis().transpose(), + rel_pos1,rel_pos2,cp.m_normalWorldOnB,body0->getInvInertiaDiagLocal(),body0->getInvMass(), + body1->getInvInertiaDiagLocal(),body1->getInvMass()); + + + btScalar jacDiagAB = jac.getDiagonal(); + + btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; + if (cpd) + { + //might be invalid + cpd->m_persistentLifeTime++; + if (cpd->m_persistentLifeTime != cp.getLifeTime()) + { + //printf("Invalid: cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd->m_persistentLifeTime,cp.getLifeTime()); + new (cpd) btConstraintPersistentData; + cpd->m_persistentLifeTime = cp.getLifeTime(); + + } else + { + //printf("Persistent: cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd->m_persistentLifeTime,cp.getLifeTime()); + + } + } else + { + + cpd = new btConstraintPersistentData; + assert(cpd); + + totalCpd ++; + //printf("totalCpd = %i Created Ptr %x\n",totalCpd,cpd); + cp.m_userPersistentData = cpd; + cpd->m_persistentLifeTime = cp.getLifeTime(); + //printf("CREATED: %x . cpd->m_persistentLifeTime = %i cp.getLifeTime() = %i\n",cpd,cpd->m_persistentLifeTime,cp.getLifeTime()); + + } + assert(cpd); + + cpd->m_jacDiagABInv = btScalar(1.) / jacDiagAB; + + //Dependent on Rigidbody A and B types, fetch the contact/friction response func + //perhaps do a similar thing for friction/restutution combiner funcs... + + cpd->m_frictionSolverFunc = m_frictionDispatch[body0->m_frictionSolverType][body1->m_frictionSolverType]; + cpd->m_contactSolverFunc = m_contactDispatch[body0->m_contactSolverType][body1->m_contactSolverType]; + + btVector3 vel1 = body0->getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body1->getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + btScalar rel_vel; + rel_vel = cp.m_normalWorldOnB.dot(vel); + + btScalar combinedRestitution = cp.m_combinedRestitution; + + cpd->m_penetration = cp.getDistance();///btScalar(info.m_numIterations); + cpd->m_friction = cp.m_combinedFriction; + cpd->m_restitution = restitutionCurve(rel_vel, combinedRestitution); + if (cpd->m_restitution <= btScalar(0.)) + { + cpd->m_restitution = btScalar(0.0); + + }; + + //restitution and penetration work in same direction so + //rel_vel + + btScalar penVel = -cpd->m_penetration/info.m_timeStep; + + if (cpd->m_restitution > penVel) + { + cpd->m_penetration = btScalar(0.); + } + + + + btScalar relaxation = info.m_damping; + if (m_solverMode & SOLVER_USE_WARMSTARTING) + { + cpd->m_appliedImpulse *= relaxation; + } else + { + cpd->m_appliedImpulse =btScalar(0.); + } + + //for friction + cpd->m_prevAppliedImpulse = cpd->m_appliedImpulse; + + //re-calculate friction direction every frame, todo: check if this is really needed + btPlaneSpace1(cp.m_normalWorldOnB,cpd->m_frictionWorldTangential0,cpd->m_frictionWorldTangential1); + + +#define NO_FRICTION_WARMSTART 1 + + #ifdef NO_FRICTION_WARMSTART + cpd->m_accumulatedTangentImpulse0 = btScalar(0.); + cpd->m_accumulatedTangentImpulse1 = btScalar(0.); + #endif //NO_FRICTION_WARMSTART + btScalar denom0 = body0->computeImpulseDenominator(pos1,cpd->m_frictionWorldTangential0); + btScalar denom1 = body1->computeImpulseDenominator(pos2,cpd->m_frictionWorldTangential0); + btScalar denom = relaxation/(denom0+denom1); + cpd->m_jacDiagABInvTangent0 = denom; + + + denom0 = body0->computeImpulseDenominator(pos1,cpd->m_frictionWorldTangential1); + denom1 = body1->computeImpulseDenominator(pos2,cpd->m_frictionWorldTangential1); + denom = relaxation/(denom0+denom1); + cpd->m_jacDiagABInvTangent1 = denom; + + btVector3 totalImpulse = + #ifndef NO_FRICTION_WARMSTART + cpd->m_frictionWorldTangential0*cpd->m_accumulatedTangentImpulse0+ + cpd->m_frictionWorldTangential1*cpd->m_accumulatedTangentImpulse1+ + #endif //NO_FRICTION_WARMSTART + cp.m_normalWorldOnB*cpd->m_appliedImpulse; + + + + /// + { + btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); + cpd->m_angularComponentA = body0->getInvInertiaTensorWorld()*torqueAxis0; + btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); + cpd->m_angularComponentB = body1->getInvInertiaTensorWorld()*torqueAxis1; + } + { + btVector3 ftorqueAxis0 = rel_pos1.cross(cpd->m_frictionWorldTangential0); + cpd->m_frictionAngularComponent0A = body0->getInvInertiaTensorWorld()*ftorqueAxis0; + } + { + btVector3 ftorqueAxis1 = rel_pos1.cross(cpd->m_frictionWorldTangential1); + cpd->m_frictionAngularComponent1A = body0->getInvInertiaTensorWorld()*ftorqueAxis1; + } + { + btVector3 ftorqueAxis0 = rel_pos2.cross(cpd->m_frictionWorldTangential0); + cpd->m_frictionAngularComponent0B = body1->getInvInertiaTensorWorld()*ftorqueAxis0; + } + { + btVector3 ftorqueAxis1 = rel_pos2.cross(cpd->m_frictionWorldTangential1); + cpd->m_frictionAngularComponent1B = body1->getInvInertiaTensorWorld()*ftorqueAxis1; + } + + /// + + + + //apply previous frames impulse on both bodies + body0->applyImpulse(totalImpulse, rel_pos1); + body1->applyImpulse(-totalImpulse, rel_pos2); + } + + } + } +} + + +btScalar btSequentialImpulseConstraintSolver::solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) +{ + btScalar maxImpulse = btScalar(0.); + + { + + btVector3 color(0,1,0); + { + if (cp.getDistance() <= btScalar(0.)) + { + + if (iter == 0) + { + if (debugDrawer) + debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); + } + + { + + //btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; + btScalar impulse = resolveSingleCollisionCombined( + *body0,*body1, + cp, + info); + + if (maxImpulse < impulse) + maxImpulse = impulse; + + } + } + } + } + return maxImpulse; +} + + + +btScalar btSequentialImpulseConstraintSolver::solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) +{ + + btScalar maxImpulse = btScalar(0.); + + { + + btVector3 color(0,1,0); + { + if (cp.getDistance() <= btScalar(0.)) + { + + if (iter == 0) + { + if (debugDrawer) + debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); + } + + { + + btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; + btScalar impulse = cpd->m_contactSolverFunc( + *body0,*body1, + cp, + info); + + if (maxImpulse < impulse) + maxImpulse = impulse; + + } + } + } + } + return maxImpulse; +} + +btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer) +{ + + (void)debugDrawer; + (void)iter; + + + { + + btVector3 color(0,1,0); + { + + if (cp.getDistance() <= btScalar(0.)) + { + + btConstraintPersistentData* cpd = (btConstraintPersistentData*) cp.m_userPersistentData; + cpd->m_frictionSolverFunc( + *body0,*body1, + cp, + info); + + + } + } + + + } + return btScalar(0.); +} diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h new file mode 100644 index 00000000000..13e70c41be4 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -0,0 +1,109 @@ +/* +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. +*/ + +#ifndef SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H +#define SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H + +#include "btConstraintSolver.h" +class btIDebugDraw; +#include "btContactConstraint.h" + + + +/// btSequentialImpulseConstraintSolver uses a Propagation Method and Sequentially applies impulses +/// The approach is the 3D version of Erin Catto's GDC 2006 tutorial. See http://www.gphysics.com +/// Although Sequential Impulse is more intuitive, it is mathematically equivalent to Projected Successive Overrelaxation (iterative LCP) +/// Applies impulses for combined restitution and penetration recovery and to simulate friction +class btSequentialImpulseConstraintSolver : public btConstraintSolver +{ + +protected: + btScalar solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); + btScalar solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); + void prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer); + + ContactSolverFunc m_contactDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; + ContactSolverFunc m_frictionDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; + + //choose between several modes, different friction model etc. + int m_solverMode; + ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction + unsigned long m_btSeed2; + +public: + + enum eSolverMode + { + SOLVER_RANDMIZE_ORDER = 1, + SOLVER_FRICTION_SEPARATE = 2, + SOLVER_USE_WARMSTARTING = 4, + SOLVER_CACHE_FRIENDLY = 8 + }; + + btSequentialImpulseConstraintSolver(); + + ///Advanced: Override the default contact solving function for contacts, for certain types of rigidbody + ///See btRigidBody::m_contactSolverType and btRigidBody::m_frictionSolverType + void setContactSolverFunc(ContactSolverFunc func,int type0,int type1) + { + m_contactDispatch[type0][type1] = func; + } + + ///Advanced: Override the default friction solving function for contacts, for certain types of rigidbody + ///See btRigidBody::m_contactSolverType and btRigidBody::m_frictionSolverType + void SetFrictionSolverFunc(ContactSolverFunc func,int type0,int type1) + { + m_frictionDispatch[type0][type1] = func; + } + + virtual ~btSequentialImpulseConstraintSolver() {} + + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc); + + virtual btScalar solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + + btScalar solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); + + + void setSolverMode(int mode) + { + m_solverMode = mode; + } + + int getSolverMode() const + { + return m_solverMode; + } + + unsigned long btRand2(); + + int btRandInt2 (int n); + + void setRandSeed(unsigned long seed) + { + m_btSeed2 = seed; + } + unsigned long getRandSeed() const + { + return m_btSeed2; + } + +}; + + + + +#endif //SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp new file mode 100644 index 00000000000..0c7dbd668bb --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp @@ -0,0 +1,255 @@ +/* +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. +*/ + + + +#include "btSolve2LinearConstraint.h" + +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" + + +void btSolve2LinearConstraint::resolveUnilateralPairConstraint( + btRigidBody* body1, + btRigidBody* body2, + + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1) +{ + (void)linvelA; + (void)linvelB; + (void)angvelB; + (void)angvelA; + + + + imp0 = btScalar(0.); + imp1 = btScalar(0.); + + btScalar len = btFabs(normalA.length()) - btScalar(1.); + if (btFabs(len) >= SIMD_EPSILON) + return; + + btAssert(len < SIMD_EPSILON); + + + //this jacobian entry could be re-used for all iterations + btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + + //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + + const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1)); + const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1)); + +// btScalar penetrationImpulse = (depth*contactTau*timeCorrection) * massTerm;//jacDiagABInv + btScalar massTerm = btScalar(1.) / (invMassA + invMassB); + + + // calculate rhs (or error) terms + const btScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping; + const btScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping; + + + // dC/dv * dv = -C + + // jacobian * impulse = -error + // + + //impulse = jacobianInverse * -error + + // inverting 2x2 symmetric system (offdiagonal are equal!) + // + + + btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB); + btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag ); + + //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + //[a b] [d -c] + //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc) + + //[jA nD] * [imp0] = [dv0] + //[nD jB] [imp1] [dv1] + +} + + + +void btSolve2LinearConstraint::resolveBilateralPairConstraint( + btRigidBody* body1, + btRigidBody* body2, + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1) +{ + + (void)linvelA; + (void)linvelB; + (void)angvelA; + (void)angvelB; + + + + imp0 = btScalar(0.); + imp1 = btScalar(0.); + + btScalar len = btFabs(normalA.length()) - btScalar(1.); + if (btFabs(len) >= SIMD_EPSILON) + return; + + btAssert(len < SIMD_EPSILON); + + + //this jacobian entry could be re-used for all iterations + btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA, + invInertiaBDiag,invMassB); + + //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB); + + const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1)); + const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1)); + + // calculate rhs (or error) terms + const btScalar dv0 = depthA * m_tau - vel0 * m_damping; + const btScalar dv1 = depthB * m_tau - vel1 * m_damping; + + // dC/dv * dv = -C + + // jacobian * impulse = -error + // + + //impulse = jacobianInverse * -error + + // inverting 2x2 symmetric system (offdiagonal are equal!) + // + + + btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB); + btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag ); + + //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet; + imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet; + + //[a b] [d -c] + //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc) + + //[jA nD] * [imp0] = [dv0] + //[nD jB] [imp1] [dv1] + + if ( imp0 > btScalar(0.0)) + { + if ( imp1 > btScalar(0.0) ) + { + //both positive + } + else + { + imp1 = btScalar(0.); + + // now imp0>0 imp1<0 + imp0 = dv0 / jacA.getDiagonal(); + if ( imp0 > btScalar(0.0) ) + { + } else + { + imp0 = btScalar(0.); + } + } + } + else + { + imp0 = btScalar(0.); + + imp1 = dv1 / jacB.getDiagonal(); + if ( imp1 <= btScalar(0.0) ) + { + imp1 = btScalar(0.); + // now imp0>0 imp1<0 + imp0 = dv0 / jacA.getDiagonal(); + if ( imp0 > btScalar(0.0) ) + { + } else + { + imp0 = btScalar(0.); + } + } else + { + } + } +} + + +/* +void btSolve2LinearConstraint::resolveAngularConstraint( const btMatrix3x3& invInertiaAWS, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btMatrix3x3& invInertiaBWS, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1) +{ + +} +*/ + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h new file mode 100644 index 00000000000..e7d26645c6a --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h @@ -0,0 +1,107 @@ +/* +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. +*/ + +#ifndef SOLVE_2LINEAR_CONSTRAINT_H +#define SOLVE_2LINEAR_CONSTRAINT_H + +#include "../../LinearMath/btMatrix3x3.h" +#include "../../LinearMath/btVector3.h" + + +class btRigidBody; + + + +/// constraint class used for lateral tyre friction. +class btSolve2LinearConstraint +{ + btScalar m_tau; + btScalar m_damping; + +public: + + btSolve2LinearConstraint(btScalar tau,btScalar damping) + { + m_tau = tau; + m_damping = damping; + } + // + // solve unilateral constraint (equality, direct method) + // + void resolveUnilateralPairConstraint( + btRigidBody* body0, + btRigidBody* body1, + + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1); + + + // + // solving 2x2 lcp problem (inequality, direct solution ) + // + void resolveBilateralPairConstraint( + btRigidBody* body0, + btRigidBody* body1, + const btMatrix3x3& world2A, + const btMatrix3x3& world2B, + + const btVector3& invInertiaADiag, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btVector3& invInertiaBDiag, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1); + +/* + void resolveAngularConstraint( const btMatrix3x3& invInertiaAWS, + const btScalar invMassA, + const btVector3& linvelA,const btVector3& angvelA, + const btVector3& rel_posA1, + const btMatrix3x3& invInertiaBWS, + const btScalar invMassB, + const btVector3& linvelB,const btVector3& angvelB, + const btVector3& rel_posA2, + + btScalar depthA, const btVector3& normalA, + const btVector3& rel_posB1,const btVector3& rel_posB2, + btScalar depthB, const btVector3& normalB, + btScalar& imp0,btScalar& imp1); + +*/ + +}; + +#endif //SOLVE_2LINEAR_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h new file mode 100644 index 00000000000..0ab536f42b3 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h @@ -0,0 +1,71 @@ +/* +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. +*/ + +#ifndef BT_SOLVER_BODY_H +#define BT_SOLVER_BODY_H + +class btRigidBody; +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" + + + + +ATTRIBUTE_ALIGNED16 (struct) btSolverBody +{ + btVector3 m_centerOfMassPosition; + btVector3 m_linearVelocity; + btVector3 m_angularVelocity; + btRigidBody* m_originalBody; + float m_invMass; + float m_friction; + float m_angularFactor; + + inline void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const + { + velocity = m_linearVelocity + m_angularVelocity.cross(rel_pos); + } + + //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position + inline void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + { + m_linearVelocity += linearComponent*impulseMagnitude; + m_angularVelocity += angularComponent*impulseMagnitude*m_angularFactor; + } + + void writebackVelocity() + { + if (m_invMass) + { + m_originalBody->setLinearVelocity(m_linearVelocity); + m_originalBody->setAngularVelocity(m_angularVelocity); + } + } + + void readVelocity() + { + if (m_invMass) + { + m_linearVelocity = m_originalBody->getLinearVelocity(); + m_angularVelocity = m_originalBody->getAngularVelocity(); + } + } + + + + +}; + +#endif //BT_SOLVER_BODY_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h new file mode 100644 index 00000000000..f1f40ffdf19 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h @@ -0,0 +1,63 @@ + + +/* +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. +*/ + +#ifndef BT_SOLVER_CONSTRAINT_H +#define BT_SOLVER_CONSTRAINT_H + +class btRigidBody; +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" + +//#define NO_FRICTION_TANGENTIALS 1 + +///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints. +ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint +{ + btVector3 m_relpos1CrossNormal; + btVector3 m_relpos2CrossNormal; + btVector3 m_contactNormal; + btVector3 m_angularComponentA; + btVector3 m_angularComponentB; + + btScalar m_appliedVelocityImpulse; + int m_solverBodyIdA; + int m_solverBodyIdB; + btScalar m_friction; + btScalar m_restitution; + btScalar m_jacDiagABInv; + btScalar m_penetration; + btScalar m_appliedImpulse; + + int m_constraintType; + int m_frictionIndex; + int m_unusedPadding[2]; + + enum btSolverConstraintType + { + BT_SOLVER_CONTACT_1D = 0, + BT_SOLVER_FRICTION_1D + }; +}; + + + + + + +#endif //BT_SOLVER_CONSTRAINT_H + + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp new file mode 100644 index 00000000000..a15b3e026cd --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp @@ -0,0 +1,53 @@ +/* +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. +*/ + + +#include "btTypedConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +static btRigidBody s_fixed(0, 0,0); + +btTypedConstraint::btTypedConstraint() +: m_userConstraintType(-1), +m_userConstraintId(-1), +m_rbA(s_fixed), +m_rbB(s_fixed), +m_appliedImpulse(btScalar(0.)) +{ + s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); +} +btTypedConstraint::btTypedConstraint(btRigidBody& rbA) +: m_userConstraintType(-1), +m_userConstraintId(-1), +m_rbA(rbA), +m_rbB(s_fixed), +m_appliedImpulse(btScalar(0.)) +{ + s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); + +} + + +btTypedConstraint::btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB) +: m_userConstraintType(-1), +m_userConstraintId(-1), +m_rbA(rbA), +m_rbB(rbB), +m_appliedImpulse(btScalar(0.)) +{ + s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); + +} + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h new file mode 100644 index 00000000000..dfee6e80d0e --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -0,0 +1,96 @@ +/* +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. +*/ + +#ifndef TYPED_CONSTRAINT_H +#define TYPED_CONSTRAINT_H + +class btRigidBody; +#include "../../LinearMath/btScalar.h" + +///TypedConstraint is the baseclass for Bullet constraints and vehicles +class btTypedConstraint +{ + int m_userConstraintType; + int m_userConstraintId; + + btTypedConstraint& operator=(btTypedConstraint& other) + { + btAssert(0); + (void) other; + return *this; + } + +protected: + btRigidBody& m_rbA; + btRigidBody& m_rbB; + btScalar m_appliedImpulse; + + +public: + + btTypedConstraint(); + virtual ~btTypedConstraint() {}; + btTypedConstraint(btRigidBody& rbA); + + btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB); + + virtual void buildJacobian() = 0; + + virtual void solveConstraint(btScalar timeStep) = 0; + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + btRigidBody& getRigidBodyA() + { + return m_rbA; + } + btRigidBody& getRigidBodyB() + { + return m_rbB; + } + + int getUserConstraintType() const + { + return m_userConstraintType ; + } + + void setUserConstraintType(int userConstraintType) + { + m_userConstraintType = userConstraintType; + }; + + void setUserConstraintId(int uid) + { + m_userConstraintId = uid; + } + + int getUserConstraintId() + { + return m_userConstraintId; + } + btScalar getAppliedImpulse() + { + return m_appliedImpulse; + } +}; + +#endif //TYPED_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp new file mode 100644 index 00000000000..248c582dcd8 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp @@ -0,0 +1,120 @@ +/* +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 +*/ + +#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]) +{ + btVector3 vp(p1[0], p1[1], p1[2]); + btTriangleShape trishapeA(vp, + btVector3(p2[0], p2[1], p2[2]), + btVector3(p3[0], p3[1], p3[2])); + trishapeA.setMargin(0.000001f); + btVector3 vq(q1[0], q1[1], q1[2]); + btTriangleShape trishapeB(vq, + 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; +} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp new file mode 100644 index 00000000000..29719ec9a3e --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -0,0 +1,954 @@ +/* +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. +*/ + + +#include "btDiscreteDynamicsWorld.h" + +//collision detection +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" +#include + +//rigidbody & constraints +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" + +//for debug rendering +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btConeShape.h" +#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" +#include "LinearMath/btIDebugDraw.h" + + + +//vehicle +#include "BulletDynamics/Vehicle/btRaycastVehicle.h" +#include "BulletDynamics/Vehicle/btVehicleRaycaster.h" +#include "BulletDynamics/Vehicle/btWheelInfo.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btMotionState.h" + + + + + +btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) +:btDynamicsWorld(dispatcher,pairCache), +m_constraintSolver(constraintSolver? constraintSolver: new btSequentialImpulseConstraintSolver), +m_debugDrawer(0), +m_gravity(0,-10,0), +m_localTime(btScalar(1.)/btScalar(60.)), +m_profileTimings(0) +{ + m_islandManager = new btSimulationIslandManager(); + m_ownsIslandManager = true; + m_ownsConstraintSolver = (constraintSolver==0); +} + + +btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld() +{ + //only delete it when we created it + if (m_ownsIslandManager) + delete m_islandManager; + if (m_ownsConstraintSolver) + delete m_constraintSolver; +} + +void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) +{ + + for (int i=0;igetActivationState() != ISLAND_SLEEPING) + { + if (body->isKinematicObject()) + { + //to calculate velocities next frame + body->saveKinematicState(timeStep); + } + } + } + } +} + +void btDiscreteDynamicsWorld::synchronizeMotionStates() +{ + //debug vehicle wheels + + + { + //todo: iterate over awake simulation islands! + for ( int i=0;igetDebugMode() & btIDebugDraw::DBG_DrawWireframe) + { + btVector3 color(btScalar(255.),btScalar(255.),btScalar(255.)); + switch(colObj->getActivationState()) + { + case ACTIVE_TAG: + color = btVector3(btScalar(255.),btScalar(255.),btScalar(255.)); break; + case ISLAND_SLEEPING: + color = btVector3(btScalar(0.),btScalar(255.),btScalar(0.));break; + case WANTS_DEACTIVATION: + color = btVector3(btScalar(0.),btScalar(255.),btScalar(255.));break; + case DISABLE_DEACTIVATION: + color = btVector3(btScalar(255.),btScalar(0.),btScalar(0.));break; + case DISABLE_SIMULATION: + color = btVector3(btScalar(255.),btScalar(255.),btScalar(0.));break; + default: + { + color = btVector3(btScalar(255.),btScalar(0.),btScalar(0.)); + } + }; + + debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color); + } + btRigidBody* body = btRigidBody::upcast(colObj); + if (body && body->getMotionState() && !body->isStaticOrKinematicObject()) + { + //we need to call the update at least once, even for sleeping objects + //otherwise the 'graphics' transform never updates properly + //so todo: add 'dirty' flag + //if (body->getActivationState() != ISLAND_SLEEPING) + { + btTransform interpolatedTransform; + btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), + body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime,interpolatedTransform); + body->getMotionState()->setWorldTransform(interpolatedTransform); + } + } + } + } + + if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe) + { + for ( int i=0;im_vehicles.size();i++) + { + for (int v=0;vgetNumWheels();v++) + { + btVector3 wheelColor(0,255,255); + if (m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_isInContact) + { + wheelColor.setValue(0,0,255); + } else + { + wheelColor.setValue(255,0,255); + } + + //synchronize the wheels with the (interpolated) chassis worldtransform + m_vehicles[i]->updateWheelTransform(v,true); + + btVector3 wheelPosWS = m_vehicles[i]->getWheelInfo(v).m_worldTransform.getOrigin(); + + btVector3 axle = btVector3( + m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[0][m_vehicles[i]->getRightAxis()], + m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[1][m_vehicles[i]->getRightAxis()], + m_vehicles[i]->getWheelInfo(v).m_worldTransform.getBasis()[2][m_vehicles[i]->getRightAxis()]); + + + //m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_wheelAxleWS + //debug wheels (cylinders) + m_debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); + m_debugDrawer->drawLine(wheelPosWS,m_vehicles[i]->getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); + + } + } + } + +} + + +int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) +{ + int numSimulationSubSteps = 0; + + if (maxSubSteps) + { + //fixed timestep with interpolation + m_localTime += timeStep; + if (m_localTime >= fixedTimeStep) + { + numSimulationSubSteps = int( m_localTime / fixedTimeStep); + m_localTime -= numSimulationSubSteps * fixedTimeStep; + } + } else + { + //variable timestep + fixedTimeStep = timeStep; + m_localTime = timeStep; + if (btFuzzyZero(timeStep)) + { + numSimulationSubSteps = 0; + maxSubSteps = 0; + } else + { + numSimulationSubSteps = 1; + maxSubSteps = 1; + } + } + + //process some debugging flags + if (getDebugDrawer()) + { + gDisableDeactivation = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0; + } + if (numSimulationSubSteps) + { + + saveKinematicState(fixedTimeStep); + + //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt + int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps; + + for (int i=0;isetGravity(gravity); + } + } +} + + +void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body) +{ + removeCollisionObject(body); +} + +void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body) +{ + if (!body->isStaticOrKinematicObject()) + { + body->setGravity(m_gravity); + } + + if (body->getCollisionShape()) + { + bool isDynamic = !(body->isStaticObject() || body->isKinematicObject()); + short collisionFilterGroup = isDynamic? short(btBroadphaseProxy::DefaultFilter) : short(btBroadphaseProxy::StaticFilter); + short collisionFilterMask = isDynamic? short(btBroadphaseProxy::AllFilter) : short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); + + addCollisionObject(body,collisionFilterGroup,collisionFilterMask); + } +} + +void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask) +{ + if (!body->isStaticOrKinematicObject()) + { + body->setGravity(m_gravity); + } + + if (body->getCollisionShape()) + { + addCollisionObject(body,group,mask); + } +} + + +void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep) +{ + BEGIN_PROFILE("updateVehicles"); + + for ( int i=0;iupdateVehicle( timeStep); + } + END_PROFILE("updateVehicles"); +} + +void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) +{ + BEGIN_PROFILE("updateActivationState"); + + for ( int i=0;iupdateDeactivation(timeStep); + + if (body->wantsSleeping()) + { + if (body->isStaticOrKinematicObject()) + { + body->setActivationState(ISLAND_SLEEPING); + } else + { + if (body->getActivationState() == ACTIVE_TAG) + body->setActivationState( WANTS_DEACTIVATION ); + } + } else + { + if (body->getActivationState() != DISABLE_DEACTIVATION) + body->setActivationState( ACTIVE_TAG ); + } + } + } + END_PROFILE("updateActivationState"); +} + +void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies) +{ + m_constraints.push_back(constraint); + if (disableCollisionsBetweenLinkedBodies) + { + constraint->getRigidBodyA().addConstraintRef(constraint); + constraint->getRigidBodyB().addConstraintRef(constraint); + } +} + +void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint) +{ + m_constraints.remove(constraint); + constraint->getRigidBodyA().removeConstraintRef(constraint); + constraint->getRigidBodyB().removeConstraintRef(constraint); +} + +void btDiscreteDynamicsWorld::addVehicle(btRaycastVehicle* vehicle) +{ + m_vehicles.push_back(vehicle); +} + +void btDiscreteDynamicsWorld::removeVehicle(btRaycastVehicle* vehicle) +{ + m_vehicles.remove(vehicle); +} + +inline int btGetConstraintIslandId(const btTypedConstraint* lhs) +{ + int islandId; + + const btCollisionObject& rcolObj0 = lhs->getRigidBodyA(); + const btCollisionObject& rcolObj1 = lhs->getRigidBodyB(); + islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag(); + return islandId; + +} + + +class btSortConstraintOnIslandPredicate +{ + public: + + bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs ) + { + int rIslandId0,lIslandId0; + rIslandId0 = btGetConstraintIslandId(rhs); + lIslandId0 = btGetConstraintIslandId(lhs); + return lIslandId0 < rIslandId0; + } +}; + + + + +void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) +{ + + struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback + { + + btContactSolverInfo& m_solverInfo; + btConstraintSolver* m_solver; + btTypedConstraint** m_sortedConstraints; + int m_numConstraints; + btIDebugDraw* m_debugDrawer; + btStackAlloc* m_stackAlloc; + + + InplaceSolverIslandCallback( + btContactSolverInfo& solverInfo, + btConstraintSolver* solver, + btTypedConstraint** sortedConstraints, + int numConstraints, + btIDebugDraw* debugDrawer, + btStackAlloc* stackAlloc) + :m_solverInfo(solverInfo), + m_solver(solver), + m_sortedConstraints(sortedConstraints), + m_numConstraints(numConstraints), + m_debugDrawer(debugDrawer), + m_stackAlloc(stackAlloc) + { + + } + + InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other) + { + btAssert(0); + (void)other; + return *this; + } + virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId) + { + //also add all non-contact constraints/joints for this island + btTypedConstraint** startConstraint = 0; + int numCurConstraints = 0; + int i; + + //find the first constraint for this island + for (i=0;isolveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc); + } + + }; + + //sorted version of all btTypedConstraint, based on islandId + btAlignedObjectArray sortedConstraints; + sortedConstraints.resize( m_constraints.size()); + int i; + for (i=0;ibuildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld()->getCollisionObjectArray(),&solverCallback); + + +} + + + + +void btDiscreteDynamicsWorld::calculateSimulationIslands() +{ + BEGIN_PROFILE("calculateSimulationIslands"); + + getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher()); + + { + int i; + int numConstraints = int(m_constraints.size()); + for (i=0;i< numConstraints ; i++ ) + { + btTypedConstraint* constraint = m_constraints[i]; + + const btRigidBody* colObj0 = &constraint->getRigidBodyA(); + const btRigidBody* colObj1 = &constraint->getRigidBodyB(); + + if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && + ((colObj1) && ((colObj1)->mergesSimulationIslands()))) + { + if (colObj0->isActive() || colObj1->isActive()) + { + + getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), + (colObj1)->getIslandTag()); + } + } + } + } + + //Store the island id in each body + getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld()); + + END_PROFILE("calculateSimulationIslands"); + +} + + +void btDiscreteDynamicsWorld::updateAabbs() +{ + BEGIN_PROFILE("updateAabbs"); + + btVector3 colorvec(1,0,0); + btTransform predictedTrans; + for ( int i=0;iIsActive() && (!body->IsStatic())) + { + btPoint3 minAabb,maxAabb; + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; + + //moving objects should be moderately sized, probably something wrong if not + if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) + { + bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb); + } else + { + //something went wrong, investigate + //this assert is unwanted in 3D modelers (danger of loosing work) + body->setActivationState(DISABLE_SIMULATION); + + static bool reportMe = true; + if (reportMe && m_debugDrawer) + { + reportMe = false; + m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); + m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); + m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); + m_debugDrawer->reportErrorWarning("Thanks.\n"); + } + + + } + if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); + } + } + } + } + + END_PROFILE("updateAabbs"); +} + +void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) +{ + BEGIN_PROFILE("integrateTransforms"); + btTransform predictedTrans; + for ( int i=0;iisActive() && (!body->isStaticOrKinematicObject())) + { + body->predictIntegratedTransform(timeStep, predictedTrans); + body->proceedToTransform( predictedTrans); + } + } + } + END_PROFILE("integrateTransforms"); +} + + + +void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + BEGIN_PROFILE("predictUnconstraintMotion"); + for ( int i=0;iisStaticOrKinematicObject()) + { + if (body->isActive()) + { + body->applyForces( timeStep); + body->integrateVelocities( timeStep); + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); + } + } + } + } + END_PROFILE("predictUnconstraintMotion"); +} + + +void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep) +{ + (void)timeStep; + #ifdef USE_QUICKPROF + + + //toggle btProfiler + if ( m_debugDrawer && m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_ProfileTimings) + { + if (!m_profileTimings) + { + m_profileTimings = 1; + // To disable profiling, simply comment out the following line. + static int counter = 0; + + char filename[128]; + sprintf(filename,"quickprof_bullet_timings%i.csv",counter++); + btProfiler::init(filename, btProfiler::BLOCK_CYCLE_SECONDS);//BLOCK_TOTAL_MICROSECONDS + } else + { + btProfiler::endProfilingCycle(); + } + + } else + { + if (m_profileTimings) + { + btProfiler::endProfilingCycle(); + + m_profileTimings = 0; + btProfiler::destroy(); + } + } +#endif //USE_QUICKPROF +} + + + + + + +class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback +{ + btIDebugDraw* m_debugDrawer; + btVector3 m_color; + btTransform m_worldTrans; + +public: + + DebugDrawcallback(btIDebugDraw* debugDrawer,const btTransform& worldTrans,const btVector3& color) : + m_debugDrawer(debugDrawer), + m_color(color), + m_worldTrans(worldTrans) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) + { + processTriangle(triangle,partId,triangleIndex); + } + + virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + + btVector3 wv0,wv1,wv2; + wv0 = m_worldTrans*triangle[0]; + wv1 = m_worldTrans*triangle[1]; + wv2 = m_worldTrans*triangle[2]; + m_debugDrawer->drawLine(wv0,wv1,m_color); + m_debugDrawer->drawLine(wv1,wv2,m_color); + m_debugDrawer->drawLine(wv2,wv0,m_color); + } +}; + +void btDiscreteDynamicsWorld::debugDrawSphere(btScalar radius, const btTransform& transform, const btVector3& color) +{ + btVector3 start = transform.getOrigin(); + + const btVector3 xoffs = transform.getBasis() * btVector3(radius,0,0); + const btVector3 yoffs = transform.getBasis() * btVector3(0,radius,0); + const btVector3 zoffs = transform.getBasis() * btVector3(0,0,radius); + + // XY + getDebugDrawer()->drawLine(start-xoffs, start+yoffs, color); + getDebugDrawer()->drawLine(start+yoffs, start+xoffs, color); + getDebugDrawer()->drawLine(start+xoffs, start-yoffs, color); + getDebugDrawer()->drawLine(start-yoffs, start-xoffs, color); + + // XZ + getDebugDrawer()->drawLine(start-xoffs, start+zoffs, color); + getDebugDrawer()->drawLine(start+zoffs, start+xoffs, color); + getDebugDrawer()->drawLine(start+xoffs, start-zoffs, color); + getDebugDrawer()->drawLine(start-zoffs, start-xoffs, color); + + // YZ + getDebugDrawer()->drawLine(start-yoffs, start+zoffs, color); + getDebugDrawer()->drawLine(start+zoffs, start+yoffs, color); + getDebugDrawer()->drawLine(start+yoffs, start-zoffs, color); + getDebugDrawer()->drawLine(start-zoffs, start-yoffs, color); +} + +void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color) +{ + // Draw a small simplex at the center of the object + { + btVector3 start = worldTransform.getOrigin(); + getDebugDrawer()->drawLine(start, start+worldTransform.getBasis() * btVector3(1,0,0), btVector3(1,0,0)); + getDebugDrawer()->drawLine(start, start+worldTransform.getBasis() * btVector3(0,1,0), btVector3(0,1,0)); + getDebugDrawer()->drawLine(start, start+worldTransform.getBasis() * btVector3(0,0,1), btVector3(0,0,1)); + } + + if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) + { + const btCompoundShape* compoundShape = static_cast(shape); + for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* colShape = compoundShape->getChildShape(i); + debugDrawObject(worldTransform*childTrans,colShape,color); + } + + } else + { + switch (shape->getShapeType()) + { + + case SPHERE_SHAPE_PROXYTYPE: + { + const btSphereShape* sphereShape = static_cast(shape); + btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin + + debugDrawSphere(radius, worldTransform, color); + break; + } + case MULTI_SPHERE_SHAPE_PROXYTYPE: + { + const btMultiSphereShape* multiSphereShape = static_cast(shape); + + for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--) + { + btTransform childTransform = worldTransform; + childTransform.getOrigin() += multiSphereShape->getSpherePosition(i); + debugDrawSphere(multiSphereShape->getSphereRadius(i), childTransform, color); + } + + break; + } + case CAPSULE_SHAPE_PROXYTYPE: + { + const btCapsuleShape* capsuleShape = static_cast(shape); + + btScalar radius = capsuleShape->getRadius(); + btScalar halfHeight = capsuleShape->getHalfHeight(); + + // Draw the ends + { + btTransform childTransform = worldTransform; + childTransform.getOrigin() = worldTransform * btVector3(0,halfHeight,0); + debugDrawSphere(radius, childTransform, color); + } + + { + btTransform childTransform = worldTransform; + childTransform.getOrigin() = worldTransform * btVector3(0,-halfHeight,0); + debugDrawSphere(radius, childTransform, color); + } + + // Draw some additional lines + btVector3 start = worldTransform.getOrigin(); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(-radius,halfHeight,0),start+worldTransform.getBasis() * btVector3(-radius,-halfHeight,0), color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(radius,halfHeight,0),start+worldTransform.getBasis() * btVector3(radius,-halfHeight,0), color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(0,halfHeight,-radius),start+worldTransform.getBasis() * btVector3(0,-halfHeight,-radius), color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(0,halfHeight,radius),start+worldTransform.getBasis() * btVector3(0,-halfHeight,radius), color); + + break; + } + case CONE_SHAPE_PROXYTYPE: + { + const btConeShape* coneShape = static_cast(shape); + btScalar radius = coneShape->getRadius();//+coneShape->getMargin(); + btScalar height = coneShape->getHeight();//+coneShape->getMargin(); + btVector3 start = worldTransform.getOrigin(); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(radius,btScalar(0.),btScalar(-0.5)*height),color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(-radius,btScalar(0.),btScalar(-0.5)*height),color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),radius,btScalar(-0.5)*height),color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),-radius,btScalar(-0.5)*height),color); + break; + + } + case CYLINDER_SHAPE_PROXYTYPE: + { + const btCylinderShape* cylinder = static_cast(shape); + int upAxis = cylinder->getUpAxis(); + btScalar radius = cylinder->getRadius(); + btScalar halfHeight = cylinder->getHalfExtents()[upAxis]; + btVector3 start = worldTransform.getOrigin(); + btVector3 offsetHeight(0,0,0); + offsetHeight[upAxis] = halfHeight; + btVector3 offsetRadius(0,0,0); + offsetRadius[(upAxis+1)%3] = radius; + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight+offsetRadius),start+worldTransform.getBasis() * (-offsetHeight+offsetRadius),color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight-offsetRadius),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color); + break; + } + default: + { + + if (shape->isConcave()) + { + btConcaveShape* concaveMesh = (btConcaveShape*) shape; + + //todo pass camera, for some culling + btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); + + DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); + concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax); + + } + + if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE) + { + btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape; + //todo: pass camera for some culling + btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); + //DebugDrawcallback drawCallback; + DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); + convexMesh->getStridingMesh()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); + } + + + /// for polyhedral shapes + if (shape->isPolyhedral()) + { + btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape; + + int i; + for (i=0;igetNumEdges();i++) + { + btPoint3 a,b; + polyshape->getEdge(i,a,b); + btVector3 wa = worldTransform * a; + btVector3 wb = worldTransform * b; + getDebugDrawer()->drawLine(wa,wb,color); + + } + + + } + } + } + } +} + + +void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) +{ + if (m_ownsConstraintSolver) + { + delete m_constraintSolver; + } + m_ownsConstraintSolver = false; + m_constraintSolver = solver; +} + +int btDiscreteDynamicsWorld::getNumConstraints() const +{ + return int(m_constraints.size()); +} +btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) +{ + return m_constraints[index]; +} +const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const +{ + return m_constraints[index]; +} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h new file mode 100644 index 00000000000..83b90bfeebc --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -0,0 +1,157 @@ +/* +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. +*/ + +#ifndef BT_DISCRETE_DYNAMICS_WORLD_H +#define BT_DISCRETE_DYNAMICS_WORLD_H + +#include "btDynamicsWorld.h" + +class btDispatcher; +class btOverlappingPairCache; +class btConstraintSolver; +class btSimulationIslandManager; +class btTypedConstraint; +#include "../ConstraintSolver/btContactSolverInfo.h" + +class btRaycastVehicle; +class btIDebugDraw; +#include "../../LinearMath/btAlignedObjectArray.h" + + +///btDiscreteDynamicsWorld provides discrete rigid body simulation +///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController +class btDiscreteDynamicsWorld : public btDynamicsWorld +{ +protected: + + btConstraintSolver* m_constraintSolver; + + btSimulationIslandManager* m_islandManager; + + btAlignedObjectArray m_constraints; + + btIDebugDraw* m_debugDrawer; + + btVector3 m_gravity; + + //for variable timesteps + btScalar m_localTime; + //for variable timesteps + + bool m_ownsIslandManager; + bool m_ownsConstraintSolver; + + btContactSolverInfo m_solverInfo; + + + btAlignedObjectArray m_vehicles; + + int m_profileTimings; + + void predictUnconstraintMotion(btScalar timeStep); + + void integrateTransforms(btScalar timeStep); + + void calculateSimulationIslands(); + + void solveConstraints(btContactSolverInfo& solverInfo); + + void updateActivationState(btScalar timeStep); + + void updateVehicles(btScalar timeStep); + + void startProfiling(btScalar timeStep); + + virtual void internalSingleStepSimulation( btScalar timeStep); + + void synchronizeMotionStates(); + + void saveKinematicState(btScalar timeStep); + + void debugDrawSphere(btScalar radius, const btTransform& transform, const btVector3& color); + +public: + + + ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those + btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); + + virtual ~btDiscreteDynamicsWorld(); + + ///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's + virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); + + virtual void updateAabbs(); + + void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false); + + void removeConstraint(btTypedConstraint* constraint); + + void addVehicle(btRaycastVehicle* vehicle); + + void removeVehicle(btRaycastVehicle* vehicle); + + btSimulationIslandManager* getSimulationIslandManager() + { + return m_islandManager; + } + + const btSimulationIslandManager* getSimulationIslandManager() const + { + return m_islandManager; + } + + btCollisionWorld* getCollisionWorld() + { + return this; + } + + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) + { + m_debugDrawer = debugDrawer; + } + + virtual btIDebugDraw* getDebugDrawer() + { + return m_debugDrawer; + } + + virtual void setGravity(const btVector3& gravity); + + virtual void addRigidBody(btRigidBody* body); + + virtual void addRigidBody(btRigidBody* body, short group, short mask); + + virtual void removeRigidBody(btRigidBody* body); + + void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color); + + virtual void setConstraintSolver(btConstraintSolver* solver); + + virtual int getNumConstraints() const; + + virtual btTypedConstraint* getConstraint(int index) ; + + virtual const btTypedConstraint* getConstraint(int index) const; + + btContactSolverInfo& getSolverInfo() + { + return m_solverInfo; + } + + +}; + +#endif //BT_DISCRETE_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h new file mode 100644 index 00000000000..65b63fad4b5 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -0,0 +1,78 @@ +/* +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. +*/ + +#ifndef BT_DYNAMICS_WORLD_H +#define BT_DYNAMICS_WORLD_H + +#include "../../BulletCollision/CollisionDispatch/btCollisionWorld.h" +class btTypedConstraint; +class btRaycastVehicle; +class btConstraintSolver; + + +///btDynamicsWorld is the baseclass for several dynamics implementation, basic, discrete, parallel, and continuous +class btDynamicsWorld : public btCollisionWorld +{ + public: + + + btDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache) + :btCollisionWorld(dispatcher,pairCache) + { + } + + virtual ~btDynamicsWorld() + { + } + + ///stepSimulation proceeds the simulation over timeStep units + ///if maxSubSteps > 0, it will interpolate time steps + virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0; + + virtual void updateAabbs() = 0; + + virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) { (void)constraint;}; + + virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;}; + + virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}; + + virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}; + + + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) = 0; + + virtual btIDebugDraw* getDebugDrawer() = 0; + + //once a rigidbody is added to the dynamics world, it will get this gravity assigned + //existing rigidbodies in the world get gravity assigned too, during this method + virtual void setGravity(const btVector3& gravity) = 0; + + virtual void addRigidBody(btRigidBody* body) = 0; + + virtual void removeRigidBody(btRigidBody* body) = 0; + + virtual void setConstraintSolver(btConstraintSolver* solver) = 0; + + virtual int getNumConstraints() const { return 0; } + + virtual btTypedConstraint* getConstraint(int index) { (void)index; return 0; } + + virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; } + +}; + +#endif //BT_DYNAMICS_WORLD_H + diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp new file mode 100644 index 00000000000..9ed3579d89c --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -0,0 +1,345 @@ +/* +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. +*/ + +#include "btRigidBody.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "LinearMath/btMinMax.h" +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btMotionState.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" + +btScalar gLinearAirDamping = btScalar(1.); +//'temporarily' global variables +btScalar gDeactivationTime = btScalar(2.); +bool gDisableDeactivation = false; + +btScalar gLinearSleepingThreshold = btScalar(0.8); +btScalar gAngularSleepingThreshold = btScalar(1.0); +static int uniqueId = 0; + +btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) +: + m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), + m_angularFactor(btScalar(1.)), + m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_linearDamping(btScalar(0.)), + m_angularDamping(btScalar(0.5)), + m_optionalMotionState(motionState), + m_contactSolverType(0), + m_frictionSolverType(0) +{ + + if (motionState) + { + motionState->getWorldTransform(m_worldTransform); + } else + { + m_worldTransform = btTransform::getIdentity(); + } + + m_interpolationWorldTransform = m_worldTransform; + m_interpolationLinearVelocity.setValue(0,0,0); + m_interpolationAngularVelocity.setValue(0,0,0); + + //moved to btCollisionObject + m_friction = friction; + m_restitution = restitution; + + m_collisionShape = collisionShape; + m_debugBodyId = uniqueId++; + + //m_internalOwner is to allow upcasting from collision object to rigid body + m_internalOwner = this; + + setMassProps(mass, localInertia); + setDamping(linearDamping, angularDamping); + updateInertiaTensor(); + +} + +#ifdef OBSOLETE_MOTIONSTATE_LESS +btRigidBody::btRigidBody( btScalar mass,const btTransform& worldTransform,btCollisionShape* collisionShape,const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) +: + m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), + m_linearDamping(btScalar(0.)), + m_angularDamping(btScalar(0.5)), + m_optionalMotionState(0), + m_contactSolverType(0), + m_frictionSolverType(0) +{ + + m_worldTransform = worldTransform; + m_interpolationWorldTransform = m_worldTransform; + m_interpolationLinearVelocity.setValue(0,0,0); + m_interpolationAngularVelocity.setValue(0,0,0); + + //moved to btCollisionObject + m_friction = friction; + m_restitution = restitution; + + m_collisionShape = collisionShape; + m_debugBodyId = uniqueId++; + + //m_internalOwner is to allow upcasting from collision object to rigid body + m_internalOwner = this; + + setMassProps(mass, localInertia); + setDamping(linearDamping, angularDamping); + updateInertiaTensor(); + +} + +#endif //OBSOLETE_MOTIONSTATE_LESS + + + + +//#define EXPERIMENTAL_JITTER_REMOVAL 1 +#ifdef EXPERIMENTAL_JITTER_REMOVAL +//Bullet 2.20b has experimental damping code to reduce jitter just before objects fall asleep/deactivate +//doesn't work very well yet (value 0 disabled this damping) +//note there this influences deactivation thresholds! +btScalar gClippedAngvelThresholdSqr = btScalar(0.01); +btScalar gClippedLinearThresholdSqr = btScalar(0.01); +#endif //EXPERIMENTAL_JITTER_REMOVAL + +btScalar gJitterVelocityDampingFactor = btScalar(0.7); + +void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform) +{ + +#ifdef EXPERIMENTAL_JITTER_REMOVAL + //if (wantsSleeping()) + { + //clip to avoid jitter + if ((m_angularVelocity.length2() < gClippedAngvelThresholdSqr) && + (m_linearVelocity.length2() < gClippedLinearThresholdSqr)) + { + m_angularVelocity *= gJitterVelocityDampingFactor; + m_linearVelocity *= gJitterVelocityDampingFactor; + } + } + +#endif //EXPERIMENTAL_JITTER_REMOVAL + + btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform); +} + +void btRigidBody::saveKinematicState(btScalar timeStep) +{ + //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities + if (timeStep != btScalar(0.)) + { + //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform + if (getMotionState()) + getMotionState()->getWorldTransform(m_worldTransform); + btVector3 linVel,angVel; + + btTransformUtil::calculateVelocity(m_interpolationWorldTransform,m_worldTransform,timeStep,m_linearVelocity,m_angularVelocity); + m_interpolationLinearVelocity = m_linearVelocity; + m_interpolationAngularVelocity = m_angularVelocity; + m_interpolationWorldTransform = m_worldTransform; + //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ()); + } +} + +void btRigidBody::getAabb(btVector3& aabbMin,btVector3& aabbMax) const +{ + getCollisionShape()->getAabb(m_worldTransform,aabbMin,aabbMax); +} + + + + +void btRigidBody::setGravity(const btVector3& acceleration) +{ + if (m_inverseMass != btScalar(0.0)) + { + m_gravity = acceleration * (btScalar(1.0) / m_inverseMass); + } +} + + + + + + +void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping) +{ + m_linearDamping = GEN_clamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + m_angularDamping = GEN_clamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); +} + + + +#include + + +void btRigidBody::applyForces(btScalar step) +{ + if (isStaticOrKinematicObject()) + return; + + applyCentralForce(m_gravity); + + m_linearVelocity *= GEN_clamped((btScalar(1.) - step * gLinearAirDamping * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + m_angularVelocity *= GEN_clamped((btScalar(1.) - step * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + +#define FORCE_VELOCITY_DAMPING 1 +#ifdef FORCE_VELOCITY_DAMPING + btScalar speed = m_linearVelocity.length(); + if (speed < m_linearDamping) + { + btScalar dampVel = btScalar(0.005); + if (speed > dampVel) + { + btVector3 dir = m_linearVelocity.normalized(); + m_linearVelocity -= dir * dampVel; + } else + { + m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + + btScalar angSpeed = m_angularVelocity.length(); + if (angSpeed < m_angularDamping) + { + btScalar angDampVel = btScalar(0.005); + if (angSpeed > angDampVel) + { + btVector3 dir = m_angularVelocity.normalized(); + m_angularVelocity -= dir * angDampVel; + } else + { + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } +#endif //FORCE_VELOCITY_DAMPING + +} + +void btRigidBody::proceedToTransform(const btTransform& newTrans) +{ + setCenterOfMassTransform( newTrans ); +} + + +void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia) +{ + if (mass == btScalar(0.)) + { + m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT; + m_inverseMass = btScalar(0.); + } else + { + m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT); + m_inverseMass = btScalar(1.0) / mass; + } + + m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x(): btScalar(0.0), + inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y(): btScalar(0.0), + inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z(): btScalar(0.0)); + +} + + + +void btRigidBody::updateInertiaTensor() +{ + m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose(); +} + + +void btRigidBody::integrateVelocities(btScalar step) +{ + if (isStaticOrKinematicObject()) + return; + + m_linearVelocity += m_totalForce * (m_inverseMass * step); + m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step; + +#define MAX_ANGVEL SIMD_HALF_PI + /// clamp angular velocity. collision calculations will fail on higher angular velocities + btScalar angvel = m_angularVelocity.length(); + if (angvel*step > MAX_ANGVEL) + { + m_angularVelocity *= (MAX_ANGVEL/step) /angvel; + } + + clearForces(); +} + +btQuaternion btRigidBody::getOrientation() const +{ + btQuaternion orn; + m_worldTransform.getBasis().getRotation(orn); + return orn; +} + + +void btRigidBody::setCenterOfMassTransform(const btTransform& xform) +{ + + if (isStaticOrKinematicObject()) + { + m_interpolationWorldTransform = m_worldTransform; + } else + { + m_interpolationWorldTransform = xform; + } + m_interpolationLinearVelocity = getLinearVelocity(); + m_interpolationAngularVelocity = getAngularVelocity(); + m_worldTransform = xform; + updateInertiaTensor(); +} + + +bool btRigidBody::checkCollideWithOverride(btCollisionObject* co) +{ + btRigidBody* otherRb = btRigidBody::upcast(co); + if (!otherRb) + return true; + + for (int i = 0; i < m_constraintRefs.size(); ++i) + { + btTypedConstraint* c = m_constraintRefs[i]; + if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb) + return false; + } + + return true; +} + +void btRigidBody::addConstraintRef(btTypedConstraint* c) +{ + int index = m_constraintRefs.findLinearSearch(c); + if (index == m_constraintRefs.size()) + m_constraintRefs.push_back(c); + + m_checkCollideWith = true; +} + +void btRigidBody::removeConstraintRef(btTypedConstraint* c) +{ + m_constraintRefs.remove(c); + m_checkCollideWith = m_constraintRefs.size() > 0; +} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h new file mode 100644 index 00000000000..0707595d48e --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h @@ -0,0 +1,357 @@ +/* +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. +*/ + +#ifndef RIGIDBODY_H +#define RIGIDBODY_H + +#include "../../LinearMath/btAlignedObjectArray.h" +#include "../../LinearMath/btPoint3.h" +#include "../../LinearMath/btTransform.h" +#include "../../BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "../../BulletCollision/CollisionDispatch/btCollisionObject.h" + +class btCollisionShape; +class btMotionState; +class btTypedConstraint; + + +extern btScalar gLinearAirDamping; + +extern btScalar gDeactivationTime; +extern bool gDisableDeactivation; +extern btScalar gLinearSleepingThreshold; +extern btScalar gAngularSleepingThreshold; + + +/// btRigidBody class for btRigidBody Dynamics +/// +class btRigidBody : public btCollisionObject +{ + + btMatrix3x3 m_invInertiaTensorWorld; + btVector3 m_linearVelocity; + btVector3 m_angularVelocity; + btScalar m_inverseMass; + btScalar m_angularFactor; + + btVector3 m_gravity; + btVector3 m_invInertiaLocal; + btVector3 m_totalForce; + btVector3 m_totalTorque; + + btScalar m_linearDamping; + btScalar m_angularDamping; + + + //m_optionalMotionState allows to automatic synchronize the world transform for active objects + btMotionState* m_optionalMotionState; + + //keep track of typed constraints referencing this rigid body + btAlignedObjectArray m_constraintRefs; + +public: + +#ifdef OBSOLETE_MOTIONSTATE_LESS + //not supported, please use btMotionState + btRigidBody(btScalar mass, const btTransform& worldTransform, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); +#endif //OBSOLETE_MOTIONSTATE_LESS + + btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); + + void proceedToTransform(const btTransform& newTrans); + + ///to keep collision detection and dynamics separate we don't store a rigidbody pointer + ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast + static const btRigidBody* upcast(const btCollisionObject* colObj) + { + return (const btRigidBody*)colObj->getInternalOwner(); + } + static btRigidBody* upcast(btCollisionObject* colObj) + { + return (btRigidBody*)colObj->getInternalOwner(); + } + + /// continuous collision detection needs prediction + void predictIntegratedTransform(btScalar step, btTransform& predictedTransform) ; + + void saveKinematicState(btScalar step); + + + void applyForces(btScalar step); + + void setGravity(const btVector3& acceleration); + + const btVector3& getGravity() const + { + return m_gravity; + } + + void setDamping(btScalar lin_damping, btScalar ang_damping); + + inline const btCollisionShape* getCollisionShape() const { + return m_collisionShape; + } + + inline btCollisionShape* getCollisionShape() { + return m_collisionShape; + } + + void setMassProps(btScalar mass, const btVector3& inertia); + + btScalar getInvMass() const { return m_inverseMass; } + const btMatrix3x3& getInvInertiaTensorWorld() const { + return m_invInertiaTensorWorld; + } + + void integrateVelocities(btScalar step); + + void setCenterOfMassTransform(const btTransform& xform); + + void applyCentralForce(const btVector3& force) + { + m_totalForce += force; + } + + const btVector3& getInvInertiaDiagLocal() + { + return m_invInertiaLocal; + }; + + void setInvInertiaDiagLocal(const btVector3& diagInvInertia) + { + m_invInertiaLocal = diagInvInertia; + } + + void applyTorque(const btVector3& torque) + { + m_totalTorque += torque; + } + + void applyForce(const btVector3& force, const btVector3& rel_pos) + { + applyCentralForce(force); + applyTorque(rel_pos.cross(force)); + } + + void applyCentralImpulse(const btVector3& impulse) + { + m_linearVelocity += impulse * m_inverseMass; + } + + void applyTorqueImpulse(const btVector3& torque) + { + m_angularVelocity += m_invInertiaTensorWorld * torque; + } + + void applyImpulse(const btVector3& impulse, const btVector3& rel_pos) + { + if (m_inverseMass != btScalar(0.)) + { + applyCentralImpulse(impulse); + if (m_angularFactor) + { + applyTorqueImpulse(rel_pos.cross(impulse)*m_angularFactor); + } + } + } + + //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position + inline void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + { + if (m_inverseMass != btScalar(0.)) + { + m_linearVelocity += linearComponent*impulseMagnitude; + if (m_angularFactor) + { + m_angularVelocity += angularComponent*impulseMagnitude*m_angularFactor; + } + } + } + + void clearForces() + { + m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + } + + void updateInertiaTensor(); + + const btPoint3& getCenterOfMassPosition() const { + return m_worldTransform.getOrigin(); + } + btQuaternion getOrientation() const; + + const btTransform& getCenterOfMassTransform() const { + return m_worldTransform; + } + const btVector3& getLinearVelocity() const { + return m_linearVelocity; + } + const btVector3& getAngularVelocity() const { + return m_angularVelocity; + } + + + inline void setLinearVelocity(const btVector3& lin_vel) + { + assert (m_collisionFlags != btCollisionObject::CF_STATIC_OBJECT); + m_linearVelocity = lin_vel; + } + + inline void setAngularVelocity(const btVector3& ang_vel) { + assert (m_collisionFlags != btCollisionObject::CF_STATIC_OBJECT); + { + m_angularVelocity = ang_vel; + } + } + + btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const + { + //we also calculate lin/ang velocity for kinematic objects + return m_linearVelocity + m_angularVelocity.cross(rel_pos); + + //for kinematic objects, we could also use use: + // return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep; + } + + void translate(const btVector3& v) + { + m_worldTransform.getOrigin() += v; + } + + + void getAabb(btVector3& aabbMin,btVector3& aabbMax) const; + + + + + + inline btScalar computeImpulseDenominator(const btPoint3& pos, const btVector3& normal) const + { + btVector3 r0 = pos - getCenterOfMassPosition(); + + btVector3 c0 = (r0).cross(normal); + + btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0); + + return m_inverseMass + normal.dot(vec); + + } + + inline btScalar computeAngularImpulseDenominator(const btVector3& axis) const + { + btVector3 vec = axis * getInvInertiaTensorWorld(); + return axis.dot(vec); + } + + inline void updateDeactivation(btScalar timeStep) + { + if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION)) + return; + + if ((getLinearVelocity().length2() < gLinearSleepingThreshold*gLinearSleepingThreshold) && + (getAngularVelocity().length2() < gAngularSleepingThreshold*gAngularSleepingThreshold)) + { + m_deactivationTime += timeStep; + } else + { + m_deactivationTime=btScalar(0.); + setActivationState(0); + } + + } + + inline bool wantsSleeping() + { + + if (getActivationState() == DISABLE_DEACTIVATION) + return false; + + //disable deactivation + if (gDisableDeactivation || (gDeactivationTime == btScalar(0.))) + return false; + + if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION)) + return true; + + if (m_deactivationTime> gDeactivationTime) + { + return true; + } + return false; + } + + + + const btBroadphaseProxy* getBroadphaseProxy() const + { + return m_broadphaseHandle; + } + btBroadphaseProxy* getBroadphaseProxy() + { + return m_broadphaseHandle; + } + void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy) + { + m_broadphaseHandle = broadphaseProxy; + } + + //btMotionState allows to automatic synchronize the world transform for active objects + btMotionState* getMotionState() + { + return m_optionalMotionState; + } + const btMotionState* getMotionState() const + { + return m_optionalMotionState; + } + void setMotionState(btMotionState* motionState) + { + m_optionalMotionState = motionState; + if (m_optionalMotionState) + motionState->getWorldTransform(m_worldTransform); + } + + //for experimental overriding of friction/contact solver func + int m_contactSolverType; + int m_frictionSolverType; + + void setAngularFactor(btScalar angFac) + { + m_angularFactor = angFac; + } + btScalar getAngularFactor() const + { + return m_angularFactor; + } + + //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase? + bool isInWorld() const + { + return (getBroadphaseProxy() != 0); + } + + virtual bool checkCollideWithOverride(btCollisionObject* co); + + void addConstraintRef(btTypedConstraint* c); + void removeConstraintRef(btTypedConstraint* c); + + int m_debugBodyId; +}; + + + +#endif + diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp new file mode 100644 index 00000000000..4ebcb8e7517 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp @@ -0,0 +1,211 @@ +/* +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. +*/ + +#include "btSimpleDynamicsWorld.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + + +/* + Make sure this dummy function never changes so that it + can be used by probes that are checking whether the + library is actually installed. +*/ +extern "C" void btBulletDynamicsProbe () {} + + + + +btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) +:btDynamicsWorld(dispatcher,pairCache), +m_constraintSolver(constraintSolver), +m_ownsConstraintSolver(false), +m_debugDrawer(0), +m_gravity(0,0,-10) +{ + +} + + +btSimpleDynamicsWorld::~btSimpleDynamicsWorld() +{ + if (m_ownsConstraintSolver) + delete m_constraintSolver; +} + +int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) +{ + (void)fixedTimeStep; + (void)maxSubSteps; + + + ///apply gravity, predict motion + predictUnconstraintMotion(timeStep); + + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + dispatchInfo.m_timeStep = timeStep; + dispatchInfo.m_stepCount = 0; + dispatchInfo.m_debugDraw = getDebugDrawer(); + + ///perform collision detection + performDiscreteCollisionDetection(); + + ///solve contact constraints + int numManifolds = m_dispatcher1->getNumManifolds(); + if (numManifolds) + { + btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer(); + + btContactSolverInfo infoGlobal; + infoGlobal.m_timeStep = timeStep; + + m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc); + } + + ///integrate transforms + integrateTransforms(timeStep); + + updateAabbs(); + + synchronizeMotionStates(); + + return 1; + +} + + +void btSimpleDynamicsWorld::setGravity(const btVector3& gravity) +{ + m_gravity = gravity; + for ( int i=0;isetGravity(gravity); + } + } +} + +void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body) +{ + removeCollisionObject(body); +} + +void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body) +{ + body->setGravity(m_gravity); + + if (body->getCollisionShape()) + { + addCollisionObject(body); + } +} + +void btSimpleDynamicsWorld::updateAabbs() +{ + btTransform predictedTrans; + for ( int i=0;iisActive() && (!body->isStaticObject())) + { + btPoint3 minAabb,maxAabb; + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + btBroadphaseInterface* bp = getBroadphase(); + bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb); + } + } + } +} + +void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep) +{ + btTransform predictedTrans; + for ( int i=0;iisActive() && (!body->isStaticObject())) + { + body->predictIntegratedTransform(timeStep, predictedTrans); + body->proceedToTransform( predictedTrans); + } + } + } +} + + + +void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + for ( int i=0;iisStaticObject()) + { + if (body->isActive()) + { + body->applyForces( timeStep); + body->integrateVelocities( timeStep); + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); + } + } + } + } +} + + +void btSimpleDynamicsWorld::synchronizeMotionStates() +{ + //todo: iterate over awake simulation islands! + for ( int i=0;igetMotionState()) + { + if (body->getActivationState() != ISLAND_SLEEPING) + { + body->getMotionState()->setWorldTransform(body->getWorldTransform()); + } + } + } + +} + + +void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) +{ + if (m_ownsConstraintSolver) + { + delete m_constraintSolver; + } + m_ownsConstraintSolver = false; + m_constraintSolver = solver; +} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h new file mode 100644 index 00000000000..25f4ccd8e68 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h @@ -0,0 +1,82 @@ +/* +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. +*/ + +#ifndef BT_SIMPLE_DYNAMICS_WORLD_H +#define BT_SIMPLE_DYNAMICS_WORLD_H + +#include "btDynamicsWorld.h" + +class btDispatcher; +class btOverlappingPairCache; +class btConstraintSolver; + +///btSimpleDynamicsWorld demonstrates very basic usage of Bullet rigid body dynamics +///It can be used for basic simulations, and as a starting point for porting Bullet +///btSimpleDynamicsWorld lacks object deactivation, island management and other concepts. +///For more complicated simulations, btDiscreteDynamicsWorld and btContinuousDynamicsWorld are recommended +///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController +class btSimpleDynamicsWorld : public btDynamicsWorld +{ +protected: + + btConstraintSolver* m_constraintSolver; + + bool m_ownsConstraintSolver; + + btIDebugDraw* m_debugDrawer; + + void predictUnconstraintMotion(btScalar timeStep); + + void integrateTransforms(btScalar timeStep); + + btVector3 m_gravity; + +public: + + + + ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver + btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); + + virtual ~btSimpleDynamicsWorld(); + + ///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead + virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); + + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) + { + m_debugDrawer = debugDrawer; + }; + + virtual btIDebugDraw* getDebugDrawer() + { + return m_debugDrawer; + } + + virtual void setGravity(const btVector3& gravity); + + virtual void addRigidBody(btRigidBody* body); + + virtual void removeRigidBody(btRigidBody* body); + + virtual void updateAabbs(); + + void synchronizeMotionStates(); + + virtual void setConstraintSolver(btConstraintSolver* solver); + +}; + +#endif //BT_SIMPLE_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp new file mode 100644 index 00000000000..d53de7f3687 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp @@ -0,0 +1,733 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ + +#include "LinearMath/btVector3.h" +#include "btRaycastVehicle.h" + +#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h" +#include "BulletDynamics/ConstraintSolver/btJacobianEntry.h" +#include "LinearMath/btQuaternion.h" +#include "BulletDynamics/Dynamics/btDynamicsWorld.h" +#include "btVehicleRaycaster.h" +#include "btWheelInfo.h" +#include "LinearMath/btMinMax.h" + + +#include "BulletDynamics/ConstraintSolver/btContactConstraint.h" + + + +static btRigidBody s_fixedObject( 0,0,0); + +btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ) +:m_vehicleRaycaster(raycaster), +m_pitchControl(btScalar(0.)) +{ + m_chassisBody = chassis; + m_indexRightAxis = 0; + m_indexUpAxis = 2; + m_indexForwardAxis = 1; + defaultInit(tuning); +} + + +void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning) +{ + (void)tuning; + m_currentVehicleSpeedKmHour = btScalar(0.); + m_steeringValue = btScalar(0.); + +} + + + +btRaycastVehicle::~btRaycastVehicle() +{ +} + + +// +// basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed +// +btWheelInfo& btRaycastVehicle::addWheel( const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel) +{ + + btWheelInfoConstructionInfo ci; + + ci.m_chassisConnectionCS = connectionPointCS; + ci.m_wheelDirectionCS = wheelDirectionCS0; + ci.m_wheelAxleCS = wheelAxleCS; + ci.m_suspensionRestLength = suspensionRestLength; + ci.m_wheelRadius = wheelRadius; + ci.m_suspensionStiffness = tuning.m_suspensionStiffness; + ci.m_wheelsDampingCompression = tuning.m_suspensionCompression; + ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping; + ci.m_frictionSlip = tuning.m_frictionSlip; + ci.m_bIsFrontWheel = isFrontWheel; + ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm; + + m_wheelInfo.push_back( btWheelInfo(ci)); + + btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1]; + + updateWheelTransformsWS( wheel , false ); + updateWheelTransform(getNumWheels()-1,false); + return wheel; +} + + + + +const btTransform& btRaycastVehicle::getWheelTransformWS( int wheelIndex ) const +{ + assert(wheelIndex < getNumWheels()); + const btWheelInfo& wheel = m_wheelInfo[wheelIndex]; + return wheel.m_worldTransform; + +} + +void btRaycastVehicle::updateWheelTransform( int wheelIndex , bool interpolatedTransform) +{ + + btWheelInfo& wheel = m_wheelInfo[ wheelIndex ]; + updateWheelTransformsWS(wheel,interpolatedTransform); + btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS; + const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS; + btVector3 fwd = up.cross(right); + fwd = fwd.normalize(); +// up = right.cross(fwd); +// up.normalize(); + + //rotate around steering over de wheelAxleWS + btScalar steering = wheel.m_steering; + + btQuaternion steeringOrn(up,steering);//wheel.m_steering); + btMatrix3x3 steeringMat(steeringOrn); + + btQuaternion rotatingOrn(right,-wheel.m_rotation); + btMatrix3x3 rotatingMat(rotatingOrn); + + btMatrix3x3 basis2( + right[0],fwd[0],up[0], + right[1],fwd[1],up[1], + right[2],fwd[2],up[2] + ); + + wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2); + wheel.m_worldTransform.setOrigin( + wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength + ); +} + +void btRaycastVehicle::resetSuspension() +{ + + int i; + for (i=0;igetMotionState())) + { + getRigidBody()->getMotionState()->getWorldTransform(chassisTrans); + } + + wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS ); + wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() * wheel.m_wheelDirectionCS ; + wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS; +} + +btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel) +{ + updateWheelTransformsWS( wheel,false); + + + btScalar depth = -1; + + btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius; + + btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen); + const btVector3& source = wheel.m_raycastInfo.m_hardPointWS; + wheel.m_raycastInfo.m_contactPointWS = source + rayvector; + const btVector3& target = wheel.m_raycastInfo.m_contactPointWS; + + btScalar param = btScalar(0.); + + btVehicleRaycaster::btVehicleRaycasterResult rayResults; + + assert(m_vehicleRaycaster); + + void* object = m_vehicleRaycaster->castRay(source,target,rayResults); + + wheel.m_raycastInfo.m_groundObject = 0; + + if (object) + { + param = rayResults.m_distFraction; + depth = raylen * rayResults.m_distFraction; + wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld; + wheel.m_raycastInfo.m_isInContact = true; + + wheel.m_raycastInfo.m_groundObject = &s_fixedObject;//todo for driving on dynamic/movable objects!; + //wheel.m_raycastInfo.m_groundObject = object; + + + btScalar hitDistance = param*raylen; + wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius; + //clamp on max suspension travel + + btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01); + btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01); + if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength) + { + wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength; + } + if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength) + { + wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength; + } + + wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld; + + btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS ); + + btVector3 chassis_velocity_at_contactPoint; + btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition(); + + chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos); + + btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); + + if ( denominator >= btScalar(-0.1)) + { + wheel.m_suspensionRelativeVelocity = btScalar(0.0); + wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1); + } + else + { + btScalar inv = btScalar(-1.) / denominator; + wheel.m_suspensionRelativeVelocity = projVel * inv; + wheel.m_clippedInvContactDotSuspension = inv; + } + + } else + { + //put wheel info as in rest position + wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength(); + wheel.m_suspensionRelativeVelocity = btScalar(0.0); + wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS; + wheel.m_clippedInvContactDotSuspension = btScalar(1.0); + } + + return depth; +} + + +const btTransform& btRaycastVehicle::getChassisWorldTransform() const +{ + /*if (getRigidBody()->getMotionState()) + { + btTransform chassisWorldTrans; + getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans); + return chassisWorldTrans; + } + */ + + + return getRigidBody()->getCenterOfMassTransform(); +} + + +void btRaycastVehicle::updateVehicle( btScalar step ) +{ + { + for (int i=0;igetLinearVelocity().length(); + + const btTransform& chassisTrans = getChassisWorldTransform(); + + btVector3 forwardW ( + chassisTrans.getBasis()[0][m_indexForwardAxis], + chassisTrans.getBasis()[1][m_indexForwardAxis], + chassisTrans.getBasis()[2][m_indexForwardAxis]); + + if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.)) + { + m_currentVehicleSpeedKmHour *= btScalar(-1.); + } + + // + // simulate suspension + // + + int i=0; + for (i=0;i gMaxSuspensionForce) + { + suspensionForce = gMaxSuspensionForce; + } + btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step; + btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition(); + + getRigidBody()->applyImpulse(impulse, relpos); + + } + + + + updateFriction( step); + + + for (i=0;igetCenterOfMassPosition(); + btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos ); + + if (wheel.m_raycastInfo.m_isInContact) + { + const btTransform& chassisWorldTransform = getChassisWorldTransform(); + + btVector3 fwd ( + chassisWorldTransform.getBasis()[0][m_indexForwardAxis], + chassisWorldTransform.getBasis()[1][m_indexForwardAxis], + chassisWorldTransform.getBasis()[2][m_indexForwardAxis]); + + btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS); + fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj; + + btScalar proj2 = fwd.dot(vel); + + wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius); + wheel.m_rotation += wheel.m_deltaRotation; + + } else + { + wheel.m_rotation += wheel.m_deltaRotation; + } + + wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact + + } + + + +} + + +void btRaycastVehicle::setSteeringValue(btScalar steering,int wheel) +{ + assert(wheel>=0 && wheel < getNumWheels()); + + btWheelInfo& wheelInfo = getWheelInfo(wheel); + wheelInfo.m_steering = steering; +} + + + +btScalar btRaycastVehicle::getSteeringValue(int wheel) const +{ + return getWheelInfo(wheel).m_steering; +} + + +void btRaycastVehicle::applyEngineForce(btScalar force, int wheel) +{ + assert(wheel>=0 && wheel < getNumWheels()); + btWheelInfo& wheelInfo = getWheelInfo(wheel); + wheelInfo.m_engineForce = force; +} + + +const btWheelInfo& btRaycastVehicle::getWheelInfo(int index) const +{ + btAssert((index >= 0) && (index < getNumWheels())); + + return m_wheelInfo[index]; +} + +btWheelInfo& btRaycastVehicle::getWheelInfo(int index) +{ + btAssert((index >= 0) && (index < getNumWheels())); + + return m_wheelInfo[index]; +} + +void btRaycastVehicle::setBrake(btScalar brake,int wheelIndex) +{ + btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels())); + getWheelInfo(wheelIndex).m_brake = brake; +} + + +void btRaycastVehicle::updateSuspension(btScalar deltaTime) +{ + (void)deltaTime; + + btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass(); + + for (int w_it=0; w_itcomputeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); + btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); + btScalar relaxation = 1.f; + m_jacDiagABInv = relaxation/(denom0+denom1); + } + + + +}; + +btScalar calcRollingFriction(btWheelContactPoint& contactPoint) +{ + + btScalar j1=0.f; + + const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld; + + btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition(); + btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition(); + + btScalar maxImpulse = contactPoint.m_maxImpulse; + + btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel); + + // calculate j that moves us to zero relative velocity + j1 = -vrel * contactPoint.m_jacDiagABInv; + GEN_set_min(j1, maxImpulse); + GEN_set_max(j1, -maxImpulse); + + return j1; +} + + + + +btScalar sideFrictionStiffness2 = btScalar(1.0); +void btRaycastVehicle::updateFriction(btScalar timeStep) +{ + + //calculate the impulse, so that the wheels don't move sidewards + int numWheel = getNumWheels(); + if (!numWheel) + return; + + + btVector3* forwardWS = new btVector3[numWheel]; + btVector3* axle = new btVector3[numWheel]; + btScalar* forwardImpulse = new btScalar[numWheel]; + btScalar* sideImpulse = new btScalar[numWheel]; + + int numWheelsOnGround = 0; + + + //collapse all those loops into one! + for (int i=0;i maximpSquared) + { + sliding = true; + + btScalar factor = maximp / btSqrt(impulseSquared); + + m_wheelInfo[wheel].m_skidInfo *= factor; + } + } + + } + } + + + + + if (sliding) + { + for (int wheel = 0;wheel < getNumWheels(); wheel++) + { + if (sideImpulse[wheel] != btScalar(0.)) + { + if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.)) + { + forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + } + } + } + } + + // apply the impulses + { + for (int wheel = 0;wheelgetCenterOfMassPosition(); + + if (forwardImpulse[wheel] != btScalar(0.)) + { + m_chassisBody->applyImpulse(forwardWS[wheel]*(forwardImpulse[wheel]),rel_pos); + } + if (sideImpulse[wheel] != btScalar(0.)) + { + class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; + + btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - + groundObject->getCenterOfMassPosition(); + + + btVector3 sideImp = axle[wheel] * sideImpulse[wheel]; + + rel_pos[2] *= wheelInfo.m_rollInfluence; + m_chassisBody->applyImpulse(sideImp,rel_pos); + + //apply friction impulse on the ground + groundObject->applyImpulse(-sideImp,rel_pos2); + } + } + } + + delete []forwardWS; + delete [] axle; + delete[]forwardImpulse; + delete[] sideImpulse; +} + + +void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) +{ +// RayResultCallback& resultCallback; + + btCollisionWorld::ClosestRayResultCallback rayCallback(from,to); + + m_dynamicsWorld->rayTest(from, to, rayCallback); + + if (rayCallback.HasHit()) + { + + btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); + if (body) + { + result.m_hitPointInWorld = rayCallback.m_hitPointWorld; + result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld; + result.m_hitNormalInWorld.normalize(); + result.m_distFraction = rayCallback.m_closestHitFraction; + return body; + } + } + return 0; +} diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h new file mode 100644 index 00000000000..f4249599615 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#ifndef RAYCASTVEHICLE_H +#define RAYCASTVEHICLE_H + +#include "../Dynamics/btRigidBody.h" +#include "../ConstraintSolver/btTypedConstraint.h" +#include "btVehicleRaycaster.h" +class btDynamicsWorld; +#include "../../LinearMath/btAlignedObjectArray.h" +#include "btWheelInfo.h" + +class btVehicleTuning; + +///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle. +class btRaycastVehicle : public btTypedConstraint +{ +public: + class btVehicleTuning + { + public: + + btVehicleTuning() + :m_suspensionStiffness(btScalar(5.88)), + m_suspensionCompression(btScalar(0.83)), + m_suspensionDamping(btScalar(0.88)), + m_maxSuspensionTravelCm(btScalar(500.)), + m_frictionSlip(btScalar(10.5)) + { + } + btScalar m_suspensionStiffness; + btScalar m_suspensionCompression; + btScalar m_suspensionDamping; + btScalar m_maxSuspensionTravelCm; + btScalar m_frictionSlip; + + }; +private: + + btScalar m_tau; + btScalar m_damping; + btVehicleRaycaster* m_vehicleRaycaster; + btScalar m_pitchControl; + btScalar m_steeringValue; + btScalar m_currentVehicleSpeedKmHour; + + btRigidBody* m_chassisBody; + + int m_indexRightAxis; + int m_indexUpAxis; + int m_indexForwardAxis; + + void defaultInit(const btVehicleTuning& tuning); + +public: + + //constructor to create a car from an existing rigidbody + btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ); + + virtual ~btRaycastVehicle() ; + + + const btTransform& getChassisWorldTransform() const; + + btScalar rayCast(btWheelInfo& wheel); + + virtual void updateVehicle(btScalar step); + + void resetSuspension(); + + btScalar getSteeringValue(int wheel) const; + + void setSteeringValue(btScalar steering,int wheel); + + + void applyEngineForce(btScalar force, int wheel); + + const btTransform& getWheelTransformWS( int wheelIndex ) const; + + void updateWheelTransform( int wheelIndex, bool interpolatedTransform = true ); + + void setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth); + + btWheelInfo& addWheel( const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS,btScalar suspensionRestLength,btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel); + + inline int getNumWheels() const { + return int (m_wheelInfo.size()); + } + + btAlignedObjectArray m_wheelInfo; + + + const btWheelInfo& getWheelInfo(int index) const; + + btWheelInfo& getWheelInfo(int index); + + void updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform = true); + + + void setBrake(btScalar brake,int wheelIndex); + + void setPitchControl(btScalar pitch) + { + m_pitchControl = pitch; + } + + void updateSuspension(btScalar deltaTime); + + void updateFriction(btScalar timeStep); + + + + inline btRigidBody* getRigidBody() + { + return m_chassisBody; + } + + const btRigidBody* getRigidBody() const + { + return m_chassisBody; + } + + inline int getRightAxis() const + { + return m_indexRightAxis; + } + inline int getUpAxis() const + { + return m_indexUpAxis; + } + + inline int getForwardAxis() const + { + return m_indexForwardAxis; + } + + + ///Worldspace forward vector + btVector3 getForwardVector() const + { + const btTransform& chassisTrans = getChassisWorldTransform(); + + btVector3 forwardW ( + chassisTrans.getBasis()[0][m_indexForwardAxis], + chassisTrans.getBasis()[1][m_indexForwardAxis], + chassisTrans.getBasis()[2][m_indexForwardAxis]); + + return forwardW; + } + + ///Velocity of vehicle (positive if velocity vector has same direction as foward vector) + btScalar getCurrentSpeedKmHour() const + { + return m_currentVehicleSpeedKmHour; + } + + virtual void setCoordinateSystem(int rightIndex,int upIndex,int forwardIndex) + { + m_indexRightAxis = rightIndex; + m_indexUpAxis = upIndex; + m_indexForwardAxis = forwardIndex; + } + + virtual void buildJacobian() + { + //not yet + } + + virtual void solveConstraint(btScalar timeStep) + { + (void)timeStep; + //not yet + } + + +}; + +class btDefaultVehicleRaycaster : public btVehicleRaycaster +{ + btDynamicsWorld* m_dynamicsWorld; +public: + btDefaultVehicleRaycaster(btDynamicsWorld* world) + :m_dynamicsWorld(world) + { + } + + virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result); + +}; + + +#endif //RAYCASTVEHICLE_H + diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h new file mode 100644 index 00000000000..64a47fcaada --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#ifndef VEHICLE_RAYCASTER_H +#define VEHICLE_RAYCASTER_H + +#include "../../LinearMath/btVector3.h" + +/// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting +struct btVehicleRaycaster +{ +virtual ~btVehicleRaycaster() +{ +} + struct btVehicleRaycasterResult + { + btVehicleRaycasterResult() :m_distFraction(btScalar(-1.)){}; + btVector3 m_hitPointInWorld; + btVector3 m_hitNormalInWorld; + btScalar m_distFraction; + }; + + virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) = 0; + +}; + +#endif //VEHICLE_RAYCASTER_H + diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.cpp b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.cpp new file mode 100644 index 00000000000..ef93c16fffc --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#include "btWheelInfo.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" // for pointvelocity + + +btScalar btWheelInfo::getSuspensionRestLength() const +{ + + return m_suspensionRestLength1; + +} + +void btWheelInfo::updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo) +{ + (void)raycastInfo; + + + if (m_raycastInfo.m_isInContact) + + { + btScalar project= m_raycastInfo.m_contactNormalWS.dot( m_raycastInfo.m_wheelDirectionWS ); + btVector3 chassis_velocity_at_contactPoint; + btVector3 relpos = m_raycastInfo.m_contactPointWS - chassis.getCenterOfMassPosition(); + chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint( relpos ); + btScalar projVel = m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); + if ( project >= btScalar(-0.1)) + { + m_suspensionRelativeVelocity = btScalar(0.0); + m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1); + } + else + { + btScalar inv = btScalar(-1.) / project; + m_suspensionRelativeVelocity = projVel * inv; + m_clippedInvContactDotSuspension = inv; + } + + } + + else // Not in contact : position wheel in a nice (rest length) position + { + m_raycastInfo.m_suspensionLength = this->getSuspensionRestLength(); + m_suspensionRelativeVelocity = btScalar(0.0); + m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS; + m_clippedInvContactDotSuspension = btScalar(1.0); + } +} diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h new file mode 100644 index 00000000000..2e349b3fde4 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies. + * Erwin Coumans makes no representations about the suitability + * of this software for any purpose. + * It is provided "as is" without express or implied warranty. +*/ +#ifndef WHEEL_INFO_H +#define WHEEL_INFO_H + +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btTransform.h" + +class btRigidBody; + +struct btWheelInfoConstructionInfo +{ + btVector3 m_chassisConnectionCS; + btVector3 m_wheelDirectionCS; + btVector3 m_wheelAxleCS; + btScalar m_suspensionRestLength; + btScalar m_maxSuspensionTravelCm; + btScalar m_wheelRadius; + + btScalar m_suspensionStiffness; + btScalar m_wheelsDampingCompression; + btScalar m_wheelsDampingRelaxation; + btScalar m_frictionSlip; + bool m_bIsFrontWheel; + +}; + +/// btWheelInfo contains information per wheel about friction and suspension. +struct btWheelInfo +{ + struct RaycastInfo + { + //set by raycaster + btVector3 m_contactNormalWS;//contactnormal + btVector3 m_contactPointWS;//raycast hitpoint + btScalar m_suspensionLength; + btVector3 m_hardPointWS;//raycast starting point + btVector3 m_wheelDirectionWS; //direction in worldspace + btVector3 m_wheelAxleWS; // axle in worldspace + bool m_isInContact; + void* m_groundObject; //could be general void* ptr + }; + + RaycastInfo m_raycastInfo; + + btTransform m_worldTransform; + + btVector3 m_chassisConnectionPointCS; //const + btVector3 m_wheelDirectionCS;//const + btVector3 m_wheelAxleCS; // const or modified by steering + btScalar m_suspensionRestLength1;//const + btScalar m_maxSuspensionTravelCm; + btScalar getSuspensionRestLength() const; + btScalar m_wheelsRadius;//const + btScalar m_suspensionStiffness;//const + btScalar m_wheelsDampingCompression;//const + btScalar m_wheelsDampingRelaxation;//const + btScalar m_frictionSlip; + btScalar m_steering; + btScalar m_rotation; + btScalar m_deltaRotation; + btScalar m_rollInfluence; + + btScalar m_engineForce; + + btScalar m_brake; + + bool m_bIsFrontWheel; + + void* m_clientInfo;//can be used to store pointer to sync transforms... + + btWheelInfo(btWheelInfoConstructionInfo& ci) + + { + + m_suspensionRestLength1 = ci.m_suspensionRestLength; + m_maxSuspensionTravelCm = ci.m_maxSuspensionTravelCm; + + m_wheelsRadius = ci.m_wheelRadius; + m_suspensionStiffness = ci.m_suspensionStiffness; + m_wheelsDampingCompression = ci.m_wheelsDampingCompression; + m_wheelsDampingRelaxation = ci.m_wheelsDampingRelaxation; + m_chassisConnectionPointCS = ci.m_chassisConnectionCS; + m_wheelDirectionCS = ci.m_wheelDirectionCS; + m_wheelAxleCS = ci.m_wheelAxleCS; + m_frictionSlip = ci.m_frictionSlip; + m_steering = btScalar(0.); + m_engineForce = btScalar(0.); + m_rotation = btScalar(0.); + m_deltaRotation = btScalar(0.); + m_brake = btScalar(0.); + m_rollInfluence = btScalar(0.1); + m_bIsFrontWheel = ci.m_bIsFrontWheel; + + } + + void updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo); + + btScalar m_clippedInvContactDotSuspension; + btScalar m_suspensionRelativeVelocity; + //calculated by suspension + btScalar m_wheelsSuspensionForce; + btScalar m_skidInfo; + +}; + +#endif //WHEEL_INFO_H + diff --git a/extern/bullet2/src/CMakeLists.txt b/extern/bullet2/src/CMakeLists.txt new file mode 100644 index 00000000000..0ae1a7ab6ab --- /dev/null +++ b/extern/bullet2/src/CMakeLists.txt @@ -0,0 +1 @@ +SUBDIRS( BulletCollision BulletDynamics LinearMath ) diff --git a/extern/bullet2/src/LinearMath/CMakeLists.txt b/extern/bullet2/src/LinearMath/CMakeLists.txt new file mode 100644 index 00000000000..207eed94a3e --- /dev/null +++ b/extern/bullet2/src/LinearMath/CMakeLists.txt @@ -0,0 +1,10 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src } +) + +ADD_LIBRARY(LibLinearMath +btQuickprof.cpp +btGeometryUtil.cpp +) + diff --git a/extern/bullet2/src/LinearMath/btAabbUtil2.h b/extern/bullet2/src/LinearMath/btAabbUtil2.h new file mode 100644 index 00000000000..429163c8138 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btAabbUtil2.h @@ -0,0 +1,127 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + + +#ifndef AABB_UTIL2 +#define AABB_UTIL2 + +#include "btVector3.h" +#include "btSimdMinMax.h" + + +#define btMin(a,b) ((a < b ? a : b)) +#define btMax(a,b) ((a > b ? a : b)) + + +/// conservative test for overlap between two aabbs +SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1, + const btVector3 &aabbMin2, const btVector3 &aabbMax2) +{ + bool overlap = true; + overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; + overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; + overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; + return overlap; +} + +/// conservative test for overlap between triangle and aabb +SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3 *vertices, + const btVector3 &aabbMin, const btVector3 &aabbMax) +{ + const btVector3 &p1 = vertices[0]; + const btVector3 &p2 = vertices[1]; + const btVector3 &p3 = vertices[2]; + + if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false; + if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false; + + if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false; + if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false; + + if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false; + if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false; + return true; +} + + +SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent) +{ + return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) | + (p.getX() > halfExtent.getX() ? 0x08 : 0x0) | + (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) | + (p.getY() > halfExtent.getY() ? 0x10 : 0x0) | + (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) | + (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0); +} + + +SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, + const btVector3& rayTo, + const btVector3& aabbMin, + const btVector3& aabbMax, + btScalar& param, btVector3& normal) +{ + btVector3 aabbHalfExtent = (aabbMax-aabbMin)* btScalar(0.5); + btVector3 aabbCenter = (aabbMax+aabbMin)* btScalar(0.5); + btVector3 source = rayFrom - aabbCenter; + btVector3 target = rayTo - aabbCenter; + int sourceOutcode = btOutcode(source,aabbHalfExtent); + int targetOutcode = btOutcode(target,aabbHalfExtent); + if ((sourceOutcode & targetOutcode) == 0x0) + { + btScalar lambda_enter = btScalar(0.0); + btScalar lambda_exit = param; + btVector3 r = target - source; + int i; + btScalar normSign = 1; + btVector3 hitNormal(0,0,0); + int bit=1; + + for (int j=0;j<2;j++) + { + for (i = 0; i != 3; ++i) + { + if (sourceOutcode & bit) + { + btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i]; + if (lambda_enter <= lambda) + { + lambda_enter = lambda; + hitNormal.setValue(0,0,0); + hitNormal[i] = normSign; + } + } + else if (targetOutcode & bit) + { + btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i]; + btSetMin(lambda_exit, lambda); + } + bit<<=1; + } + normSign = btScalar(-1.); + } + if (lambda_enter <= lambda_exit) + { + param = lambda_enter; + normal = hitNormal; + return true; + } + } + return false; +} + + +#endif + diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp new file mode 100644 index 00000000000..1f5877fa37e --- /dev/null +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp @@ -0,0 +1,70 @@ +/* +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. +*/ + +#include "btAlignedAllocator.h" + + +#if defined (BT_HAS_ALIGNED_ALOCATOR) + +#include +void* btAlignedAlloc (int size, int alignment) +{ + return _aligned_malloc(size,alignment); +} + +void btAlignedFree (void* ptr) +{ + _aligned_free(ptr); +} + +#else + +#ifdef __CELLOS_LV2__ + +#include + +int numAllocs = 0; +int numFree = 0; + +void* btAlignedAlloc (int size, int alignment) +{ + numAllocs++; + return memalign(alignment, size); +} + +void btAlignedFree (void* ptr) +{ + numFree++; + free(ptr); +} + +#else +///todo +///will add some multi-platform version that works without _aligned_malloc/_aligned_free + +void* btAlignedAlloc (int size, int alignment) +{ + return new char[size]; +} + +void btAlignedFree (void* ptr) +{ + delete [] (char*) ptr; +} +#endif // + +#endif + + diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.h b/extern/bullet2/src/LinearMath/btAlignedAllocator.h new file mode 100644 index 00000000000..07585717f45 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.h @@ -0,0 +1,80 @@ +/* +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. +*/ + +#ifndef BT_ALIGNED_ALLOCATOR +#define BT_ALIGNED_ALLOCATOR + +///we probably replace this with our own aligned memory allocator +///so we replace _aligned_malloc and _aligned_free with our own +///that is better portable and more predictable + +#include "btScalar.h" + +void* btAlignedAlloc (int size, int alignment); + +void btAlignedFree (void* ptr); + + +typedef int size_type; + + +template < typename T , unsigned Alignment > +class btAlignedAllocator { + + typedef btAlignedAllocator< T , Alignment > self_type; + +public: + + //just going down a list: + btAlignedAllocator() {} + /* + btAlignedAllocator( const self_type & ) {} + */ + + template < typename Other > + btAlignedAllocator( const btAlignedAllocator< Other , Alignment > & ) {} + + typedef const T* const_pointer; + typedef const T& const_reference; + typedef T* pointer; + typedef T& reference; + typedef T value_type; + + pointer address ( reference ref ) const { return &ref; } + const_pointer address ( const_reference ref ) const { return &ref; } + pointer allocate ( size_type n , const_pointer * hint = 0 ) { + (void)hint; + return reinterpret_cast< pointer >(btAlignedAlloc( sizeof(value_type) * n , Alignment )); + } + void construct ( pointer ptr , const value_type & value ) { new (ptr) value_type( value ); } + void deallocate( pointer ptr ) { + btAlignedFree( reinterpret_cast< void * >( ptr ) ); + } + void destroy ( pointer ptr ) { ptr->~value_type(); } + + + template < typename O > struct rebind { + typedef btAlignedAllocator< O , Alignment > other; + }; + template < typename O > + self_type & operator=( const btAlignedAllocator< O , Alignment > & ) { return *this; } + + friend bool operator==( const self_type & , const self_type & ) { return true; } +}; + + + +#endif //BT_ALIGNED_ALLOCATOR + diff --git a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h new file mode 100644 index 00000000000..8bef5eb5d06 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h @@ -0,0 +1,367 @@ +/* +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. +*/ + + +#ifndef BT_OBJECT_ARRAY__ +#define BT_OBJECT_ARRAY__ + +#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE +#include "btAlignedAllocator.h" + +///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW +///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors +///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator= +///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and +///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240 + +#define BT_USE_PLACEMENT_NEW 1 +//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in or or otherwise... + +#ifdef BT_USE_MEMCPY +#include +#include +#endif //BT_USE_MEMCPY + +#ifdef BT_USE_PLACEMENT_NEW +#include //for placement new +#endif //BT_USE_PLACEMENT_NEW + + +///btAlignedObjectArray uses a subset of the stl::vector interface for its methods +///It is developed to replace stl::vector to avoid STL alignment issues to add SIMD/SSE data +template +//template +class btAlignedObjectArray +{ + btAlignedAllocator m_allocator; + + int m_size; + int m_capacity; + T* m_data; + + protected: + SIMD_FORCE_INLINE int allocSize(int size) + { + return (size ? size*2 : 1); + } + SIMD_FORCE_INLINE void copy(int start,int end, T* dest) + { + int i; + for (i=start;i size()) + { + reserve(newsize); + } +#ifdef BT_USE_PLACEMENT_NEW + for (int i=curSize;i + void downHeap(T *pArr, int k, int n,L CompareFunc) + { + /* PRE: a[k+1..N] is a heap */ + /* POST: a[k..N] is a heap */ + + T temp = pArr[k - 1]; + /* k has child(s) */ + while (k <= n/2) + { + int child = 2*k; + + if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child])) + { + child++; + } + /* pick larger child */ + if (CompareFunc(temp , pArr[child - 1])) + { + /* move child up */ + pArr[k - 1] = pArr[child - 1]; + k = child; + } + else + { + break; + } + } + pArr[k - 1] = temp; + } /*downHeap*/ + + void swap(int index0,int index1) + { +#ifdef BT_USE_MEMCPY + char temp[sizeof(T)]; + memcpy(temp,&m_data[index0],sizeof(T)); + memcpy(&m_data[index0],&m_data[index1],sizeof(T)); + memcpy(&m_data[index1],temp,sizeof(T)); +#else + T temp = m_data[index0]; + m_data[index0] = m_data[index1]; + m_data[index1] = temp; +#endif //BT_USE_PLACEMENT_NEW + + } + + template + void heapSort(L CompareFunc) + { + /* sort a[0..N-1], N.B. 0 to N-1 */ + int k; + int n = m_size; + for (k = n/2; k > 0; k--) + { + downHeap(m_data, k, n, CompareFunc); + } + + /* a[1..N] is now a heap */ + while ( n>=1 ) + { + swap(0,n-1); /* largest of a[0..n-1] */ + + + n = n - 1; + /* restore a[1..i-1] heap */ + downHeap(m_data, 1, n, CompareFunc); + } + } + + ///non-recursive binary search, assumes sorted array + int findBinarySearch(const T& key) const + { + int first = 0; + int last = size(); + + //assume sorted array + while (first <= last) { + int mid = (first + last) / 2; // compute mid point. + if (key > m_data[mid]) + first = mid + 1; // repeat search in top half. + else if (key < m_data[mid]) + last = mid - 1; // repeat search in bottom half. + else + return mid; // found it. return position ///// + } + return size(); // failed to find key + } + + + int findLinearSearch(const T& key) const + { + int index=size(); + int i; + + for (i=0;i& planeEquations, const btVector3& point, btScalar margin) +{ + int numbrushes = planeEquations.size(); + for (int i=0;ibtScalar(0.)) + { + return false; + } + } + return true; + +} + + +bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray& vertices, btScalar margin) +{ + int numvertices = vertices.size(); + for (int i=0;ibtScalar(0.)) + { + return false; + } + } + return true; +} + +bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations) +{ + int numbrushes = planeEquations.size(); + for (int i=0;i btScalar(0.999)) + { + return false; + } + } + return true; +} + +void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray& vertices, btAlignedObjectArray& planeEquationsOut ) +{ + const int numvertices = vertices.size(); + // brute force: + for (int i=0;i btScalar(0.0001)) + { + planeEquation.normalize(); + if (notExist(planeEquation,planeEquationsOut)) + { + planeEquation[3] = -planeEquation.dot(N1); + + //check if inside, and replace supportingVertexOut if needed + if (areVerticesBehindPlane(planeEquation,vertices,btScalar(0.01))) + { + planeEquationsOut.push_back(planeEquation); + } + } + } + normalSign = btScalar(-1.); + } + + } + } + } + +} + +void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray& planeEquations , btAlignedObjectArray& verticesOut ) +{ + const int numbrushes = planeEquations.size(); + // brute force: + for (int i=0;i btScalar(0.0001) ) && + ( n3n1.length2() > btScalar(0.0001) ) && + ( n1n2.length2() > btScalar(0.0001) ) ) + { + //point P out of 3 plane equations: + + // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 ) + //P = ------------------------------------------------------------------------- + // N1 . ( N2 * N3 ) + + + btScalar quotient = (N1.dot(n2n3)); + if (btFabs(quotient) > btScalar(0.000001)) + { + quotient = btScalar(-1.) / quotient; + n2n3 *= N1[3]; + n3n1 *= N2[3]; + n1n2 *= N3[3]; + btVector3 potentialVertex = n2n3; + potentialVertex += n3n1; + potentialVertex += n1n2; + potentialVertex *= quotient; + + //check if inside, and replace supportingVertexOut if needed + if (isPointInsidePlanes(planeEquations,potentialVertex,btScalar(0.01))) + { + verticesOut.push_back(potentialVertex); + } + } + } + } + } + } +} + diff --git a/extern/bullet2/src/LinearMath/btGeometryUtil.h b/extern/bullet2/src/LinearMath/btGeometryUtil.h new file mode 100644 index 00000000000..766cd75c383 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btGeometryUtil.h @@ -0,0 +1,41 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + +#ifndef BT_GEOMETRY_UTIL_H +#define BT_GEOMETRY_UTIL_H + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +class btGeometryUtil +{ + public: + + + static void getPlaneEquationsFromVertices(btAlignedObjectArray& vertices, btAlignedObjectArray& planeEquationsOut ); + + static void getVerticesFromPlaneEquations(const btAlignedObjectArray& planeEquations , btAlignedObjectArray& verticesOut ); + + static bool isInside(const btAlignedObjectArray& vertices, const btVector3& planeNormal, btScalar margin); + + static bool isPointInsidePlanes(const btAlignedObjectArray& planeEquations, const btVector3& point, btScalar margin); + + static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray& vertices, btScalar margin); + +}; + + +#endif //BT_GEOMETRY_UTIL_H + diff --git a/extern/bullet2/src/LinearMath/btIDebugDraw.h b/extern/bullet2/src/LinearMath/btIDebugDraw.h new file mode 100644 index 00000000000..5f40ca39157 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btIDebugDraw.h @@ -0,0 +1,100 @@ +/* +Copyright (c) 2005 Gino van den Bergen / Erwin Coumans http://continuousphysics.com + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef IDEBUG_DRAW__H +#define IDEBUG_DRAW__H + +#include "btVector3.h" + + +class btIDebugDraw +{ + public: + + enum DebugDrawModes + { + DBG_NoDebug=0, + DBG_DrawWireframe = 1, + DBG_DrawAabb=2, + DBG_DrawFeaturesText=4, + DBG_DrawContactPoints=8, + DBG_NoDeactivation=16, + DBG_NoHelpText = 32, + DBG_DrawText=64, + DBG_ProfileTimings = 128, + DBG_EnableSatComparison = 256, + DBG_DisableBulletLCP = 512, + DBG_EnableCCD = 1024, + DBG_MAX_DEBUG_DRAW_MODE + }; + + virtual ~btIDebugDraw() {}; + + virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0; + + virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0; + + virtual void reportErrorWarning(const char* warningString) = 0; + + virtual void setDebugMode(int debugMode) =0; + + virtual int getDebugMode() const = 0; + + inline void drawAabb(const btVector3& from,const btVector3& to,const btVector3& color) + { + + btVector3 halfExtents = (to-from)* 0.5f; + btVector3 center = (to+from) *0.5f; + int i,j; + + btVector3 edgecoord(1.f,1.f,1.f),pa,pb; + for (i=0;i<4;i++) + { + for (j=0;j<3;j++) + { + pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], + edgecoord[2]*halfExtents[2]); + pa+=center; + + int othercoord = j%3; + edgecoord[othercoord]*=-1.f; + pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1], + edgecoord[2]*halfExtents[2]); + pb+=center; + + drawLine(pa,pb,color); + } + edgecoord = btVector3(-1.f,-1.f,-1.f); + if (i<3) + edgecoord[i]*=-1.f; + } + } +}; + + +#endif //IDEBUG_DRAW__H + diff --git a/extern/bullet2/src/LinearMath/btList.h b/extern/bullet2/src/LinearMath/btList.h new file mode 100644 index 00000000000..c87b47faf2b --- /dev/null +++ b/extern/bullet2/src/LinearMath/btList.h @@ -0,0 +1,73 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + + +#ifndef GEN_LIST_H +#define GEN_LIST_H + +class btGEN_Link { +public: + btGEN_Link() : m_next(0), m_prev(0) {} + btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {} + + btGEN_Link *getNext() const { return m_next; } + btGEN_Link *getPrev() const { return m_prev; } + + bool isHead() const { return m_prev == 0; } + bool isTail() const { return m_next == 0; } + + void insertBefore(btGEN_Link *link) { + m_next = link; + m_prev = link->m_prev; + m_next->m_prev = this; + m_prev->m_next = this; + } + + void insertAfter(btGEN_Link *link) { + m_next = link->m_next; + m_prev = link; + m_next->m_prev = this; + m_prev->m_next = this; + } + + void remove() { + m_next->m_prev = m_prev; + m_prev->m_next = m_next; + } + +private: + btGEN_Link *m_next; + btGEN_Link *m_prev; +}; + +class btGEN_List { +public: + btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {} + + btGEN_Link *getHead() const { return m_head.getNext(); } + btGEN_Link *getTail() const { return m_tail.getPrev(); } + + void addHead(btGEN_Link *link) { link->insertAfter(&m_head); } + void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); } + +private: + btGEN_Link m_head; + btGEN_Link m_tail; +}; + +#endif + + + diff --git a/extern/bullet2/src/LinearMath/btMatrix3x3.h b/extern/bullet2/src/LinearMath/btMatrix3x3.h new file mode 100644 index 00000000000..94f53c3c0a5 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btMatrix3x3.h @@ -0,0 +1,410 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + +#ifndef btMatrix3x3_H +#define btMatrix3x3_H + +#include "btScalar.h" + +#include "btVector3.h" +#include "btQuaternion.h" + + +class btMatrix3x3 { + public: + btMatrix3x3 () {} + +// explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); } + + explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); } + /* + template + Matrix3x3(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + setEulerYPR(yaw, pitch, roll); + } + */ + btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz, + const btScalar& yx, const btScalar& yy, const btScalar& yz, + const btScalar& zx, const btScalar& zy, const btScalar& zz) + { + setValue(xx, xy, xz, + yx, yy, yz, + zx, zy, zz); + } + + SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other) + { + m_el[0] = other.m_el[0]; + m_el[1] = other.m_el[1]; + m_el[2] = other.m_el[2]; + } + + SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other) + { + m_el[0] = other.m_el[0]; + m_el[1] = other.m_el[1]; + m_el[2] = other.m_el[2]; + return *this; + } + + SIMD_FORCE_INLINE btVector3 getColumn(int i) const + { + return btVector3(m_el[0][i],m_el[1][i],m_el[2][i]); + } + + + + SIMD_FORCE_INLINE const btVector3& getRow(int i) const + { + return m_el[i]; + } + + + SIMD_FORCE_INLINE btVector3& operator[](int i) + { + btFullAssert(0 <= i && i < 3); + return m_el[i]; + } + + SIMD_FORCE_INLINE const btVector3& operator[](int i) const + { + btFullAssert(0 <= i && i < 3); + return m_el[i]; + } + + btMatrix3x3& operator*=(const btMatrix3x3& m); + + + void setFromOpenGLSubMatrix(const btScalar *m) + { + m_el[0].setValue(m[0],m[4],m[8]); + m_el[1].setValue(m[1],m[5],m[9]); + m_el[2].setValue(m[2],m[6],m[10]); + + } + + void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz, + const btScalar& yx, const btScalar& yy, const btScalar& yz, + const btScalar& zx, const btScalar& zy, const btScalar& zz) + { + m_el[0].setValue(xx,xy,xz); + m_el[1].setValue(yx,yy,yz); + m_el[2].setValue(zx,zy,zz); + } + + void setRotation(const btQuaternion& q) + { + btScalar d = q.length2(); + btFullAssert(d != btScalar(0.0)); + btScalar s = btScalar(2.0) / d; + btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s; + btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs; + btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs; + btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs; + setValue(btScalar(1.0) - (yy + zz), xy - wz, xz + wy, + xy + wz, btScalar(1.0) - (xx + zz), yz - wx, + xz - wy, yz + wx, btScalar(1.0) - (xx + yy)); + } + + + + void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + + btScalar cy(btCos(yaw)); + btScalar sy(btSin(yaw)); + btScalar cp(btCos(pitch)); + btScalar sp(btSin(pitch)); + btScalar cr(btCos(roll)); + btScalar sr(btSin(roll)); + btScalar cc = cy * cr; + btScalar cs = cy * sr; + btScalar sc = sy * cr; + btScalar ss = sy * sr; + setValue(cc - sp * ss, -cs - sp * sc, -sy * cp, + cp * sr, cp * cr, -sp, + sc + sp * cs, -ss + sp * cc, cy * cp); + + } + + /** + * setEulerZYX + * @param euler a const reference to a btVector3 of euler angles + * These angles are used to produce a rotation matrix. The euler + * angles are applied in ZYX order. I.e a vector is first rotated + * about X then Y and then Z + **/ + + void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) { + btScalar ci ( btCos(eulerX)); + btScalar cj ( btCos(eulerY)); + btScalar ch ( btCos(eulerZ)); + btScalar si ( btSin(eulerX)); + btScalar sj ( btSin(eulerY)); + btScalar sh ( btSin(eulerZ)); + btScalar cc = ci * ch; + btScalar cs = ci * sh; + btScalar sc = si * ch; + btScalar ss = si * sh; + + setValue(cj * ch, sj * sc - cs, sj * cc + ss, + cj * sh, sj * ss + cc, sj * cs - sc, + -sj, cj * si, cj * ci); + } + + void setIdentity() + { + setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0), + btScalar(0.0), btScalar(1.0), btScalar(0.0), + btScalar(0.0), btScalar(0.0), btScalar(1.0)); + } + + void getOpenGLSubMatrix(btScalar *m) const + { + m[0] = btScalar(m_el[0].x()); + m[1] = btScalar(m_el[1].x()); + m[2] = btScalar(m_el[2].x()); + m[3] = btScalar(0.0); + m[4] = btScalar(m_el[0].y()); + m[5] = btScalar(m_el[1].y()); + m[6] = btScalar(m_el[2].y()); + m[7] = btScalar(0.0); + m[8] = btScalar(m_el[0].z()); + m[9] = btScalar(m_el[1].z()); + m[10] = btScalar(m_el[2].z()); + m[11] = btScalar(0.0); + } + + void getRotation(btQuaternion& q) const + { + btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z(); + btScalar temp[4]; + + if (trace > btScalar(0.0)) + { + btScalar s = btSqrt(trace + btScalar(1.0)); + temp[3]=(s * btScalar(0.5)); + s = btScalar(0.5) / s; + + temp[0]=((m_el[2].y() - m_el[1].z()) * s); + temp[1]=((m_el[0].z() - m_el[2].x()) * s); + temp[2]=((m_el[1].x() - m_el[0].y()) * s); + } + else + { + int i = m_el[0].x() < m_el[1].y() ? + (m_el[1].y() < m_el[2].z() ? 2 : 1) : + (m_el[0].x() < m_el[2].z() ? 2 : 0); + int j = (i + 1) % 3; + int k = (i + 2) % 3; + + btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0)); + temp[i] = s * btScalar(0.5); + s = btScalar(0.5) / s; + + temp[3] = (m_el[k][j] - m_el[j][k]) * s; + temp[j] = (m_el[j][i] + m_el[i][j]) * s; + temp[k] = (m_el[k][i] + m_el[i][k]) * s; + } + q.setValue(temp[0],temp[1],temp[2],temp[3]); + } + + void getEuler(btScalar& yaw, btScalar& pitch, btScalar& roll) const + { + + if (btScalar(m_el[1].z()) < btScalar(1)) + { + if (btScalar(m_el[1].z()) > -btScalar(1)) + { + yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x())); + pitch = btScalar(btAsin(-m_el[1].y())); + roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z())); + } + else + { + yaw = btScalar(-btAtan2(-m_el[0].y(), m_el[0].z())); + pitch = SIMD_HALF_PI; + roll = btScalar(0.0); + } + } + else + { + yaw = btScalar(btAtan2(-m_el[0].y(), m_el[0].z())); + pitch = -SIMD_HALF_PI; + roll = btScalar(0.0); + } + } + + + + + btMatrix3x3 scaled(const btVector3& s) const + { + return btMatrix3x3(m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(), + m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(), + m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z()); + } + + btScalar determinant() const; + btMatrix3x3 adjoint() const; + btMatrix3x3 absolute() const; + btMatrix3x3 transpose() const; + btMatrix3x3 inverse() const; + + btMatrix3x3 transposeTimes(const btMatrix3x3& m) const; + btMatrix3x3 timesTranspose(const btMatrix3x3& m) const; + + SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const + { + return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z(); + } + SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const + { + return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z(); + } + SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const + { + return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z(); + } + + + + protected: + btScalar cofac(int r1, int c1, int r2, int c2) const + { + return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1]; + } + + btVector3 m_el[3]; + }; + + SIMD_FORCE_INLINE btMatrix3x3& + btMatrix3x3::operator*=(const btMatrix3x3& m) + { + setValue(m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]), + m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]), + m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2])); + return *this; + } + + SIMD_FORCE_INLINE btScalar + btMatrix3x3::determinant() const + { + return triple((*this)[0], (*this)[1], (*this)[2]); + } + + + SIMD_FORCE_INLINE btMatrix3x3 + btMatrix3x3::absolute() const + { + return btMatrix3x3( + btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()), + btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()), + btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z())); + } + + SIMD_FORCE_INLINE btMatrix3x3 + btMatrix3x3::transpose() const + { + return btMatrix3x3(m_el[0].x(), m_el[1].x(), m_el[2].x(), + m_el[0].y(), m_el[1].y(), m_el[2].y(), + m_el[0].z(), m_el[1].z(), m_el[2].z()); + } + + SIMD_FORCE_INLINE btMatrix3x3 + btMatrix3x3::adjoint() const + { + return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2), + cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0), + cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1)); + } + + SIMD_FORCE_INLINE btMatrix3x3 + btMatrix3x3::inverse() const + { + btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)); + btScalar det = (*this)[0].dot(co); + btFullAssert(det != btScalar(0.0)); + btScalar s = btScalar(1.0) / det; + return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s, + co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s, + co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s); + } + + SIMD_FORCE_INLINE btMatrix3x3 + btMatrix3x3::transposeTimes(const btMatrix3x3& m) const + { + return btMatrix3x3( + m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(), + m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(), + m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(), + m_el[0].y() * m[0].x() + m_el[1].y() * m[1].x() + m_el[2].y() * m[2].x(), + m_el[0].y() * m[0].y() + m_el[1].y() * m[1].y() + m_el[2].y() * m[2].y(), + m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(), + m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(), + m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(), + m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].x()); + } + + SIMD_FORCE_INLINE btMatrix3x3 + btMatrix3x3::timesTranspose(const btMatrix3x3& m) const + { + return btMatrix3x3( + m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]), + m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]), + m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2])); + + } + + SIMD_FORCE_INLINE btVector3 + operator*(const btMatrix3x3& m, const btVector3& v) + { + return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v)); + } + + + SIMD_FORCE_INLINE btVector3 + operator*(const btVector3& v, const btMatrix3x3& m) + { + return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v)); + } + + SIMD_FORCE_INLINE btMatrix3x3 + operator*(const btMatrix3x3& m1, const btMatrix3x3& m2) + { + return btMatrix3x3( + m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]), + m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]), + m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2])); + } + +/* + SIMD_FORCE_INLINE btMatrix3x3 btMultTransposeLeft(const btMatrix3x3& m1, const btMatrix3x3& m2) { + return btMatrix3x3( + m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0], + m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1], + m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0], + m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1], + m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0], + m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1], + m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]); +} +*/ + + +#endif diff --git a/extern/bullet2/src/LinearMath/btMinMax.h b/extern/bullet2/src/LinearMath/btMinMax.h new file mode 100644 index 00000000000..1b8a3633f38 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btMinMax.h @@ -0,0 +1,69 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + + +#ifndef GEN_MINMAX_H +#define GEN_MINMAX_H + +template +SIMD_FORCE_INLINE const T& GEN_min(const T& a, const T& b) +{ + return b < a ? b : a; +} + +template +SIMD_FORCE_INLINE const T& GEN_max(const T& a, const T& b) +{ + return a < b ? b : a; +} + +template +SIMD_FORCE_INLINE const T& GEN_clamped(const T& a, const T& lb, const T& ub) +{ + return a < lb ? lb : (ub < a ? ub : a); +} + +template +SIMD_FORCE_INLINE void GEN_set_min(T& a, const T& b) +{ + if (b < a) + { + a = b; + } +} + +template +SIMD_FORCE_INLINE void GEN_set_max(T& a, const T& b) +{ + if (a < b) + { + a = b; + } +} + +template +SIMD_FORCE_INLINE void GEN_clamp(T& a, const T& lb, const T& ub) +{ + if (a < lb) + { + a = lb; + } + else if (ub < a) + { + a = ub; + } +} + +#endif diff --git a/extern/bullet2/src/LinearMath/btMotionState.h b/extern/bullet2/src/LinearMath/btMotionState.h new file mode 100644 index 00000000000..1975e5ff900 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btMotionState.h @@ -0,0 +1,40 @@ +/* +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. +*/ + +#ifndef BT_MOTIONSTATE_H +#define BT_MOTIONSTATE_H + +#include "btTransform.h" + +///btMotionState allows the dynamics world to synchronize the updated world transforms with graphics +///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation) +class btMotionState +{ + public: + + virtual ~btMotionState() + { + + } + + virtual void getWorldTransform(btTransform& worldTrans ) const =0; + + //Bullet only calls the update of worldtransform for active objects + virtual void setWorldTransform(const btTransform& worldTrans)=0; + + +}; + +#endif //BT_MOTIONSTATE_H diff --git a/extern/bullet2/src/LinearMath/btPoint3.h b/extern/bullet2/src/LinearMath/btPoint3.h new file mode 100644 index 00000000000..a2020e26d12 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btPoint3.h @@ -0,0 +1,24 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + + +#ifndef btPoint3_H +#define btPoint3_H + +#include "btVector3.h" + +typedef btVector3 btPoint3; + +#endif diff --git a/extern/bullet2/src/LinearMath/btQuadWord.h b/extern/bullet2/src/LinearMath/btQuadWord.h new file mode 100644 index 00000000000..961ac484d20 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btQuadWord.h @@ -0,0 +1,139 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + +#ifndef SIMD_QUADWORD_H +#define SIMD_QUADWORD_H + +#include "btScalar.h" + + + + +///btQuadWord is base-class for vectors, points +class btQuadWord +{ + protected: + btScalar m_x; + btScalar m_y; + btScalar m_z; + btScalar m_unusedW; + + public: + +// SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_x)[i]; } +// SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_x)[i]; } + + SIMD_FORCE_INLINE const btScalar& getX() const { return m_x; } + + SIMD_FORCE_INLINE const btScalar& getY() const { return m_y; } + + SIMD_FORCE_INLINE const btScalar& getZ() const { return m_z; } + + SIMD_FORCE_INLINE void setX(btScalar x) { m_x = x;}; + + SIMD_FORCE_INLINE void setY(btScalar y) { m_y = y;}; + + SIMD_FORCE_INLINE void setZ(btScalar z) { m_z = z;}; + + SIMD_FORCE_INLINE void setW(btScalar w) { m_unusedW = w;}; + + SIMD_FORCE_INLINE const btScalar& x() const { return m_x; } + + SIMD_FORCE_INLINE const btScalar& y() const { return m_y; } + + SIMD_FORCE_INLINE const btScalar& z() const { return m_z; } + + SIMD_FORCE_INLINE const btScalar& w() const { return m_unusedW; } + + + SIMD_FORCE_INLINE operator btScalar *() { return &m_x; } + SIMD_FORCE_INLINE operator const btScalar *() const { return &m_x; } + + SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) + { + m_x=x; + m_y=y; + m_z=z; + m_unusedW = 0.f; + } + +/* void getValue(btScalar *m) const + { + m[0] = m_x; + m[1] = m_y; + m[2] = m_z; + } +*/ + SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) + { + m_x=x; + m_y=y; + m_z=z; + m_unusedW=w; + } + + SIMD_FORCE_INLINE btQuadWord() + // :m_x(btScalar(0.)),m_y(btScalar(0.)),m_z(btScalar(0.)),m_unusedW(btScalar(0.)) + { + } + + SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z) + :m_x(x),m_y(y),m_z(z) + //todo, remove this in release/simd ? + ,m_unusedW(btScalar(0.)) + { + } + + SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) + :m_x(x),m_y(y),m_z(z),m_unusedW(w) + { + } + + + SIMD_FORCE_INLINE void setMax(const btQuadWord& other) + { + if (other.m_x > m_x) + m_x = other.m_x; + + if (other.m_y > m_y) + m_y = other.m_y; + + if (other.m_z > m_z) + m_z = other.m_z; + + if (other.m_unusedW > m_unusedW) + m_unusedW = other.m_unusedW; + } + + SIMD_FORCE_INLINE void setMin(const btQuadWord& other) + { + if (other.m_x < m_x) + m_x = other.m_x; + + if (other.m_y < m_y) + m_y = other.m_y; + + if (other.m_z < m_z) + m_z = other.m_z; + + if (other.m_unusedW < m_unusedW) + m_unusedW = other.m_unusedW; + } + + + +}; + +#endif //SIMD_QUADWORD_H diff --git a/extern/bullet2/src/LinearMath/btQuaternion.h b/extern/bullet2/src/LinearMath/btQuaternion.h new file mode 100644 index 00000000000..50334970ba6 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btQuaternion.h @@ -0,0 +1,321 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + + +#ifndef SIMD__QUATERNION_H_ +#define SIMD__QUATERNION_H_ + +#include "btVector3.h" + +class btQuaternion : public btQuadWord { +public: + btQuaternion() {} + + // template + // explicit Quaternion(const btScalar *v) : Tuple4(v) {} + + btQuaternion(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w) + : btQuadWord(x, y, z, w) + {} + + btQuaternion(const btVector3& axis, const btScalar& angle) + { + setRotation(axis, angle); + } + + btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + setEuler(yaw, pitch, roll); + } + + void setRotation(const btVector3& axis, const btScalar& angle) + { + btScalar d = axis.length(); + assert(d != btScalar(0.0)); + btScalar s = btSin(angle * btScalar(0.5)) / d; + setValue(axis.x() * s, axis.y() * s, axis.z() * s, + btCos(angle * btScalar(0.5))); + } + + void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) + { + btScalar halfYaw = btScalar(yaw) * btScalar(0.5); + btScalar halfPitch = btScalar(pitch) * btScalar(0.5); + btScalar halfRoll = btScalar(roll) * btScalar(0.5); + btScalar cosYaw = btCos(halfYaw); + btScalar sinYaw = btSin(halfYaw); + btScalar cosPitch = btCos(halfPitch); + btScalar sinPitch = btSin(halfPitch); + btScalar cosRoll = btCos(halfRoll); + btScalar sinRoll = btSin(halfRoll); + setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, + cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, + sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, + cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); + } + + btQuaternion& operator+=(const btQuaternion& q) + { + m_x += q.x(); m_y += q.y(); m_z += q.z(); m_unusedW += q.m_unusedW; + return *this; + } + + btQuaternion& operator-=(const btQuaternion& q) + { + m_x -= q.x(); m_y -= q.y(); m_z -= q.z(); m_unusedW -= q.m_unusedW; + return *this; + } + + btQuaternion& operator*=(const btScalar& s) + { + m_x *= s; m_y *= s; m_z *= s; m_unusedW *= s; + return *this; + } + + + btQuaternion& operator*=(const btQuaternion& q) + { + setValue(m_unusedW * q.x() + m_x * q.m_unusedW + m_y * q.z() - m_z * q.y(), + m_unusedW * q.y() + m_y * q.m_unusedW + m_z * q.x() - m_x * q.z(), + m_unusedW * q.z() + m_z * q.m_unusedW + m_x * q.y() - m_y * q.x(), + m_unusedW * q.m_unusedW - m_x * q.x() - m_y * q.y() - m_z * q.z()); + return *this; + } + + btScalar dot(const btQuaternion& q) const + { + return m_x * q.x() + m_y * q.y() + m_z * q.z() + m_unusedW * q.m_unusedW; + } + + btScalar length2() const + { + return dot(*this); + } + + btScalar length() const + { + return btSqrt(length2()); + } + + btQuaternion& normalize() + { + return *this /= length(); + } + + SIMD_FORCE_INLINE btQuaternion + operator*(const btScalar& s) const + { + return btQuaternion(x() * s, y() * s, z() * s, m_unusedW * s); + } + + + + btQuaternion operator/(const btScalar& s) const + { + assert(s != btScalar(0.0)); + return *this * (btScalar(1.0) / s); + } + + + btQuaternion& operator/=(const btScalar& s) + { + assert(s != btScalar(0.0)); + return *this *= btScalar(1.0) / s; + } + + + btQuaternion normalized() const + { + return *this / length(); + } + + btScalar angle(const btQuaternion& q) const + { + btScalar s = btSqrt(length2() * q.length2()); + assert(s != btScalar(0.0)); + return btAcos(dot(q) / s); + } + + btScalar getAngle() const + { + btScalar s = btScalar(2.) * btAcos(m_unusedW); + return s; + } + + + + btQuaternion inverse() const + { + return btQuaternion(m_x, m_y, m_z, -m_unusedW); + } + + SIMD_FORCE_INLINE btQuaternion + operator+(const btQuaternion& q2) const + { + const btQuaternion& q1 = *this; + return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_unusedW + q2.m_unusedW); + } + + SIMD_FORCE_INLINE btQuaternion + operator-(const btQuaternion& q2) const + { + const btQuaternion& q1 = *this; + return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_unusedW - q2.m_unusedW); + } + + SIMD_FORCE_INLINE btQuaternion operator-() const + { + const btQuaternion& q2 = *this; + return btQuaternion( - q2.x(), - q2.y(), - q2.z(), - q2.m_unusedW); + } + + SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const + { + btQuaternion diff,sum; + diff = *this - qd; + sum = *this + qd; + if( diff.dot(diff) > sum.dot(sum) ) + return qd; + return (-qd); + } + + btQuaternion slerp(const btQuaternion& q, const btScalar& t) const + { + btScalar theta = angle(q); + if (theta != btScalar(0.0)) + { + btScalar d = btScalar(1.0) / btSin(theta); + btScalar s0 = btSin((btScalar(1.0) - t) * theta); + btScalar s1 = btSin(t * theta); + return btQuaternion((m_x * s0 + q.x() * s1) * d, + (m_y * s0 + q.y() * s1) * d, + (m_z * s0 + q.z() * s1) * d, + (m_unusedW * s0 + q.m_unusedW * s1) * d); + } + else + { + return *this; + } + } + + SIMD_FORCE_INLINE const btScalar& getW() const { return m_unusedW; } + + +}; + + + +SIMD_FORCE_INLINE btQuaternion +operator-(const btQuaternion& q) +{ + return btQuaternion(-q.x(), -q.y(), -q.z(), -q.w()); +} + + + + +SIMD_FORCE_INLINE btQuaternion +operator*(const btQuaternion& q1, const btQuaternion& q2) { + return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(), + q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(), + q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(), + q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z()); +} + +SIMD_FORCE_INLINE btQuaternion +operator*(const btQuaternion& q, const btVector3& w) +{ + return btQuaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(), + q.w() * w.y() + q.z() * w.x() - q.x() * w.z(), + q.w() * w.z() + q.x() * w.y() - q.y() * w.x(), + -q.x() * w.x() - q.y() * w.y() - q.z() * w.z()); +} + +SIMD_FORCE_INLINE btQuaternion +operator*(const btVector3& w, const btQuaternion& q) +{ + return btQuaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(), + w.y() * q.w() + w.z() * q.x() - w.x() * q.z(), + w.z() * q.w() + w.x() * q.y() - w.y() * q.x(), + -w.x() * q.x() - w.y() * q.y() - w.z() * q.z()); +} + +SIMD_FORCE_INLINE btScalar +dot(const btQuaternion& q1, const btQuaternion& q2) +{ + return q1.dot(q2); +} + + +SIMD_FORCE_INLINE btScalar +length(const btQuaternion& q) +{ + return q.length(); +} + +SIMD_FORCE_INLINE btScalar +angle(const btQuaternion& q1, const btQuaternion& q2) +{ + return q1.angle(q2); +} + + +SIMD_FORCE_INLINE btQuaternion +inverse(const btQuaternion& q) +{ + return q.inverse(); +} + +SIMD_FORCE_INLINE btQuaternion +slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) +{ + return q1.slerp(q2, t); +} + +SIMD_FORCE_INLINE btVector3 +quatRotate(btQuaternion& rotation, btVector3& v) +{ + btQuaternion q = rotation * v; + q *= rotation.inverse(); + return btVector3(q.getX(),q.getY(),q.getZ()); +} + +SIMD_FORCE_INLINE btQuaternion +shortestArcQuat(btVector3& v0,btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized +{ + btVector3 c = v0.cross(v1); + btScalar d = v0.dot(v1); + + if (d < -1.0 + SIMD_EPSILON) + return btQuaternion(0.0f,1.0f,0.0f,0.0f); // just pick any vector + + btScalar s = btSqrt((1.0f + d) * 2.0f); + btScalar rs = 1.0f / s; + + return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f); +} + +SIMD_FORCE_INLINE btQuaternion +shortestArcQuatNormalize(btVector3& v0,btVector3& v1) +{ + v0.normalize(); + v1.normalize(); + return shortestArcQuat(v0,v1); +} + +#endif + + + diff --git a/extern/bullet2/src/LinearMath/btQuickprof.cpp b/extern/bullet2/src/LinearMath/btQuickprof.cpp new file mode 100644 index 00000000000..37a0c8c3be5 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btQuickprof.cpp @@ -0,0 +1,38 @@ +/* +Copyright (c) 2006 Tyler Streeter + +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. + +*/ + + +// Please visit the project website (http://quickprof.sourceforge.net) +// for usage instructions. + +// Credits: The Clock class was inspired by the Timer classes in +// Ogre (www.ogre3d.org). + +#include "LinearMath/btQuickprof.h" + +#ifdef USE_QUICKPROF + +// Note: We must declare these private static variables again here to +// avoid link errors. +bool btProfiler::mEnabled = false; +btClock btProfiler::mClock; +unsigned long int btProfiler::mCurrentCycleStartMicroseconds = 0; +unsigned long int btProfiler::mLastCycleDurationMicroseconds = 0; +std::map btProfiler::mProfileBlocks; +std::ofstream btProfiler::mOutputFile; +bool btProfiler::mFirstFileOutput = true; +btProfiler::BlockTimingMethod btProfiler::mFileOutputMethod; +unsigned long int btProfiler::mCycleNumber = 0; +#endif //USE_QUICKPROF diff --git a/extern/bullet2/src/LinearMath/btQuickprof.h b/extern/bullet2/src/LinearMath/btQuickprof.h new file mode 100644 index 00000000000..a885967c5fa --- /dev/null +++ b/extern/bullet2/src/LinearMath/btQuickprof.h @@ -0,0 +1,712 @@ +/* +Copyright (c) 2006 Tyler Streeter + +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. + +*/ + +// Please visit the project website (http://quickprof.sourceforge.net) +// for usage instructions. + +// Credits: The Clock class was inspired by the Timer classes in +// Ogre (www.ogre3d.org). + +#ifndef QUICK_PROF_H +#define QUICK_PROF_H + +#include "btScalar.h" + +//#define USE_QUICKPROF 1 +//Don't use quickprof for now, because it contains STL. TODO: replace STL by Bullet container classes. + + +//if you don't need btClock, you can comment next line +#define USE_BT_CLOCK 1 + +#ifdef USE_BT_CLOCK +#ifdef __CELLOS_LV2__ +#include +#include +typedef uint64_t __int64; +#endif + +#if defined (SUNOS) || defined (__SUNOS__) + #include +#endif + +#if defined(WIN32) || defined(_WIN32) + + #define USE_WINDOWS_TIMERS + #define WIN32_LEAN_AND_MEAN + #define NOWINRES + #define NOMCX + #define NOIME +#ifdef _XBOX + #include +#else + #include +#endif + #include + +#else + #include +#endif + +#define mymin(a,b) (a > b ? a : b) + +/// basic clock +class btClock + { + public: + btClock() + { +#ifdef USE_WINDOWS_TIMERS + QueryPerformanceFrequency(&mClockFrequency); +#endif + reset(); + } + + ~btClock() + { + } + + /// Resets the initial reference time. + void reset() + { +#ifdef USE_WINDOWS_TIMERS + QueryPerformanceCounter(&mStartTime); + mStartTick = GetTickCount(); + mPrevElapsedTime = 0; +#else +#ifdef __CELLOS_LV2__ + + typedef uint64_t __int64; + typedef __int64 ClockSize; + ClockSize newTime; + __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + mStartTime = newTime; +#else + gettimeofday(&mStartTime, 0); +#endif + +#endif + } + + /// Returns the time in ms since the last call to reset or since + /// the btClock was created. + unsigned long int getTimeMilliseconds() + { +#ifdef USE_WINDOWS_TIMERS + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + mStartTime.QuadPart; + + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + mClockFrequency.QuadPart); + + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + mClockFrequency.QuadPart / 1000, elapsedTime - + mPrevElapsedTime); + mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; + + // Recompute the number of millisecond ticks elapsed. + msecTicks = (unsigned long)(1000 * elapsedTime / + mClockFrequency.QuadPart); + } + + // Store the current elapsed time for adjustments next time. + mPrevElapsedTime = elapsedTime; + + return msecTicks; +#else + +#ifdef __CELLOS_LV2__ + __int64 freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq) / 1000.0; + typedef uint64_t __int64; + typedef __int64 ClockSize; + ClockSize newTime; + __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + + return (newTime-mStartTime) / dFreq; +#else + + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 + + (currentTime.tv_usec - mStartTime.tv_usec) / 1000; +#endif //__CELLOS_LV2__ +#endif + } + + /// Returns the time in us since the last call to reset or since + /// the Clock was created. + unsigned long int getTimeMicroseconds() + { +#ifdef USE_WINDOWS_TIMERS + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + mStartTime.QuadPart; + + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + mClockFrequency.QuadPart); + + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + mClockFrequency.QuadPart / 1000, elapsedTime - + mPrevElapsedTime); + mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; + } + + // Store the current elapsed time for adjustments next time. + mPrevElapsedTime = elapsedTime; + + // Convert to microseconds. + unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / + mClockFrequency.QuadPart); + + return usecTicks; +#else + +#ifdef __CELLOS_LV2__ + __int64 freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq)/ 1000000.0; + typedef uint64_t __int64; + typedef __int64 ClockSize; + ClockSize newTime; + __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + + return (newTime-mStartTime) / dFreq; +#else + + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 + + (currentTime.tv_usec - mStartTime.tv_usec); +#endif//__CELLOS_LV2__ +#endif + } + + private: +#ifdef USE_WINDOWS_TIMERS + LARGE_INTEGER mClockFrequency; + DWORD mStartTick; + LONGLONG mPrevElapsedTime; + LARGE_INTEGER mStartTime; +#else +#ifdef __CELLOS_LV2__ + uint64_t mStartTime; +#else + struct timeval mStartTime; +#endif +#endif //__CELLOS_LV2__ + + }; + +#endif //USE_BT_CLOCK + + +#ifdef USE_QUICKPROF + + +#include +#include +#include +#include + + + + +namespace hidden +{ + /// A simple data structure representing a single timed block + /// of code. + struct ProfileBlock + { + ProfileBlock() + { + currentBlockStartMicroseconds = 0; + currentCycleTotalMicroseconds = 0; + lastCycleTotalMicroseconds = 0; + totalMicroseconds = 0; + } + + /// The starting time (in us) of the current block update. + unsigned long int currentBlockStartMicroseconds; + + /// The accumulated time (in us) spent in this block during the + /// current profiling cycle. + unsigned long int currentCycleTotalMicroseconds; + + /// The accumulated time (in us) spent in this block during the + /// past profiling cycle. + unsigned long int lastCycleTotalMicroseconds; + + /// The total accumulated time (in us) spent in this block. + unsigned long int totalMicroseconds; + }; + +}; + +/// A static class that manages timing for a set of profiling blocks. +class btProfiler +{ +public: + /// A set of ways to retrieve block timing data. + enum BlockTimingMethod + { + /// The total time spent in the block (in seconds) since the + /// profiler was initialized. + BLOCK_TOTAL_SECONDS, + + /// The total time spent in the block (in ms) since the + /// profiler was initialized. + BLOCK_TOTAL_MILLISECONDS, + + /// The total time spent in the block (in us) since the + /// profiler was initialized. + BLOCK_TOTAL_MICROSECONDS, + + /// The total time spent in the block, as a % of the total + /// elapsed time since the profiler was initialized. + BLOCK_TOTAL_PERCENT, + + /// The time spent in the block (in seconds) in the most recent + /// profiling cycle. + BLOCK_CYCLE_SECONDS, + + /// The time spent in the block (in ms) in the most recent + /// profiling cycle. + BLOCK_CYCLE_MILLISECONDS, + + /// The time spent in the block (in us) in the most recent + /// profiling cycle. + BLOCK_CYCLE_MICROSECONDS, + + /// The time spent in the block (in seconds) in the most recent + /// profiling cycle, as a % of the total cycle time. + BLOCK_CYCLE_PERCENT + }; + + /// Initializes the profiler. This must be called first. If this is + /// never called, the profiler is effectively disabled; all other + /// functions will return immediately. The first parameter + /// is the name of an output data file; if this string is not empty, + /// data will be saved on every profiling cycle; if this string is + /// empty, no data will be saved to a file. The second parameter + /// determines which timing method is used when printing data to the + /// output file. + inline static void init(const std::string outputFilename="", + BlockTimingMethod outputMethod=BLOCK_CYCLE_MILLISECONDS); + + /// Cleans up allocated memory. + inline static void destroy(); + + /// Begins timing the named block of code. + inline static void beginBlock(const std::string& name); + + /// Updates the accumulated time spent in the named block by adding + /// the elapsed time since the last call to startBlock for this block + /// name. + inline static void endBlock(const std::string& name); + + /// Returns the time spent in the named block according to the + /// given timing method. See comments on BlockTimingMethod for details. + inline static double getBlockTime(const std::string& name, + BlockTimingMethod method=BLOCK_CYCLE_MILLISECONDS); + + /// Defines the end of a profiling cycle. Use this regularly if you + /// want to generate detailed timing information. This must not be + /// called within a timing block. + inline static void endProfilingCycle(); + + /// A helper function that creates a string of statistics for + /// each timing block. This is mainly for printing an overall + /// summary to the command line. + inline static std::string createStatsString( + BlockTimingMethod method=BLOCK_TOTAL_PERCENT); + +//private: + inline btProfiler(); + + inline ~btProfiler(); + + /// Prints an error message to standard output. + inline static void printError(const std::string& msg) + { + //btAssert(0); + std::cout << "[QuickProf error] " << msg << std::endl; + } + + /// Determines whether the profiler is enabled. + static bool mEnabled; + + /// The clock used to time profile blocks. + static btClock mClock; + + /// The starting time (in us) of the current profiling cycle. + static unsigned long int mCurrentCycleStartMicroseconds; + + /// The duration (in us) of the most recent profiling cycle. + static unsigned long int mLastCycleDurationMicroseconds; + + /// Internal map of named profile blocks. + static std::map mProfileBlocks; + + /// The data file used if this feature is enabled in 'init.' + static std::ofstream mOutputFile; + + /// Tracks whether we have begun print data to the output file. + static bool mFirstFileOutput; + + /// The method used when printing timing data to an output file. + static BlockTimingMethod mFileOutputMethod; + + /// The number of the current profiling cycle. + static unsigned long int mCycleNumber; +}; + + +btProfiler::btProfiler() +{ + // This never gets called because a btProfiler instance is never + // created. +} + +btProfiler::~btProfiler() +{ + // This never gets called because a btProfiler instance is never + // created. +} + +void btProfiler::init(const std::string outputFilename, + BlockTimingMethod outputMethod) +{ + mEnabled = true; + + if (!outputFilename.empty()) + { + mOutputFile.open(outputFilename.c_str()); + } + + mFileOutputMethod = outputMethod; + + mClock.reset(); + + // Set the start time for the first cycle. + mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); +} + +void btProfiler::destroy() +{ + if (!mEnabled) + { + return; + } + + if (mOutputFile.is_open()) + { + mOutputFile.close(); + } + + // Destroy all ProfileBlocks. + while (!mProfileBlocks.empty()) + { + delete (*mProfileBlocks.begin()).second; + mProfileBlocks.erase(mProfileBlocks.begin()); + } +} + +void btProfiler::beginBlock(const std::string& name) +{ + if (!mEnabled) + { + return; + } + + if (name.empty()) + { + printError("Cannot allow unnamed profile blocks."); + return; + } + + hidden::ProfileBlock* block = mProfileBlocks[name]; + + if (!block) + { + // Create a new ProfileBlock. + mProfileBlocks[name] = new hidden::ProfileBlock(); + block = mProfileBlocks[name]; + } + + // We do this at the end to get more accurate results. + block->currentBlockStartMicroseconds = mClock.getTimeMicroseconds(); +} + +void btProfiler::endBlock(const std::string& name) +{ + if (!mEnabled) + { + return; + } + + // We do this at the beginning to get more accurate results. + unsigned long int endTick = mClock.getTimeMicroseconds(); + + hidden::ProfileBlock* block = mProfileBlocks[name]; + + if (!block) + { + // The named block does not exist. Print an error. + printError("The profile block named '" + name + + "' does not exist."); + return; + } + + unsigned long int blockDuration = endTick - + block->currentBlockStartMicroseconds; + block->currentCycleTotalMicroseconds += blockDuration; + block->totalMicroseconds += blockDuration; +} + +double btProfiler::getBlockTime(const std::string& name, + BlockTimingMethod method) +{ + if (!mEnabled) + { + return 0; + } + + hidden::ProfileBlock* block = mProfileBlocks[name]; + + if (!block) + { + // The named block does not exist. Print an error. + printError("The profile block named '" + name + + "' does not exist."); + return 0; + } + + double result = 0; + + switch(method) + { + case BLOCK_TOTAL_SECONDS: + result = (double)block->totalMicroseconds * (double)0.000001; + break; + case BLOCK_TOTAL_MILLISECONDS: + result = (double)block->totalMicroseconds * (double)0.001; + break; + case BLOCK_TOTAL_MICROSECONDS: + result = (double)block->totalMicroseconds; + break; + case BLOCK_TOTAL_PERCENT: + { + double timeSinceInit = (double)mClock.getTimeMicroseconds(); + if (timeSinceInit <= 0) + { + result = 0; + } + else + { + result = 100.0 * (double)block->totalMicroseconds / + timeSinceInit; + } + break; + } + case BLOCK_CYCLE_SECONDS: + result = (double)block->lastCycleTotalMicroseconds * + (double)0.000001; + break; + case BLOCK_CYCLE_MILLISECONDS: + result = (double)block->lastCycleTotalMicroseconds * + (double)0.001; + break; + case BLOCK_CYCLE_MICROSECONDS: + result = (double)block->lastCycleTotalMicroseconds; + break; + case BLOCK_CYCLE_PERCENT: + { + if (0 == mLastCycleDurationMicroseconds) + { + // We have not yet finished a cycle, so just return zero + // percent to avoid a divide by zero error. + result = 0; + } + else + { + result = 100.0 * (double)block->lastCycleTotalMicroseconds / + mLastCycleDurationMicroseconds; + } + break; + } + default: + break; + } + + return result; +} + +void btProfiler::endProfilingCycle() +{ + if (!mEnabled) + { + return; + } + + // Store the duration of the cycle that just finished. + mLastCycleDurationMicroseconds = mClock.getTimeMicroseconds() - + mCurrentCycleStartMicroseconds; + + // For each block, update data for the cycle that just finished. + std::map::iterator iter; + for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) + { + hidden::ProfileBlock* block = (*iter).second; + block->lastCycleTotalMicroseconds = + block->currentCycleTotalMicroseconds; + block->currentCycleTotalMicroseconds = 0; + } + + if (mOutputFile.is_open()) + { + // Print data to the output file. + if (mFirstFileOutput) + { + // On the first iteration, print a header line that shows the + // names of each profiling block. + mOutputFile << "#cycle, "; + + for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); + ++iter) + { + mOutputFile << (*iter).first << ", "; + } + + mOutputFile << std::endl; + mFirstFileOutput = false; + } + + mOutputFile << mCycleNumber << ", "; + + for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); + ++iter) + { + mOutputFile << getBlockTime((*iter).first, mFileOutputMethod) + << ", "; + } + + mOutputFile << std::endl; + } + + ++mCycleNumber; + mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); +} + +std::string btProfiler::createStatsString(BlockTimingMethod method) +{ + if (!mEnabled) + { + return ""; + } + + std::string s; + std::string suffix; + + switch(method) + { + case BLOCK_TOTAL_SECONDS: + suffix = "s"; + break; + case BLOCK_TOTAL_MILLISECONDS: + suffix = "ms"; + break; + case BLOCK_TOTAL_MICROSECONDS: + suffix = "us"; + break; + case BLOCK_TOTAL_PERCENT: + { + suffix = "%"; + break; + } + case BLOCK_CYCLE_SECONDS: + suffix = "s"; + break; + case BLOCK_CYCLE_MILLISECONDS: + suffix = "ms"; + break; + case BLOCK_CYCLE_MICROSECONDS: + suffix = "us"; + break; + case BLOCK_CYCLE_PERCENT: + { + suffix = "%"; + break; + } + default: + break; + } + + std::map::iterator iter; + for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) + { + if (iter != mProfileBlocks.begin()) + { + s += "\n"; + } + + char blockTime[64]; + sprintf(blockTime, "%lf", getBlockTime((*iter).first, method)); + + s += (*iter).first; + s += ": "; + s += blockTime; + s += " "; + s += suffix; + } + + return s; +} + + +#define BEGIN_PROFILE(a) btProfiler::beginBlock(a) +#define END_PROFILE(a) btProfiler::endBlock(a) + +#else //USE_QUICKPROF +#define BEGIN_PROFILE(a) +#define END_PROFILE(a) + +#endif //USE_QUICKPROF + +#endif //QUICK_PROF_H + + diff --git a/extern/bullet2/src/LinearMath/btRandom.h b/extern/bullet2/src/LinearMath/btRandom.h new file mode 100644 index 00000000000..fdf65e01caf --- /dev/null +++ b/extern/bullet2/src/LinearMath/btRandom.h @@ -0,0 +1,42 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + + +#ifndef GEN_RANDOM_H +#define GEN_RANDOM_H + +#ifdef MT19937 + +#include +#include + +#define GEN_RAND_MAX UINT_MAX + +SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); } +SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); } + +#else + +#include + +#define GEN_RAND_MAX RAND_MAX + +SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); } +SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); } + +#endif + +#endif + diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h new file mode 100644 index 00000000000..01ad93e786a --- /dev/null +++ b/extern/bullet2/src/LinearMath/btScalar.h @@ -0,0 +1,181 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + + +#ifndef SIMD___SCALAR_H +#define SIMD___SCALAR_H + +#include + +#include +#include +#include + +#ifdef WIN32 + + #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) + #define SIMD_FORCE_INLINE inline + #define ATTRIBUTE_ALIGNED16(a) a + #else + #define BT_HAS_ALIGNED_ALOCATOR + #pragma warning(disable:4530) + #pragma warning(disable:4996) + #pragma warning(disable:4786) + #define SIMD_FORCE_INLINE __forceinline + #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a + #ifdef _XBOX + #define BT_USE_VMX128 + #else + #define BT_USE_SSE + #endif + #endif //__MINGW32__ + + #include + #define btAssert assert + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) +#else + +#if defined (__CELLOS_LV2__) + #define SIMD_FORCE_INLINE inline + #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #ifndef assert + #include + #endif + #define btAssert assert + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) +#else + + //non-windows systems + + #define SIMD_FORCE_INLINE inline + #define ATTRIBUTE_ALIGNED16(a) a + #ifndef assert + #include + #endif + #define btAssert assert + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) +#endif //__CELLOS_LV2__ +#endif + +/// older compilers (gcc 3.x) and Sun needs double version of sqrt etc. +/// exclude Apple Intel (i's assumed to be a Macbook or new Intel Dual Core Processor) +#if defined (__sun) || defined (__sun__) || defined (__sparc) || (defined (__APPLE__) && ! defined (__i386__)) +//use slow double float precision operation on those platforms +#ifndef BT_USE_DOUBLE_PRECISION +#define BT_FORCE_DOUBLE_FUNCTIONS +#endif +#endif + +#if defined(BT_USE_DOUBLE_PRECISION) +typedef double btScalar; +#else +typedef float btScalar; +#endif + + +#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS) + +SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); } +SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); } +SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); } +SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); } +SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); } +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acos(x); } +SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asin(x); } +SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); } +SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); } +SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); } +SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); } +SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } + +#else + +SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrtf(x); } +SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); } +SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } +SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } +SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acosf(x); } +SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); } +SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } +SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } +SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); } +SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); } +SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); } + +#endif + +#define SIMD_2_PI btScalar(6.283185307179586232) +#define SIMD_PI (SIMD_2_PI * btScalar(0.5)) +#define SIMD_HALF_PI (SIMD_2_PI * btScalar(0.25)) +#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0)) +#define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI) + +#ifdef BT_USE_DOUBLE_PRECISION +#define SIMD_EPSILON DBL_EPSILON +#define SIMD_INFINITY DBL_MAX +#else +#define SIMD_EPSILON FLT_EPSILON +#define SIMD_INFINITY FLT_MAX +#endif + +SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x) +{ + btScalar coeff_1 = SIMD_PI / 4.0f; + btScalar coeff_2 = 3.0f * coeff_1; + btScalar abs_y = btFabs(y); + btScalar angle; + if (x >= 0.0f) { + btScalar r = (x - abs_y) / (x + abs_y); + angle = coeff_1 - coeff_1 * r; + } else { + btScalar r = (x + abs_y) / (abs_y - x); + angle = coeff_2 - coeff_1 * r; + } + return (y < 0.0f) ? -angle : angle; +} + +SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; } + +SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps) { + return (((a) <= eps) && !((a) < -eps)); +} +SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) { + return (!((a) <= eps)); +} + +/*SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } +SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } +SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acosf(x); } +SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); } +SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } +SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } +*/ + +SIMD_FORCE_INLINE int btIsNegative(btScalar x) { + return x < btScalar(0.0) ? 1 : 0; +} + +SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; } +SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; } + +#define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + + +#endif //SIMD___SCALAR_H diff --git a/extern/bullet2/src/LinearMath/btSimdMinMax.h b/extern/bullet2/src/LinearMath/btSimdMinMax.h new file mode 100644 index 00000000000..75e83f3c53f --- /dev/null +++ b/extern/bullet2/src/LinearMath/btSimdMinMax.h @@ -0,0 +1,41 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + + +#ifndef SIMD_MINMAX_H +#define SIMD_MINMAX_H +#include "btScalar.h" + +template +SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) { + return b < a ? b : a; +} + +template +SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) { + return a < b ? b : a; +} + +template +SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) { + if (a > b) a = b; +} + +template +SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) { + if (a < b) a = b; +} + +#endif diff --git a/extern/bullet2/src/LinearMath/btStackAlloc.h b/extern/bullet2/src/LinearMath/btStackAlloc.h new file mode 100644 index 00000000000..d219b453537 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btStackAlloc.h @@ -0,0 +1,106 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + +/* +StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson +Nov.2006 +*/ + +#ifndef BT_STACK_ALLOC +#define BT_STACK_ALLOC + +#include "btScalar.h" //for btAssert + +struct btBlock +{ + btBlock* previous; + unsigned char* address; +}; + +///StackAlloc provides some fast stack-based memory allocator (LIFO last-in first-out) +class btStackAlloc +{ +public: + + btStackAlloc(unsigned int size) { ctor();create(size); } + ~btStackAlloc() { destroy(); } + + inline void create(unsigned int size) + { + destroy(); + data = new unsigned char[size]; + totalsize = size; + } + inline void destroy() + { + btAssert(usedsize==0); + //Raise(L"StackAlloc is still in use"); + + if(usedsize==0) + { + if(!ischild) delete[] data; + data = 0; + usedsize = 0; + } + + } + unsigned char* allocate(unsigned int size) + { + const unsigned int nus(usedsize+size); + if(nusprevious = current; + pb->address = data+usedsize; + current = pb; + return(pb); + } + inline void endBlock(btBlock* block) + { + btAssert(block==current); + //Raise(L"Unmatched blocks"); + if(block==current) + { + current = block->previous; + usedsize = (unsigned int)((block->address-data)-sizeof(btBlock)); + } + } + +private: + void ctor() + { + data = 0; + totalsize = 0; + usedsize = 0; + current = 0; + ischild = false; + } + unsigned char* data; + unsigned int totalsize; + unsigned int usedsize; + btBlock* current; + bool ischild; +}; + +#endif //BT_STACK_ALLOC diff --git a/extern/bullet2/src/LinearMath/btTransform.h b/extern/bullet2/src/LinearMath/btTransform.h new file mode 100644 index 00000000000..2d55fec83a4 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btTransform.h @@ -0,0 +1,206 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + + +#ifndef btTransform_H +#define btTransform_H + +#include "btVector3.h" +#include "btMatrix3x3.h" + + +///btTransform supports rigid transforms (only translation and rotation, no scaling/shear) +class btTransform { + + +public: + + + btTransform() {} + + explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q, + const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) + : m_basis(q), + m_origin(c) + {} + + explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b, + const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) + : m_basis(b), + m_origin(c) + {} + + SIMD_FORCE_INLINE btTransform (const btTransform& other) + : m_basis(other.m_basis), + m_origin(other.m_origin) + { + } + + SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other) + { + m_basis = other.m_basis; + m_origin = other.m_origin; + return *this; + } + + + SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2) { + m_basis = t1.m_basis * t2.m_basis; + m_origin = t1(t2.m_origin); + } + +/* void multInverseLeft(const btTransform& t1, const btTransform& t2) { + btVector3 v = t2.m_origin - t1.m_origin; + m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis); + m_origin = v * t1.m_basis; + } + */ + + + SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const + { + return btVector3(m_basis[0].dot(x) + m_origin.x(), + m_basis[1].dot(x) + m_origin.y(), + m_basis[2].dot(x) + m_origin.z()); + } + + SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const + { + return (*this)(x); + } + + SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; } + SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; } + + SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; } + SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; } + + btQuaternion getRotation() const { + btQuaternion q; + m_basis.getRotation(q); + return q; + } + template + void setValue(const Scalar2 *m) + { + m_basis.setValue(m); + m_origin.setValue(&m[12]); + } + + + void setFromOpenGLMatrix(const btScalar *m) + { + m_basis.setFromOpenGLSubMatrix(m); + m_origin.setValue(m[12],m[13],m[14]); + } + + void getOpenGLMatrix(btScalar *m) const + { + m_basis.getOpenGLSubMatrix(m); + m[12] = m_origin.x(); + m[13] = m_origin.y(); + m[14] = m_origin.z(); + m[15] = btScalar(1.0); + } + + SIMD_FORCE_INLINE void setOrigin(const btVector3& origin) + { + m_origin = origin; + } + + SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const; + + + + SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis) + { + m_basis = basis; + } + + SIMD_FORCE_INLINE void setRotation(const btQuaternion& q) + { + m_basis.setRotation(q); + } + + + + void setIdentity() + { + m_basis.setIdentity(); + m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + } + + + btTransform& operator*=(const btTransform& t) + { + m_origin += m_basis * t.m_origin; + m_basis *= t.m_basis; + return *this; + } + + btTransform inverse() const + { + btMatrix3x3 inv = m_basis.transpose(); + return btTransform(inv, inv * -m_origin); + } + + btTransform inverseTimes(const btTransform& t) const; + + btTransform operator*(const btTransform& t) const; + + static btTransform getIdentity() + { + btTransform tr; + tr.setIdentity(); + return tr; + } + +private: + + btMatrix3x3 m_basis; + btVector3 m_origin; +}; + + +SIMD_FORCE_INLINE btVector3 +btTransform::invXform(const btVector3& inVec) const +{ + btVector3 v = inVec - m_origin; + return (m_basis.transpose() * v); +} + +SIMD_FORCE_INLINE btTransform +btTransform::inverseTimes(const btTransform& t) const +{ + btVector3 v = t.getOrigin() - m_origin; + return btTransform(m_basis.transposeTimes(t.m_basis), + v * m_basis); +} + +SIMD_FORCE_INLINE btTransform +btTransform::operator*(const btTransform& t) const +{ + return btTransform(m_basis * t.m_basis, + (*this)(t.m_origin)); +} + + + +#endif + + + + + diff --git a/extern/bullet2/src/LinearMath/btTransformUtil.h b/extern/bullet2/src/LinearMath/btTransformUtil.h new file mode 100644 index 00000000000..bc42fd166b6 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btTransformUtil.h @@ -0,0 +1,138 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + +#ifndef SIMD_TRANSFORM_UTIL_H +#define SIMD_TRANSFORM_UTIL_H + +#include "btTransform.h" +#define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI + + + +#define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490) + +#define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */ + +inline btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) +{ + return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), + supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), + supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); +} + + +inline void btPlaneSpace1 (const btVector3& n, btVector3& p, btVector3& q) +{ + if (btFabs(n.z()) > SIMDSQRT12) { + // choose p in y-z plane + btScalar a = n[1]*n[1] + n[2]*n[2]; + btScalar k = btRecipSqrt (a); + p.setValue(0,-n[2]*k,n[1]*k); + // set q = n x p + q.setValue(a*k,-n[0]*p[2],n[0]*p[1]); + } + else { + // choose p in x-y plane + btScalar a = n.x()*n.x() + n.y()*n.y(); + btScalar k = btRecipSqrt (a); + p.setValue(-n.y()*k,n.x()*k,0); + // set q = n x p + q.setValue(-n.z()*p.y(),n.z()*p.x(),a*k); + } +} + + + +/// Utils related to temporal transforms +class btTransformUtil +{ + +public: + + static void integrateTransform(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep,btTransform& predictedTransform) + { + predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep); +// #define QUATERNION_DERIVATIVE + #ifdef QUATERNION_DERIVATIVE + btQuaternion predictedOrn = curTrans.getRotation(); + predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5)); + predictedOrn.normalize(); + #else + //exponential map + btVector3 axis; + btScalar fAngle = angvel.length(); + //limit the angular motion + if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD) + { + fAngle = ANGULAR_MOTION_THRESHOLD / timeStep; + } + + if ( fAngle < btScalar(0.001) ) + { + // use Taylor's expansions of sync function + axis = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle ); + } + else + { + // sync(fAngle) = sin(c*fAngle)/t + axis = angvel*( btSin(btScalar(0.5)*fAngle*timeStep)/fAngle ); + } + btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*timeStep*btScalar(0.5) )); + btQuaternion orn0 = curTrans.getRotation(); + + btQuaternion predictedOrn = dorn * orn0; + predictedOrn.normalize(); + #endif + predictedTransform.setRotation(predictedOrn); + } + + static void calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel) + { + linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep; + btVector3 axis; + btScalar angle; + calculateDiffAxisAngle(transform0,transform1,axis,angle); + angVel = axis * angle / timeStep; + } + + static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle) + { + + #ifdef USE_QUATERNION_DIFF + btQuaternion orn0 = transform0.getRotation(); + btQuaternion orn1a = transform1.getRotation(); + btQuaternion orn1 = orn0.farthest(orn1a); + btQuaternion dorn = orn1 * orn0.inverse(); +#else + btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse(); + btQuaternion dorn; + dmat.getRotation(dorn); +#endif//USE_QUATERNION_DIFF + + angle = dorn.getAngle(); + axis = btVector3(dorn.x(),dorn.y(),dorn.z()); + axis[3] = btScalar(0.); + //check for axis length + btScalar len = axis.length2(); + if (len < SIMD_EPSILON*SIMD_EPSILON) + axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.)); + else + axis /= btSqrt(len); + } + +}; + +#endif //SIMD_TRANSFORM_UTIL_H + diff --git a/extern/bullet2/src/LinearMath/btVector3.h b/extern/bullet2/src/LinearMath/btVector3.h new file mode 100644 index 00000000000..74d41ad2a19 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btVector3.h @@ -0,0 +1,402 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / 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. +*/ + + + +#ifndef SIMD__VECTOR3_H +#define SIMD__VECTOR3_H + +#include "btQuadWord.h" + +///btVector3 can be used to represent 3D points and vectors. +///It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user +///Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers +class btVector3 : public btQuadWord { + +public: + SIMD_FORCE_INLINE btVector3() {} + + + + SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z) + :btQuadWord(x,y,z,btScalar(0.)) + { + } + +// SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) +// : btQuadWord(x,y,z,w) +// { +// } + + + + SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v) + { + m_x += v.x(); m_y += v.y(); m_z += v.z(); + return *this; + } + + + + SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v) + { + m_x -= v.x(); m_y -= v.y(); m_z -= v.z(); + return *this; + } + + SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s) + { + m_x *= s; m_y *= s; m_z *= s; + return *this; + } + + SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s) + { + btFullAssert(s != btScalar(0.0)); + return *this *= btScalar(1.0) / s; + } + + SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const + { + return m_x * v.x() + m_y * v.y() + m_z * v.z(); + } + + SIMD_FORCE_INLINE btScalar length2() const + { + return dot(*this); + } + + SIMD_FORCE_INLINE btScalar length() const + { + return btSqrt(length2()); + } + + SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const; + + SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const; + + SIMD_FORCE_INLINE btVector3& normalize() + { + return *this /= length(); + } + + SIMD_FORCE_INLINE btVector3 normalized() const; + + SIMD_FORCE_INLINE btVector3 rotate( const btVector3& wAxis, const btScalar angle ); + + SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const + { + btScalar s = btSqrt(length2() * v.length2()); + btFullAssert(s != btScalar(0.0)); + return btAcos(dot(v) / s); + } + + SIMD_FORCE_INLINE btVector3 absolute() const + { + return btVector3( + btFabs(m_x), + btFabs(m_y), + btFabs(m_z)); + } + + SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const + { + return btVector3( + m_y * v.z() - m_z * v.y(), + m_z * v.x() - m_x * v.z(), + m_x * v.y() - m_y * v.x()); + } + + SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const + { + return m_x * (v1.y() * v2.z() - v1.z() * v2.y()) + + m_y * (v1.z() * v2.x() - v1.x() * v2.z()) + + m_z * (v1.x() * v2.y() - v1.y() * v2.x()); + } + + SIMD_FORCE_INLINE int minAxis() const + { + return m_x < m_y ? (m_x < m_z ? 0 : 2) : (m_y < m_z ? 1 : 2); + } + + SIMD_FORCE_INLINE int maxAxis() const + { + return m_x < m_y ? (m_y < m_z ? 2 : 1) : (m_x < m_z ? 2 : 0); + } + + SIMD_FORCE_INLINE int furthestAxis() const + { + return absolute().minAxis(); + } + + SIMD_FORCE_INLINE int closestAxis() const + { + return absolute().maxAxis(); + } + + SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt) + { + btScalar s = btScalar(1.0) - rt; + m_x = s * v0.x() + rt * v1.x(); + m_y = s * v0.y() + rt * v1.y(); + m_z = s * v0.z() + rt * v1.z(); + //don't do the unused w component + // m_co[3] = s * v0[3] + rt * v1[3]; + } + + SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const + { + return btVector3(m_x + (v.x() - m_x) * t, + m_y + (v.y() - m_y) * t, + m_z + (v.z() - m_z) * t); + } + + + SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v) + { + m_x *= v.x(); m_y *= v.y(); m_z *= v.z(); + return *this; + } + + + +}; + +SIMD_FORCE_INLINE btVector3 +operator+(const btVector3& v1, const btVector3& v2) +{ + return btVector3(v1.x() + v2.x(), v1.y() + v2.y(), v1.z() + v2.z()); +} + +SIMD_FORCE_INLINE btVector3 +operator*(const btVector3& v1, const btVector3& v2) +{ + return btVector3(v1.x() * v2.x(), v1.y() * v2.y(), v1.z() * v2.z()); +} + +SIMD_FORCE_INLINE btVector3 +operator-(const btVector3& v1, const btVector3& v2) +{ + return btVector3(v1.x() - v2.x(), v1.y() - v2.y(), v1.z() - v2.z()); +} + +SIMD_FORCE_INLINE btVector3 +operator-(const btVector3& v) +{ + return btVector3(-v.x(), -v.y(), -v.z()); +} + +SIMD_FORCE_INLINE btVector3 +operator*(const btVector3& v, const btScalar& s) +{ + return btVector3(v.x() * s, v.y() * s, v.z() * s); +} + +SIMD_FORCE_INLINE btVector3 +operator*(const btScalar& s, const btVector3& v) +{ + return v * s; +} + +SIMD_FORCE_INLINE btVector3 +operator/(const btVector3& v, const btScalar& s) +{ + btFullAssert(s != btScalar(0.0)); + return v * (btScalar(1.0) / s); +} + +SIMD_FORCE_INLINE btVector3 +operator/(const btVector3& v1, const btVector3& v2) +{ + return btVector3(v1.x() / v2.x(),v1.y() / v2.y(),v1.z() / v2.z()); +} + +SIMD_FORCE_INLINE btScalar +dot(const btVector3& v1, const btVector3& v2) +{ + return v1.dot(v2); +} + + + +SIMD_FORCE_INLINE btScalar +distance2(const btVector3& v1, const btVector3& v2) +{ + return v1.distance2(v2); +} + + +SIMD_FORCE_INLINE btScalar +distance(const btVector3& v1, const btVector3& v2) +{ + return v1.distance(v2); +} + +SIMD_FORCE_INLINE btScalar +angle(const btVector3& v1, const btVector3& v2) +{ + return v1.angle(v2); +} + +SIMD_FORCE_INLINE btVector3 +cross(const btVector3& v1, const btVector3& v2) +{ + return v1.cross(v2); +} + +SIMD_FORCE_INLINE btScalar +triple(const btVector3& v1, const btVector3& v2, const btVector3& v3) +{ + return v1.triple(v2, v3); +} + +SIMD_FORCE_INLINE btVector3 +lerp(const btVector3& v1, const btVector3& v2, const btScalar& t) +{ + return v1.lerp(v2, t); +} + + +SIMD_FORCE_INLINE bool operator==(const btVector3& p1, const btVector3& p2) +{ + return p1.x() == p2.x() && p1.y() == p2.y() && p1.z() == p2.z(); +} + +SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const +{ + return (v - *this).length2(); +} + +SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const +{ + return (v - *this).length(); +} + +SIMD_FORCE_INLINE btVector3 btVector3::normalized() const +{ + return *this / length(); +} + +SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar angle ) +{ + // wAxis must be a unit lenght vector + + btVector3 o = wAxis * wAxis.dot( *this ); + btVector3 x = *this - o; + btVector3 y; + + y = wAxis.cross( *this ); + + return ( o + x * btCos( angle ) + y * btSin( angle ) ); +} + +class btVector4 : public btVector3 +{ +public: + + SIMD_FORCE_INLINE btVector4() {} + + + SIMD_FORCE_INLINE btVector4(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) + : btVector3(x,y,z) + { + m_unusedW = w; + } + + + SIMD_FORCE_INLINE btVector4 absolute4() const + { + return btVector4( + btFabs(m_x), + btFabs(m_y), + btFabs(m_z), + btFabs(m_unusedW)); + } + + + + btScalar getW() const { return m_unusedW;} + + + SIMD_FORCE_INLINE int maxAxis4() const + { + int maxIndex = -1; + btScalar maxVal = btScalar(-1e30); + if (m_x > maxVal) + { + maxIndex = 0; + maxVal = m_x; + } + if (m_y > maxVal) + { + maxIndex = 1; + maxVal = m_y; + } + if (m_z > maxVal) + { + maxIndex = 2; + maxVal = m_z; + } + if (m_unusedW > maxVal) + { + maxIndex = 3; + maxVal = m_unusedW; + } + + + + + return maxIndex; + + } + + + SIMD_FORCE_INLINE int minAxis4() const + { + int minIndex = -1; + btScalar minVal = btScalar(1e30); + if (m_x < minVal) + { + minIndex = 0; + minVal = m_x; + } + if (m_y < minVal) + { + minIndex = 1; + minVal = m_y; + } + if (m_z < minVal) + { + minIndex = 2; + minVal = m_z; + } + if (m_unusedW < minVal) + { + minIndex = 3; + minVal = m_unusedW; + } + + return minIndex; + + } + + + SIMD_FORCE_INLINE int closestAxis4() const + { + return absolute4().maxAxis4(); + } + +}; + +#endif //SIMD__VECTOR3_H diff --git a/extern/bullet2/src/Makefile b/extern/bullet2/src/Makefile new file mode 100644 index 00000000000..d7bb6a5e427 --- /dev/null +++ b/extern/bullet2/src/Makefile @@ -0,0 +1,68 @@ +# +# $Id: Makefile 14444 2008-04-16 22:40:48Z hos $ +# +# ***** BEGIN GPL 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. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL LICENSE BLOCK ***** +# + +LIBNAME = bullet2 +DIR = $(OCGDIR)/extern/$(LIBNAME) + +BULLETDIRS = \ +LinearMath \ +BulletCollision/BroadphaseCollision \ +BulletCollision/CollisionShapes \ +BulletCollision/NarrowPhaseCollision \ +BulletCollision/CollisionDispatch \ +BulletDynamics/ConstraintSolver \ +BulletDynamics/Vehicle \ +BulletDynamics/Dynamics + +CCSRCS = $(wildcard \ +LinearMath/*.cpp \ +BulletCollision/BroadphaseCollision/*.cpp \ +BulletCollision/CollisionShapes/*.cpp \ +BulletCollision/NarrowPhaseCollision/*.cpp \ +BulletCollision/CollisionDispatch/*.cpp \ +BulletDynamics/ConstraintSolver/*.cpp \ +BulletDynamics/Vehicle/*.cpp \ +BulletDynamics/Dynamics/*.cpp) + +CPPFLAGS += -D_LIB -I. -IBulletCollision -IBulletDynamics -ILinearMath + +all debug:: objdirs + +include nan_compile.mk + +.PHONY: objdirs clean +objdirs: + @for i in $(BULLETDIRS); do \ + [ -d $(DIR)/$(DEBUG_DIR)$$i ] || mkdir -p $(DIR)/$(DEBUG_DIR)$$i; \ + done + +clean:: + rm -rf $(DIR) + rm -rf $(NAN_BULLET2)/lib/libbullet2.a + rm -rf $(NAN_BULLET2)/include diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript new file mode 100644 index 00000000000..19702782b0d --- /dev/null +++ b/extern/bullet2/src/SConscript @@ -0,0 +1,98 @@ +#!/usr/bin/python +import sys +import os + +Import('env') + +defs = 'USE_DOUBLES QHULL _LIB' +cflags = [] + +if env['OURPLATFORM']=='win32-vc': + defs += ' WIN32 NDEBUG _WINDOWS _LIB' + #cflags += ['/MT', '/W3', '/GX', '/O2', '/Op'] + cflags += ['/MT', '/W3', '/GX', '/Og', '/Ot', '/Ob1', '/Op', '/G6'] +elif env['OURPLATFORM']=='win32-mingw': + defs += ' NDEBUG' + cflags += ['-O2'] +elif sys.platform=='linux2' or sys.platform=='linux-i386' or sys.platform=='freebsd4' or sys.platform=='freebsd5': + defs += ' NDEBUG' + cflags += ['-O2'] +elif sys.platform=='darwin': + defs += ' NDEBUG' + cflags += ['-O2','-pipe', '-fPIC', '-funsigned-char', '-ffast-math'] + +linearmath_src = env.Glob("LinearMath/*.cpp") +bulletdyn_src = ["BulletDynamics/ConstraintSolver/btContactConstraint.cpp", + "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp", + "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp", + "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp", + "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp", + "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp", + "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp", + "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp", + "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.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", + "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp", + "BulletCollision/BroadphaseCollision/btDispatcher.cpp", + "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", + "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", + "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp", + "BulletCollision/CollisionDispatch/btCollisionObject.cpp", + "BulletCollision/CollisionDispatch/btCollisionWorld.cpp", + "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btManifoldResult.cpp", + "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp", + "BulletCollision/CollisionDispatch/btUnionFind.cpp", + "BulletCollision/CollisionShapes/btBoxShape.cpp", + "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp", + "BulletCollision/CollisionShapes/btCollisionShape.cpp", + "BulletCollision/CollisionShapes/btCompoundShape.cpp", + "BulletCollision/CollisionShapes/btConcaveShape.cpp", + "BulletCollision/CollisionShapes/btConeShape.cpp", + "BulletCollision/CollisionShapes/btConvexHullShape.cpp", + "BulletCollision/CollisionShapes/btConvexShape.cpp", + "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp", + "BulletCollision/CollisionShapes/btCylinderShape.cpp", + "BulletCollision/CollisionShapes/btEmptyShape.cpp", + "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp", + "BulletCollision/CollisionShapes/btMultiSphereShape.cpp", + "BulletCollision/CollisionShapes/btOptimizedBvh.cpp", + "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp", + "BulletCollision/CollisionShapes/btTetrahedronShape.cpp", + "BulletCollision/CollisionShapes/btSphereShape.cpp", + "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp", + "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp", + "BulletCollision/CollisionShapes/btTriangleCallback.cpp", + "BulletCollision/CollisionShapes/btTriangleBuffer.cpp", + "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp", + "BulletCollision/CollisionShapes/btTriangleMesh.cpp", + "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp", + "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp", + "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp", + "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp", + "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp", + "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp", + "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp", + "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp", + "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp"] + +incs = '. BulletCollision BulletDynamics LinearMath' + +env.BlenderLib ( libname = 'extern_bullet2linmath', sources=linearmath_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) +env.BlenderLib ( libname = 'extern_bullet2dynamics', sources=bulletdyn_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[19, 169], compileflags=cflags ) +env.BlenderLib ( libname = 'extern_bullet2collision', sources=collision_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) diff --git a/extern/bullet2/src/btBulletCollisionCommon.h b/extern/bullet2/src/btBulletCollisionCommon.h new file mode 100644 index 00000000000..8417ccc671f --- /dev/null +++ b/extern/bullet2/src/btBulletCollisionCommon.h @@ -0,0 +1,61 @@ +/* +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. +*/ + +#ifndef BULLET_COLLISION_COMMON_H +#define BULLET_COLLISION_COMMON_H + +///Common headerfile includes for Bullet Collision Detection + +///Bullet's btCollisionWorld and btCollisionObject definitions +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" + +///Collision Shapes +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btCapsuleShape.h" +#include "BulletCollision/CollisionShapes/btCylinderShape.h" +#include "BulletCollision/CollisionShapes/btConeShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" +#include "BulletCollision/CollisionShapes/btTriangleMesh.h" +#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "BulletCollision/CollisionShapes/btEmptyShape.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" + +///Narrowphase Collision Detector +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" + +///Dispatching and generation of collision pairs (broadphase) +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" + + +///Math library & Utils +#include "LinearMath/btQuaternion.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btDefaultMotionState.h" +#include "LinearMath/btQuickprof.h" +#include "LinearMath/btIDebugDraw.h" + +#endif //BULLET_COLLISION_COMMON_H + diff --git a/extern/bullet2/src/btBulletDynamicsCommon.h b/extern/bullet2/src/btBulletDynamicsCommon.h new file mode 100644 index 00000000000..25f016cba8a --- /dev/null +++ b/extern/bullet2/src/btBulletDynamicsCommon.h @@ -0,0 +1,42 @@ +/* +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. +*/ + +#ifndef BULLET_DYNAMICS_COMMON_H +#define BULLET_DYNAMICS_COMMON_H + +///Common headerfile includes for Bullet Dynamics, including Collision Detection +#include "btBulletCollisionCommon.h" + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" +#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" +#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" +#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" + + +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +///Vehicle simulation, with wheel contact simulated by raycasts +#include "BulletDynamics/Vehicle/btRaycastVehicle.h" + + + + + + +#endif //BULLET_DYNAMICS_COMMON_H + From a68c03e409e01285bee622b12313117012e486a8 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 7 May 2008 20:42:16 +0000 Subject: [PATCH 088/101] Reason of all this work: Commiting my work-in-progress on reviewed collision system (better + general access to kdop, uses less memory, put it into BLI_* namespace and usage defined like existing BLI_kdtree_*). Deleted old kdop.c --- intern/sph/SConscript | 11 + intern/sph/extern/sph_extern.h | 51 ++ intern/sph/intern/sph.cpp | 51 ++ source/blender/blenkernel/BKE_cloth.h | 20 +- source/blender/blenkernel/BKE_collision.h | 36 +- source/blender/blenkernel/BKE_effect.h | 1 + source/blender/blenkernel/BKE_sph.h | 69 ++ source/blender/blenkernel/CCGSubSurf.h | 152 ++++ source/blender/blenkernel/SConscript | 1 + source/blender/blenkernel/bmesh_private.h | 71 ++ source/blender/blenkernel/intern/cloth.c | 126 +-- source/blender/blenkernel/intern/collision.c | 684 ++++++++------- source/blender/blenkernel/intern/kdop.c | 860 ------------------- source/blender/blenkernel/intern/modifier.c | 125 ++- source/blender/blenkernel/intern/sph.c | 490 +++++++++++ source/blender/blenlib/BLI_kdopbvh.h | 63 ++ source/blender/blenlib/intern/BLI_kdopbvh.c | 786 +++++++++++++++++ source/blender/blenloader/intern/readfile.c | 20 +- source/blender/include/butspace.h | 4 + source/blender/makesdna/DNA_modifier_types.h | 11 +- source/blender/makesdna/DNA_sph_types.h | 102 +++ source/blender/src/buttons_editing.c | 8 +- source/blender/src/buttons_object.c | 136 +++ source/blender/src/drawobject.c | 22 +- 24 files changed, 2614 insertions(+), 1286 deletions(-) create mode 100644 intern/sph/SConscript create mode 100644 intern/sph/extern/sph_extern.h create mode 100644 intern/sph/intern/sph.cpp create mode 100644 source/blender/blenkernel/BKE_sph.h create mode 100644 source/blender/blenkernel/CCGSubSurf.h create mode 100644 source/blender/blenkernel/bmesh_private.h delete mode 100644 source/blender/blenkernel/intern/kdop.c create mode 100644 source/blender/blenkernel/intern/sph.c create mode 100644 source/blender/blenlib/BLI_kdopbvh.h create mode 100644 source/blender/blenlib/intern/BLI_kdopbvh.c create mode 100644 source/blender/makesdna/DNA_sph_types.h diff --git a/intern/sph/SConscript b/intern/sph/SConscript new file mode 100644 index 00000000000..52243f767c3 --- /dev/null +++ b/intern/sph/SConscript @@ -0,0 +1,11 @@ +#!/usr/bin/python +import sys +import os +Import('env') + +sources = env.Glob('intern/*.cpp') + +incs = ' . extern intern' +defs = '' + +env.BlenderLib ('bf_sph', sources, Split(incs), Split(defs), libtype='blender', priority=0 ) diff --git a/intern/sph/extern/sph_extern.h b/intern/sph/extern/sph_extern.h new file mode 100644 index 00000000000..b4964739212 --- /dev/null +++ b/intern/sph/extern/sph_extern.h @@ -0,0 +1,51 @@ +/** + * ***** 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): Daniel Genrich. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef PW_EXTERN_H +#define PW_EXTERN_H + + + +#ifdef __cplusplus +extern "C" { +#endif +/* +void sph_init_cpp(struct SphModifierData *sphmd); +void sph_free_cpp(struct SphModifierData *sphmd); +int sph_simulate_cpp(struct Object *ob, struct SphModifierData *sphmd, float frame, struct ListBase *effectors); +*/ +#ifdef __cplusplus +} +#endif + + +#endif //PW_EXTERN_H + + diff --git a/intern/sph/intern/sph.cpp b/intern/sph/intern/sph.cpp new file mode 100644 index 00000000000..f7afa3c34eb --- /dev/null +++ b/intern/sph/intern/sph.cpp @@ -0,0 +1,51 @@ +/* pw.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. +* +* Contributor(s): Daniel Genrich +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#include + +#include "sph_extern.h" +/* +extern "C" void sph_init_cpp(struct SphModifierData *sphmd) +{ + +} +/* +extern "C" void sph_free_cpp(struct SphModifierData *sphmd) +{ + + +} + +extern "C" int sph_simulate_cpp(struct Object *ob, struct SphModifierData *sphmd, float frame, struct ListBase *effectors) +{ + + return 1; +} +*/ diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index af920e9762d..f01ed6bbea4 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -24,14 +24,14 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Daniel Genrich. * * ***** END GPL LICENSE BLOCK ***** */ #ifndef BKE_CLOTH_H #define BKE_CLOTH_H -#include "float.h" +#include #include "BLI_linklist.h" #include "BKE_customdata.h" @@ -49,6 +49,9 @@ #include "BKE_collision.h" +#include "RE_raytrace.h" + + struct Object; struct MFace; @@ -102,7 +105,8 @@ typedef struct Cloth 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 BVHTree *bvhtree; /* collision tree for this cloth object */ + struct RayTree *selftree; /* collision tree for this cloth object */ struct MFace *mfaces; struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ struct Implicit_Data *implicitEM; /* our implicit solver connects to this pointer */ @@ -171,17 +175,10 @@ ClothSpring; /* 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_FLAG_AUTOPROTECT = ( 1 << 10 ), /* is autoprotect enabled? */ - //CLOTH_SIMSETTINGS_FLAG_CCACHE_OUTDATED = (1 << 11), /* while protected, did cache get outdated? */ CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12) /* edit cache in editmode */ } CLOTH_SIMSETTINGS_FLAGS; @@ -208,6 +205,7 @@ typedef enum CLOTH_SPRING_FLAG_NEEDED = ( 1 << 2 ), // springs has values to be applied } CLOTH_SPRINGS_FLAGS; + ///////////////////////////////////////////////// // collision.c //////////////////////////////////////////////// @@ -246,7 +244,7 @@ DerivedMesh *clothModifier_do ( ClothModifierData *clmd,Object *ob, DerivedMesh 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 ); +void bvhtree_update_from_cloth ( ClothModifierData *clmd, int moving ); // needed for editmesh.c void cloth_write_cache ( Object *ob, ClothModifierData *clmd, float framenr ); diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index 7328f9108e3..f0298950f8b 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -32,7 +32,7 @@ #define BKE_COLLISIONS_H #include -#include "float.h" +#include #include #include @@ -47,6 +47,8 @@ #include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "BLI_kdopbvh.h" + struct Object; struct Cloth; struct MFace; @@ -102,10 +104,16 @@ BVH; typedef void ( *CM_COLLISION_RESPONSE ) ( ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2 ); // needed for collision.c -int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response, int selfcollision); +int bvh_traverse ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response, int selfcollision ); //////////////////////////////////////// +/* COLLISION FLAGS */ +typedef enum +{ + COLLISION_IN_FUTURE = ( 1 << 1 ), +} COLLISION_FLAGS; + //////////////////////////////////////// // used for collisions in kdop.c and also collision.c @@ -119,10 +127,10 @@ typedef struct CollPair 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 + int flag; float time; // collision time, from 0 up to 1 - unsigned int ap1, ap2, ap3, bp1, bp2, bp3; - unsigned int pointsb[4]; + int ap1, ap2, ap3, bp1, bp2, bp3; + int pointsb[4]; } CollPair; @@ -160,8 +168,9 @@ FaceCollPair; // 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); +void bvh_build ( BVH *bvh ); +BVH *bvh_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon ); +BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon ); // frees the same void bvh_free ( BVH * bvh ); @@ -169,20 +178,21 @@ 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->current_xold (static) +// update bounding volumes, needs updated positions in bvh->current_xold (static) // and also bvh->current_x if moving==1 -void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving); -void bvh_update(BVH * bvh, int moving); +void bvh_update_from_mvert ( BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving ); +void bvh_update ( BVH * bvh, int moving ); +void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, 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); +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); +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 ); ///////////////////////////////////////////////// diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 3763a659f2f..15816699285 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -31,6 +31,7 @@ #ifndef BKE_EFFECT_H #define BKE_EFFECT_H +#include "DNA_effect_types.h" #include "DNA_object_types.h" struct Effect; diff --git a/source/blender/blenkernel/BKE_sph.h b/source/blender/blenkernel/BKE_sph.h new file mode 100644 index 00000000000..9fa42f5acb2 --- /dev/null +++ b/source/blender/blenkernel/BKE_sph.h @@ -0,0 +1,69 @@ +/** + * ***** 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): Daniel Genrich. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_SPH_H +#define BKE_SPH_H + + +#include "BKE_DerivedMesh.h" +#include "BKE_utildefines.h" + +#include "BLI_linklist.h" + +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" + +void sph_init(SphModifierData *sphmd); +void sph_free_modifier (SphModifierData *sphmd); +DerivedMesh *sphModifier_do(SphModifierData *sphmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc); +int sph_init_all (SphModifierData *sphmd, DerivedMesh *dm, Object *ob); + + +/* SIMULATION FLAGS: goal flags,.. */ +/* These are the bits used in SimSettings.flags. */ +// first 16 (short) flags are used for fluid type identification +typedef enum +{ + SPH_SIMSETTINGS_FLAG_FLUID = ( 1 << 0 ), // Fluid object? + SPH_SIMSETTINGS_FLAG_OBSTACLE = ( 1 << 1 ), // Obstacle? + SPH_SIMSETTINGS_FLAG_DOMAIN = ( 1 << 2 ), // Fluid domain + + SPH_SIMSETTINGS_FLAG_GHOSTS = ( 1 << 16 ), // use ghost particles? + SPH_SIMSETTINGS_FLAG_OFFLINE = ( 1 << 17 ), // do offline simulation? + SPH_SIMSETTINGS_FLAG_MULTIRES = ( 1 << 18 ), // use multires? + SPH_SIMSETTINGS_FLAG_VORTICITY = ( 1 << 19 ), // use vorticity enhancement? + SPH_SIMSETTINGS_FLAG_BAKING = ( 1 << 20 ), // is domain baking? + SPH_SIMSETTINGS_FLAG_INIT = ( 1 << 21 ), // inited? +} SPH_SIMSETTINGS_FLAGS; + + +#endif //BKE_SPH_H + + + diff --git a/source/blender/blenkernel/CCGSubSurf.h b/source/blender/blenkernel/CCGSubSurf.h new file mode 100644 index 00000000000..a8269b7ada0 --- /dev/null +++ b/source/blender/blenkernel/CCGSubSurf.h @@ -0,0 +1,152 @@ +/* $Id: CCGSubSurf.h 12931 2007-12-17 18:20:48Z theeth $ */ + +typedef void* CCGMeshHDL; +typedef void* CCGVertHDL; +typedef void* CCGEdgeHDL; +typedef void* CCGFaceHDL; + +typedef struct _CCGVert CCGVert; +typedef struct _CCGEdge CCGEdge; +typedef struct _CCGFace CCGFace; + +typedef struct _CCGMeshIFC CCGMeshIFC; +struct _CCGMeshIFC { + int vertUserSize, edgeUserSize, faceUserSize; + + int vertDataSize; +}; + +/***/ + +typedef void* CCGAllocatorHDL; + +typedef struct _CCGAllocatorIFC CCGAllocatorIFC; +struct _CCGAllocatorIFC { + void* (*alloc) (CCGAllocatorHDL a, int numBytes); + void* (*realloc) (CCGAllocatorHDL a, void *ptr, int newSize, int oldSize); + void (*free) (CCGAllocatorHDL a, void *ptr); + void (*release) (CCGAllocatorHDL a); +}; + +/***/ + +typedef enum { + eCCGError_None = 0, + + eCCGError_InvalidSyncState, + eCCGError_InvalidValue, +} CCGError; + +/***/ + +typedef struct _CCGSubSurf CCGSubSurf; + +CCGSubSurf* ccgSubSurf_new (CCGMeshIFC *ifc, int subdivisionLevels, CCGAllocatorIFC *allocatorIFC, CCGAllocatorHDL allocator); +void ccgSubSurf_free (CCGSubSurf *ss); + +CCGError ccgSubSurf_sync (CCGSubSurf *ss); + +CCGError ccgSubSurf_initFullSync (CCGSubSurf *ss); +CCGError ccgSubSurf_initPartialSync (CCGSubSurf *ss); + +CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r); +CCGError ccgSubSurf_syncEdge (CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r); +CCGError ccgSubSurf_syncFace (CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r); + +CCGError ccgSubSurf_syncVertDel (CCGSubSurf *ss, CCGVertHDL vHDL); +CCGError ccgSubSurf_syncEdgeDel (CCGSubSurf *ss, CCGEdgeHDL eHDL); +CCGError ccgSubSurf_syncFaceDel (CCGSubSurf *ss, CCGFaceHDL fHDL); + +CCGError ccgSubSurf_processSync (CCGSubSurf *ss); + +CCGError ccgSubSurf_setSubdivisionLevels (CCGSubSurf *ss, int subdivisionLevels); + +CCGError ccgSubSurf_setAllowEdgeCreation (CCGSubSurf *ss, int allowEdgeCreation, float defaultCreaseValue, void *defaultUserData); +void ccgSubSurf_getAllowEdgeCreation (CCGSubSurf *ss, int *allowEdgeCreation_r, float *defaultCreaseValue_r, void *defaultUserData_r); + +void ccgSubSurf_getUseAgeCounts (CCGSubSurf *ss, int *useAgeCounts_r, int *vertUserOffset_r, int *edgeUserOffset_r, int *faceUserOffset_r); +CCGError ccgSubSurf_setUseAgeCounts (CCGSubSurf *ss, int useAgeCounts, int vertUserOffset, int edgeUserOffset, int faceUserOffset); + +CCGError ccgSubSurf_setCalcVertexNormals (CCGSubSurf *ss, int useVertNormals, int normalDataOffset); + +/***/ + +int ccgSubSurf_getNumVerts (CCGSubSurf *ss); +int ccgSubSurf_getNumEdges (CCGSubSurf *ss); +int ccgSubSurf_getNumFaces (CCGSubSurf *ss); + +int ccgSubSurf_getSubdivisionLevels (CCGSubSurf *ss); +int ccgSubSurf_getEdgeSize (CCGSubSurf *ss); +int ccgSubSurf_getEdgeLevelSize (CCGSubSurf *ss, int level); +int ccgSubSurf_getGridSize (CCGSubSurf *ss); +int ccgSubSurf_getGridLevelSize (CCGSubSurf *ss, int level); + +CCGVert* ccgSubSurf_getVert (CCGSubSurf *ss, CCGVertHDL v); +CCGVertHDL ccgSubSurf_getVertVertHandle (CCGSubSurf *ss, CCGVert *v); +int ccgSubSurf_getVertNumFaces (CCGSubSurf *ss, CCGVert *v); +CCGFace* ccgSubSurf_getVertFace (CCGSubSurf *ss, CCGVert *v, int index); +int ccgSubSurf_getVertNumEdges (CCGSubSurf *ss, CCGVert *v); +CCGEdge* ccgSubSurf_getVertEdge (CCGSubSurf *ss, CCGVert *v, int index); + +int ccgSubSurf_getVertAge (CCGSubSurf *ss, CCGVert *v); +void* ccgSubSurf_getVertUserData (CCGSubSurf *ss, CCGVert *v); +void* ccgSubSurf_getVertData (CCGSubSurf *ss, CCGVert *v); +void* ccgSubSurf_getVertLevelData (CCGSubSurf *ss, CCGVert *v, int level); + +CCGEdge* ccgSubSurf_getEdge (CCGSubSurf *ss, CCGEdgeHDL e); +CCGEdgeHDL ccgSubSurf_getEdgeEdgeHandle (CCGSubSurf *ss, CCGEdge *e); +int ccgSubSurf_getEdgeNumFaces (CCGSubSurf *ss, CCGEdge *e); +CCGFace* ccgSubSurf_getEdgeFace (CCGSubSurf *ss, CCGEdge *e, int index); +CCGVert* ccgSubSurf_getEdgeVert0 (CCGSubSurf *ss, CCGEdge *e); +CCGVert* ccgSubSurf_getEdgeVert1 (CCGSubSurf *ss, CCGEdge *e); +float ccgSubSurf_getEdgeCrease (CCGSubSurf *ss, CCGEdge *e); + +int ccgSubSurf_getEdgeAge (CCGSubSurf *ss, CCGEdge *e); +void* ccgSubSurf_getEdgeUserData (CCGSubSurf *ss, CCGEdge *e); +void* ccgSubSurf_getEdgeDataArray (CCGSubSurf *ss, CCGEdge *e); +void* ccgSubSurf_getEdgeData (CCGSubSurf *ss, CCGEdge *e, int x); +void* ccgSubSurf_getEdgeLevelData (CCGSubSurf *ss, CCGEdge *e, int x, int level); + +CCGFace* ccgSubSurf_getFace (CCGSubSurf *ss, CCGFaceHDL f); +CCGFaceHDL ccgSubSurf_getFaceFaceHandle (CCGSubSurf *ss, CCGFace *f); +int ccgSubSurf_getFaceNumVerts (CCGSubSurf *ss, CCGFace *f); +CCGVert* ccgSubSurf_getFaceVert (CCGSubSurf *ss, CCGFace *f, int index); +CCGEdge* ccgSubSurf_getFaceEdge (CCGSubSurf *ss, CCGFace *f, int index); +int ccgSubSurf_getFaceEdgeIndex (CCGSubSurf *ss, CCGFace *f, CCGEdge *e); + +int ccgSubSurf_getFaceAge (CCGSubSurf *ss, CCGFace *f); +void* ccgSubSurf_getFaceUserData (CCGSubSurf *ss, CCGFace *f); +void* ccgSubSurf_getFaceCenterData (CCGSubSurf *ss, CCGFace *f); +void* ccgSubSurf_getFaceGridEdgeDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex); +void* ccgSubSurf_getFaceGridEdgeData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x); +void* ccgSubSurf_getFaceGridDataArray (CCGSubSurf *ss, CCGFace *f, int gridIndex); +void* ccgSubSurf_getFaceGridData (CCGSubSurf *ss, CCGFace *f, int gridIndex, int x, int y); + +int ccgSubSurf_getNumFinalVerts (CCGSubSurf *ss); +int ccgSubSurf_getNumFinalEdges (CCGSubSurf *ss); +int ccgSubSurf_getNumFinalFaces (CCGSubSurf *ss); + +/***/ + +typedef struct _CCGVertIterator CCGVertIterator; +typedef struct _CCGEdgeIterator CCGEdgeIterator; +typedef struct _CCGFaceIterator CCGFaceIterator; + +CCGVertIterator* ccgSubSurf_getVertIterator (CCGSubSurf *ss); +CCGEdgeIterator* ccgSubSurf_getEdgeIterator (CCGSubSurf *ss); +CCGFaceIterator* ccgSubSurf_getFaceIterator (CCGSubSurf *ss); + +CCGVert* ccgVertIterator_getCurrent (CCGVertIterator *vi); +int ccgVertIterator_isStopped (CCGVertIterator *vi); +void ccgVertIterator_next (CCGVertIterator *vi); +void ccgVertIterator_free (CCGVertIterator *vi); + +CCGEdge* ccgEdgeIterator_getCurrent (CCGEdgeIterator *ei); +int ccgEdgeIterator_isStopped (CCGEdgeIterator *ei); +void ccgEdgeIterator_next (CCGEdgeIterator *ei); +void ccgEdgeIterator_free (CCGEdgeIterator *ei); + +CCGFace* ccgFaceIterator_getCurrent (CCGFaceIterator *fi); +int ccgFaceIterator_isStopped (CCGFaceIterator *fi); +void ccgFaceIterator_next (CCGFaceIterator *fi); +void ccgFaceIterator_free (CCGFaceIterator *fi); diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 1bb98239a68..4f77e4f42a7 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -10,6 +10,7 @@ incs += ' #/intern/iksolver/extern ../blenloader ../quicktime' incs += ' #/extern/bullet2/src' incs += ' #/intern/bmfont' incs += ' #/intern/opennl/extern' +incs += ' #/intern/sph/extern' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_OPENGL_INC'] diff --git a/source/blender/blenkernel/bmesh_private.h b/source/blender/blenkernel/bmesh_private.h new file mode 100644 index 00000000000..ad90398bf66 --- /dev/null +++ b/source/blender/blenkernel/bmesh_private.h @@ -0,0 +1,71 @@ +/** + * BME_private.h jan 2007 + * + * low level, 'private' function prototypes for bmesh kernel. + * + * $Id: BKE_bmesh.h,v 1.00 2007/01/17 17:42:01 Briggs Exp $ + * + * ***** BEGIN GPL 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) 2004 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Geoffrey Bantle. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BMESH_PRIVATE +#define BMESH_PRIVATE + +#include "BKE_bmesh.h" + +/*ALLOCATION/DEALLOCATION*/ +struct BME_Vert *BME_addvertlist(struct BME_Mesh *bm, struct BME_Vert *example); +struct BME_Edge *BME_addedgelist(struct BME_Mesh *bm, struct BME_Vert *v1, struct BME_Vert *v2, struct BME_Edge *example); +struct BME_Poly *BME_addpolylist(struct BME_Mesh *bm, struct BME_Poly *example); +struct BME_Loop *BME_create_loop(struct BME_Mesh *bm, struct BME_Vert *v, struct BME_Edge *e, struct BME_Poly *f, struct BME_Loop *example); + +void BME_free_vert(struct BME_Mesh *bm, struct BME_Vert *v); +void BME_free_edge(struct BME_Mesh *bm, struct BME_Edge *e); +void BME_free_poly(struct BME_Mesh *bm, struct BME_Poly *f); +void BME_free_loop(struct BME_Mesh *bm, struct BME_Loop *l); +void BME_delete_loop(struct BME_Mesh *bm, struct BME_Loop *l); + +/*DOUBLE CIRCULAR LINKED LIST FUNCTIONS*/ +void BME_cycle_append(void *h, void *nt); +int BME_cycle_remove(void *h, void *remn); +int BME_cycle_validate(int len, void *h); +/*DISK CYCLE MANAGMENT*/ +int BME_disk_append_edge(struct BME_Edge *e, struct BME_Vert *v); +void BME_disk_remove_edge(struct BME_Edge *e, struct BME_Vert *v); +/*RADIAL CYCLE MANAGMENT*/ +void BME_radial_append(struct BME_Edge *e, struct BME_Loop *l); +void BME_radial_remove_loop(struct BME_Loop *l, struct BME_Edge *e); + +/*MISC FUNCTIONS*/ +int BME_edge_swapverts(struct BME_Edge *e, struct BME_Vert *orig, struct BME_Vert *new); /*relink edge*/ +int BME_disk_hasedge(struct BME_Vert *v, struct BME_Edge *e); + +/*Error reporting. Shouldnt be called by tools ever.*/ +void BME_error(void); +#endif diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 4be4434dfda..192ebd90faa 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -45,6 +45,8 @@ #include "BKE_pointcache.h" +#include "BLI_kdopbvh.h" + #ifdef _WIN32 void tstart ( void ) {} @@ -151,13 +153,14 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->goalfrict = 0.0f; } - -BVH *bvh_build_from_cloth (ClothModifierData *clmd, float epsilon) +BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) { - unsigned int i = 0; - BVH *bvh=NULL; + int i; + BVHTree *bvhtree; Cloth *cloth = clmd->clothObject; - ClothVertex *verts = NULL; + ClothVertex *verts; + MFace *mfaces; + float co[12]; if(!clmd) return NULL; @@ -168,69 +171,86 @@ BVH *bvh_build_from_cloth (ClothModifierData *clmd, float epsilon) return NULL; verts = cloth->verts; + mfaces = cloth->mfaces; // in the moment, return zero if no faces there if(!cloth->numfaces) return NULL; - bvh = MEM_callocN(sizeof(BVH), "BVH"); - if (bvh == NULL) + // create quadtree with k=26 + bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 4, 26); + + // fill tree + for(i = 0; i < cloth->numfaces; i++, mfaces++) { - printf("bvh: Out of memory.\n"); - return NULL; + VECCOPY(&co[0*3], verts[mfaces->v1].xold); + VECCOPY(&co[1*3], verts[mfaces->v2].xold); + VECCOPY(&co[2*3], verts[mfaces->v3].xold); + + if(mfaces->v4) + VECCOPY(&co[3*3], verts[mfaces->v4].xold); + + BLI_bvhtree_insert(bvhtree, i, co, (mfaces->v4 ? 4 : 3)); } - // springs = cloth->springs; - // numsprings = cloth->numsprings; - - bvh->epsilon = epsilon; - bvh->numfaces = cloth->numfaces; - bvh->mfaces = cloth->mfaces; - - bvh->numverts = cloth->numverts; + // balance tree + BLI_bvhtree_balance(bvhtree); - bvh->current_x = MEM_callocN ( sizeof ( MVert ) * bvh->numverts, "bvh->current_x" ); - - if (bvh->current_x == NULL) - { - printf("bvh: Out of memory.\n"); - MEM_freeN(bvh); - return NULL; - } - - for(i = 0; i < bvh->numverts; i++) - { - VECCOPY(bvh->current_x[i].co, verts[i].tx); - } - - bvh_build (bvh); - - return bvh; + return bvhtree; } -void bvh_update_from_cloth(ClothModifierData *clmd, int moving) -{ +void bvhtree_update_from_cloth(ClothModifierData *clmd, int moving) +{ unsigned int i = 0; Cloth *cloth = clmd->clothObject; - BVH *bvh = cloth->tree; + BVHTree *bvhtree = cloth->bvhtree; ClothVertex *verts = cloth->verts; + MFace *mfaces; + float co[12], co_moving[12]; + int ret = 0; - if(!bvh) + if(!bvhtree) return; - if(cloth->numverts!=bvh->numverts) - return; + mfaces = cloth->mfaces; - if(cloth->verts) + // update vertex position in bvh tree + if(verts && mfaces) { - for(i = 0; i < bvh->numverts; i++) + for(i = 0; i < cloth->numfaces; i++, mfaces++) { - VECCOPY(bvh->current_x[i].co, verts[i].tx); - VECCOPY(bvh->current_xold[i].co, verts[i].txold); + VECCOPY(&co[0*3], verts[mfaces->v1].txold); + VECCOPY(&co[1*3], verts[mfaces->v2].txold); + VECCOPY(&co[2*3], verts[mfaces->v3].txold); + + if(mfaces->v4) + VECCOPY(&co[3*3], verts[mfaces->v4].txold); + + // copy new locations into array + if(moving) + { + // update moving positions + VECCOPY(&co_moving[0*3], verts[mfaces->v1].tx); + VECCOPY(&co_moving[1*3], verts[mfaces->v2].tx); + VECCOPY(&co_moving[2*3], verts[mfaces->v3].tx); + + if(mfaces->v4) + VECCOPY(&co_moving[3*3], verts[mfaces->v4].tx); + + ret = BLI_bvhtree_update_node(bvhtree, i, co, co_moving, (mfaces->v4 ? 4 : 3)); + } + else + { + ret = BLI_bvhtree_update_node(bvhtree, i, co, NULL, (mfaces->v4 ? 4 : 3)); + } + + // check if tree is already full + if(!ret) + break; } + + BLI_bvhtree_update_tree(bvhtree); } - - bvh_update(bvh, moving); } int modifiers_indexInObject(Object *ob, ModifierData *md_seek); @@ -541,8 +561,8 @@ void cloth_free_modifier ( Object *ob, ClothModifierData *clmd ) cloth->numsprings = 0; // free BVH collision tree - if ( cloth->tree ) - bvh_free ( ( BVH * ) cloth->tree ); + if ( cloth->bvhtree ) + BLI_bvhtree_free ( cloth->bvhtree ); // we save our faces for collision objects if ( cloth->mfaces ) @@ -611,8 +631,8 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd ) cloth->numsprings = 0; // free BVH collision tree - if ( cloth->tree ) - bvh_free ( ( BVH * ) cloth->tree ); + if ( cloth->bvhtree ) + BLI_bvhtree_free ( cloth->bvhtree ); // we save our faces for collision objects if ( cloth->mfaces ) @@ -810,6 +830,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d VECCOPY ( verts->xold, verts->x ); VECCOPY ( verts->xconst, verts->x ); VECCOPY ( verts->txold, verts->x ); + VECCOPY ( verts->tx, verts->x ); VecMulf ( verts->v, 0.0f ); verts->impulse_count = 0; @@ -845,12 +866,11 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if(!first) implicit_set_positions(clmd); - clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); - + clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); + return 1; } - static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) { unsigned int numverts = dm->getNumVerts ( dm ); diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index e244ccca306..f3637b4dda2 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -41,7 +41,6 @@ #include "BKE_global.h" #include "BKE_mesh.h" #include "BKE_object.h" -#include "BKE_cloth.h" #include "BKE_modifier.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" @@ -49,6 +48,38 @@ #include "Bullet-C-Api.h" +#include "BLI_kdopbvh.h" +#include "BKE_collision.h" + +#ifdef _WIN32 +static void start ( void ) +{} +static void end ( void ) +{ +} +static double val() +{ + return 0; +} +#else +#include +static void mystart ( struct timeval *start, struct timezone *z ) +{ + gettimeofday ( start, z ); +} +static void myend ( struct timeval *end, struct timezone *z ) +{ + gettimeofday ( end,z ); +} +static double myval ( struct timeval *start, struct timeval *end ) +{ + double t1, t2; + t1 = ( double ) start->tv_sec + ( double ) start->tv_usec/ ( 1000*1000 ); + t2 = ( double ) end->tv_sec + ( double ) end->tv_usec/ ( 1000*1000 ); + return t2-t1; +} +#endif + /*********************************** Collision modifier code start ***********************************/ @@ -66,58 +97,80 @@ void collision_move_object ( CollisionModifierData *collmd, float step, float pr VECADDS ( collmd->current_xnew[i].co, collmd->x[i].co, tv, step ); VECSUB ( collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co ); } - bvh_update_from_mvert ( collmd->bvh, collmd->current_x, collmd->numverts, collmd->current_xnew, 1 ); + bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 ); } -/* build bounding volume hierarchy from mverts (see kdop.c for whole BVH code) */ -BVH *bvh_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon ) +BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon ) { - BVH *bvh=NULL; + BVHTree *tree; + float co[12]; + int i; + MFace *tface = mfaces; - bvh = MEM_callocN ( sizeof ( BVH ), "BVH" ); - if ( bvh == NULL ) + tree = BLI_bvhtree_new ( numfaces*2, epsilon, 4, 26 ); + + // fill tree + for ( i = 0; i < numfaces; i++, tface++ ) { - printf ( "bvh: Out of memory.\n" ); - return NULL; + VECCOPY ( &co[0*3], x[tface->v1].co ); + VECCOPY ( &co[1*3], x[tface->v2].co ); + VECCOPY ( &co[2*3], x[tface->v3].co ); + if ( tface->v4 ) + VECCOPY ( &co[3*3], x[tface->v4].co ); + + BLI_bvhtree_insert ( tree, i, co, ( mfaces->v4 ? 4 : 3 ) ); } - // in the moment, return zero if no faces there - if ( !numfaces ) - return NULL; + // balance tree + BLI_bvhtree_balance ( tree ); - bvh->epsilon = epsilon; - bvh->numfaces = numfaces; - bvh->mfaces = mfaces; - - // we have no faces, we save seperate points - if ( !mfaces ) - { - bvh->numfaces = numverts; - } - - bvh->numverts = numverts; - bvh->current_x = MEM_dupallocN ( x ); - - bvh_build ( bvh ); - - return bvh; + return tree; } -void bvh_update_from_mvert ( BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving ) +void bvhtree_update_from_mvert ( BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int numverts, int moving ) { - if ( !bvh ) - return; + int i; + MFace *mfaces = faces; + float co[12], co_moving[12]; + int ret = 0; - if ( numverts!=bvh->numverts ) + if ( !bvhtree ) return; if ( x ) - memcpy ( bvh->current_xold, x, sizeof ( MVert ) * numverts ); + { + for ( i = 0; i < numfaces; i++, mfaces++ ) + { + VECCOPY ( &co[0*3], x[mfaces->v1].co ); + VECCOPY ( &co[1*3], x[mfaces->v2].co ); + VECCOPY ( &co[2*3], x[mfaces->v3].co ); + if ( mfaces->v4 ) + VECCOPY ( &co[3*3], x[mfaces->v4].co ); - if ( xnew ) - memcpy ( bvh->current_x, xnew, sizeof ( MVert ) * numverts ); + // copy new locations into array + if ( moving && xnew ) + { + // update moving positions + VECCOPY ( &co_moving[0*3], xnew[mfaces->v1].co ); + VECCOPY ( &co_moving[1*3], xnew[mfaces->v2].co ); + VECCOPY ( &co_moving[2*3], xnew[mfaces->v3].co ); + if ( mfaces->v4 ) + VECCOPY ( &co_moving[3*3], xnew[mfaces->v4].co ); - bvh_update ( bvh, moving ); + ret = BLI_bvhtree_update_node ( bvhtree, i, co, co_moving, ( mfaces->v4 ? 4 : 3 ) ); + } + else + { + ret = BLI_bvhtree_update_node ( bvhtree, i, co, NULL, ( mfaces->v4 ? 4 : 3 ) ); + } + + // check if tree is already full + if ( !ret ) + break; + } + + BLI_bvhtree_update_tree ( bvhtree ); + } } /*********************************** @@ -157,11 +210,11 @@ int gsl_poly_solve_cubic ( float a, float b, float c, float *x0, float *x1, floa else if ( CR2 == CQ3 ) { /* this test is actually R2 == Q3, written in a form suitable - for exact computation with integers */ + for exact computation with integers */ /* Due to finite precision some float roots may be missed, and - considered to be a pair of complex roots z = x +/- epsilon i - close to the real axis. */ + considered to be a pair of complex roots z = x +/- epsilon i + close to the real axis. */ float sqrtQ = sqrt ( Q ); @@ -419,24 +472,22 @@ DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float VECADDMUL ( to, v3, w3 ); } -int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd ) +int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { int result = 0; - LinkNode *search = NULL; - CollPair *collpair = NULL; Cloth *cloth1; float w1, w2, w3, u1, u2, u3; float v1[3], v2[3], relativeVelocity[3]; float magrelVel; - float epsilon2 = collmd->bvh->epsilon; + float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); cloth1 = clmd->clothObject; - search = clmd->coll_parms->collision_list; - - while ( search ) + for ( ; collpair != collision_end; collpair++ ) { - collpair = search->link; + // only handle static collisions here + if ( collpair->flag & COLLISION_IN_FUTURE ) + continue; // compute barycentric coordinates for both collision points collision_compute_barycentric ( collpair->pa, @@ -530,8 +581,6 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier result = 1; } - - search = search->next; } @@ -549,51 +598,46 @@ int cloth_collision_response_moving_edges ( ClothModifierData *clmd, ClothModifi return 1; } -void cloth_collision_static ( ModifierData *md1, ModifierData *md2, CollisionTree *tree1, CollisionTree *tree2 ) +//Determines collisions on overlap, collisions are writen to collpair[i] and collision+number_collision_found is returned +CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair ) { ClothModifierData *clmd = ( ClothModifierData * ) md1; CollisionModifierData *collmd = ( CollisionModifierData * ) md2; - CollPair *collpair = NULL; - Cloth *cloth1=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL; + MFace *face1=NULL, *face2 = NULL; + ClothVertex *verts1 = clmd->clothObject->verts; double distance = 0; - float epsilon = clmd->coll_parms->epsilon; - float epsilon2 = ( ( CollisionModifierData * ) md2 )->bvh->epsilon; - unsigned int i = 0; + float epsilon1 = clmd->coll_parms->epsilon; + float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); + int i; + face1 = & ( clmd->clothObject->mfaces[overlap->indexA] ); + face2 = & ( collmd->mfaces[overlap->indexB] ); + + // check all 4 possible collisions for ( i = 0; i < 4; i++ ) { - collpair = ( CollPair * ) MEM_callocN ( sizeof ( CollPair ), "cloth coll pair" ); - - cloth1 = clmd->clothObject; - - verts1 = cloth1->verts; - - face1 = & ( cloth1->mfaces[tree1->tri_index] ); - face2 = & ( collmd->mfaces[tree2->tri_index] ); - - // check all possible pairs of triangles if ( i == 0 ) { + // fill faceA collpair->ap1 = face1->v1; collpair->ap2 = face1->v2; collpair->ap3 = face1->v3; + // fill faceB collpair->bp1 = face2->v1; collpair->bp2 = face2->v2; collpair->bp3 = face2->v3; - } - - if ( i == 1 ) + else if ( i == 1 ) { if ( face1->v4 ) { - collpair->ap1 = face1->v3; + // fill faceA + collpair->ap1 = face1->v1; collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; + collpair->ap3 = face1->v3; + // fill faceB collpair->bp1 = face2->v1; collpair->bp2 = face2->v2; collpair->bp3 = face2->v3; @@ -601,235 +645,215 @@ void cloth_collision_static ( ModifierData *md1, ModifierData *md2, CollisionTre else i++; } - if ( i == 2 ) { if ( face2->v4 ) { + // fill faceA collpair->ap1 = face1->v1; collpair->ap2 = face1->v2; collpair->ap3 = face1->v3; - collpair->bp1 = face2->v3; + // fill faceB + collpair->bp1 = face2->v1; collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; + collpair->bp3 = face2->v3; } else - i+=2; + break; } - - if ( i == 3 ) + else if ( i == 3 ) { - if ( ( face1->v4 ) && ( face2->v4 ) ) + if ( face1->v4 && face2->v4 ) { - collpair->ap1 = face1->v3; + // fill faceA + collpair->ap1 = face1->v1; collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; + collpair->ap3 = face1->v3; - collpair->bp1 = face2->v3; + // fill faceB + collpair->bp1 = face2->v1; collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; + collpair->bp3 = face2->v3; } else - i++; + break; } - // calc SIPcode (?) - - if ( i < 4 ) - { - // calc distance + normal #ifdef WITH_BULLET - distance = plNearestPoints ( - verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector ); + // calc distance + normal + distance = plNearestPoints ( + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector ); #else - // just be sure that we don't add anything - distance = 2.0 * ( epsilon + epsilon2 + ALMOST_ZERO ); + // just be sure that we don't add anything + distance = 2.0 * ( epsilon1 + epsilon2 + ALMOST_ZERO ); #endif - if ( distance <= ( epsilon + epsilon2 + ALMOST_ZERO ) ) - { - // printf("dist: %f\n", (float)distance); - // collpair->face1 = tree1->tri_index; - // collpair->face2 = tree2->tri_index; + if ( distance <= ( epsilon1 + epsilon2 + ALMOST_ZERO ) ) + { + VECCOPY ( collpair->normal, collpair->vector ); + Normalize ( collpair->normal ); - VECCOPY ( collpair->normal, collpair->vector ); - Normalize ( collpair->normal ); - - collpair->distance = distance; - BLI_linklist_prepend ( &clmd->coll_parms->collision_list, collpair ); - - } - else - { - MEM_freeN ( collpair ); - } + collpair->distance = distance; + collpair->flag = 0; } else { - MEM_freeN ( collpair ); + // check for collision in the future + collpair->flag |= COLLISION_IN_FUTURE; } + collpair++; } + return collpair; } -int cloth_are_edges_adjacent ( ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair ) +int cloth_are_edges_adjacent ( ClothModifierData *clmd, CollisionModifierData *collmd, EdgeCollPair *edgecollpair ) { - Cloth *cloth1 = NULL, *cloth2 = NULL; - ClothVertex *verts1 = NULL, *verts2 = NULL; + Cloth *cloth1 = NULL; + ClothVertex *verts1 = NULL; float temp[3]; + MVert *verts2 = collmd->current_x; // old x cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - verts1 = cloth1->verts; - verts2 = cloth2->verts; - VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold ); + VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold ); + VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold ); + VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold ); + VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; return 0; } -void cloth_collision_moving_edges ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 ) +void cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) { EdgeCollPair edgecollpair; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; + Cloth *cloth1=NULL; + ClothVertex *verts1=NULL; unsigned int i = 0, j = 0, k = 0; int numsolutions = 0; float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; + MVert *verts2 = collmd->current_x; // old x + MVert *velocity2 = collmd->current_v; // velocity + float mintime = 0; cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - verts1 = cloth1->verts; - verts2 = cloth2->verts; - face1 = & ( cloth1->mfaces[tree1->tri_index] ); - face2 = & ( cloth2->mfaces[tree2->tri_index] ); - - for ( i = 0; i < 5; i++ ) + for(i = 0; i < 9; i++) { - if ( i == 0 ) + // 9 edge - edge possibilities + + if(i == 0) // cloth edge: 1-2; coll edge: 1-2 { - edgecollpair.p11 = face1->v1; - edgecollpair.p12 = face1->v2; + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap2; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp2; } - else if ( i == 1 ) + else if(i == 1) // cloth edge: 1-2; coll edge: 2-3 { - edgecollpair.p11 = face1->v2; - edgecollpair.p12 = face1->v3; + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap2; + + edgecollpair.p21 = collpair->bp2; + edgecollpair.p22 = collpair->bp3; } - else if ( i == 2 ) + else if(i == 2) // cloth edge: 1-2; coll edge: 1-3 { - if ( face1->v4 ) - { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v4; - } - else - { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v1; - i+=5; // get out of here after this edge pair is handled - } + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap2; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp3; } - else if ( i == 3 ) + else if(i == 3) // cloth edge: 2-3; coll edge: 1-2 { - if ( face1->v4 ) - { - edgecollpair.p11 = face1->v4; - edgecollpair.p12 = face1->v1; - } - else - continue; + edgecollpair.p11 = collpair->ap2; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp2; } - else + else if(i == 4) // cloth edge: 2-3; coll edge: 2-3 { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v1; + edgecollpair.p11 = collpair->ap2; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp2; + edgecollpair.p22 = collpair->bp3; } - - - for ( j = 0; j < 5; j++ ) + else if(i == 5) // cloth edge: 2-3; coll edge: 1-3 { - if ( j == 0 ) + edgecollpair.p11 = collpair->ap2; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp3; + } + else if(i ==6) // cloth edge: 1-3; coll edge: 1-2 + { + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp2; + } + else if(i ==7) // cloth edge: 1-3; coll edge: 2-3 + { + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp2; + edgecollpair.p22 = collpair->bp3; + } + else if(i == 8) // cloth edge: 1-3; coll edge: 1-3 + { + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap3; + + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp3; + } + + if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) ) + { + // always put coll points in p21/p22 + VECSUB ( a, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold ); + VECSUB ( b, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv ); + VECSUB ( c, verts2[edgecollpair.p21].co, verts1[edgecollpair.p11].txold ); + VECSUB ( d, velocity2[edgecollpair.p21].co, verts1[edgecollpair.p11].tv ); + VECSUB ( e, verts2[edgecollpair.p22].co, verts1[edgecollpair.p11].txold ); + VECSUB ( f, velocity2[edgecollpair.p22].co, verts1[edgecollpair.p11].v ); + + numsolutions = cloth_get_collision_time ( a, b, c, d, e, f, solution ); + + for ( k = 0; k < numsolutions; k++ ) { - edgecollpair.p21 = face2->v1; - edgecollpair.p22 = face2->v2; - } - else if ( j == 1 ) - { - edgecollpair.p21 = face2->v2; - edgecollpair.p22 = face2->v3; - } - else if ( j == 2 ) - { - if ( face2->v4 ) + if ( ( solution[k] >= 0.0 ) && ( solution[k] <= 1.0 ) ) { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v4; - } - else - { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v1; - } - } - else if ( j == 3 ) - { - if ( face2->v4 ) - { - edgecollpair.p21 = face2->v4; - edgecollpair.p22 = face2->v1; - } - else - continue; - } - else - { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v1; - } - - - if ( !cloth_are_edges_adjacent ( clmd, coll_clmd, &edgecollpair ) ) - { - VECSUB ( a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold ); - VECSUB ( b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v ); - VECSUB ( c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold ); - VECSUB ( d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v ); - VECSUB ( e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold ); - VECSUB ( f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v ); - - numsolutions = cloth_get_collision_time ( a, b, c, d, e, f, solution ); - - for ( k = 0; k < numsolutions; k++ ) - { - if ( ( solution[k] >= 0.0 ) && ( solution[k] <= 1.0 ) ) - { - //float out_collisionTime = solution[k]; - - // TODO: check for collisions - - // TODO: put into (edge) collision list - - // printf("Moving edge found!\n"); - } + //float out_collisionTime = solution[k]; + + // TODO: check for collisions + + // TODO: put into (edge) collision list + + mintime = MIN2(mintime, solution[k]); + + printf("Moving edge found!, mintime: %f\n", mintime); + break; } } } @@ -928,6 +952,7 @@ void cloth_collision_moving_tris ( ClothModifierData *clmd, ClothModifierData *c } } +/* void cloth_collision_moving ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 ) { // TODO: check for adjacent @@ -936,51 +961,68 @@ void cloth_collision_moving ( ClothModifierData *clmd, ClothModifierData *coll_c cloth_collision_moving_tris ( clmd, coll_clmd, tree1, tree2 ); cloth_collision_moving_tris ( coll_clmd, clmd, tree2, tree1 ); } +*/ -void cloth_free_collision_list ( ClothModifierData *clmd ) +int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { - // free collision list - if ( clmd->coll_parms->collision_list ) + int result = 0; + Cloth *cloth1; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); + + cloth1 = clmd->clothObject; + + for ( ; collpair != collision_end; collpair++ ) { - LinkNode *search = clmd->coll_parms->collision_list; - while ( search ) - { - CollPair *coll_pair = search->link; - - MEM_freeN ( coll_pair ); - search = search->next; - } - BLI_linklist_free ( clmd->coll_parms->collision_list,NULL ); - - clmd->coll_parms->collision_list = NULL; + // only handle moving collisions here + if (!( collpair->flag & COLLISION_IN_FUTURE )) + continue; + + cloth_collision_moving_edges ( clmd, collmd, collpair); } } int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData *collmd, float step, float dt ) { Cloth *cloth = clmd->clothObject; - BVH *cloth_bvh= ( BVH * ) cloth->tree; + BVHTree *cloth_bvh= ( BVHTree * ) cloth->bvhtree; long i=0, j = 0, numfaces = 0, numverts = 0; ClothVertex *verts = NULL; + CollPair *collisions = NULL, *collisions_index = NULL; int ret = 0; - unsigned int result = 0; + int result = 0; float tnull[3] = {0,0,0}; + BVHTreeOverlap *overlap = NULL; + numfaces = clmd->clothObject->numfaces; numverts = clmd->clothObject->numverts; verts = cloth->verts; - if ( collmd->bvh ) + if ( collmd->bvhtree ) { /* get pointer to bounding volume hierarchy */ - BVH *coll_bvh = collmd->bvh; + BVHTree *coll_bvh = collmd->bvhtree; /* move object to position (step) in time */ collision_move_object ( collmd, step + dt, step ); /* search for overlapping collision pairs */ - bvh_traverse ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static, 0 ); + overlap = BLI_bvhtree_overlap ( cloth_bvh, coll_bvh, &result ); + + collisions = ( CollPair* ) MEM_mallocN ( sizeof ( CollPair ) * result*4, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision + collisions_index = collisions; + + for ( i = 0; i < result; i++ ) + { + collisions_index = cloth_collision ( ( ModifierData * ) clmd, ( ModifierData * ) collmd, overlap+i, collisions_index ); + } + + if ( overlap ) + MEM_freeN ( overlap ); } else { @@ -994,11 +1036,15 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData { result = 0; - if ( collmd->bvh ) - result += cloth_collision_response_static ( clmd, collmd ); + if ( collmd->bvhtree ) + { + result += cloth_collision_response_static ( clmd, collmd, collisions, collisions_index ); + result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); + } // apply impulses in parallel if ( result ) + { for ( i = 0; i < numverts; i++ ) { // calculate "velocities" (just xnew = xold + v; no dt in v) @@ -1011,12 +1057,10 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData ret++; } } - - if ( !result ) - break; + } } - cloth_free_collision_list ( clmd ); + if ( collisions ) MEM_freeN ( collisions ); return ret; } @@ -1028,7 +1072,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) CollisionModifierData *collmd=NULL; Cloth *cloth=NULL; Object *coll_ob=NULL; - BVH *cloth_bvh=NULL; + BVHTree *cloth_bvh=NULL; long i=0, j = 0, numfaces = 0, numverts = 0; unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; @@ -1036,14 +1080,14 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) ClothModifierData *tclmd; int collisions = 0, count = 0; - if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->tree ) ) + if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) || ! ( ( ( Cloth * ) clmd->clothObject )->bvhtree ) ) { return 0; } cloth = clmd->clothObject; verts = cloth->verts; - cloth_bvh = ( BVH * ) cloth->tree; + cloth_bvh = ( BVHTree * ) cloth->bvhtree; numfaces = clmd->clothObject->numfaces; numverts = clmd->clothObject->numverts; @@ -1052,12 +1096,11 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// // update cloth bvh - bvh_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) + bvhtree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) do { result = 0; - clmd->coll_parms->collision_list = NULL; // check all collision objects for ( base = G.scene->base.first; base; base = base->next ) @@ -1126,80 +1169,87 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { + + MFace *mface = clmd->clothObject->mfaces; + collisions = 1; verts = cloth->verts; // needed for openMP + + + /* for ( count = 0; count < clmd->coll_parms->self_loop_count; count++ ) { - if ( collisions ) - { - collisions = 0; -#pragma omp parallel for private(i,j, collisions) shared(verts, ret) - for ( i = 0; i < cloth->numverts; i++ ) - { - for ( j = i + 1; j < cloth->numverts; j++ ) - { - float temp[3]; - float length = 0; - float mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); + if ( collisions ) + { + collisions = 0; + #pragma omp parallel for private(i,j, collisions) shared(verts, ret) + for ( i = 0; i < cloth->numverts; i++ ) + { + for ( j = i + 1; j < cloth->numverts; j++ ) + { + float temp[3]; + float length = 0; + float mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - { - if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) - { - continue; - } - } + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + { + if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) + { + continue; + } + } - VECSUB ( temp, verts[i].tx, verts[j].tx ); + VECSUB ( temp, verts[i].tx, verts[j].tx ); - if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; + if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; // check for adjacent points (i must be smaller j) - if ( BLI_edgehash_haskey ( cloth->edgehash, i, j ) ) - { - continue; - } - - length = Normalize ( temp ); - - if ( length < mindistance ) - { - float correction = mindistance - length; - - if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, -correction ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - } - else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, correction ); - VECADD ( verts[i].tx, verts[i].tx, temp ); - } - else - { - VecMulf ( temp, -correction*0.5 ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - - VECSUB ( verts[i].tx, verts[i].tx, temp ); - } - - collisions = 1; - - if ( !ret ) - { -#pragma omp critical - { - ret = 1; - } - } - } - } - } - } + if ( BLI_edgehash_haskey ( cloth->edgehash, i, j ) ) + { + continue; } + + length = Normalize ( temp ); + + if ( length < mindistance ) + { + float correction = mindistance - length; + + if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, -correction ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + } + else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, correction ); + VECADD ( verts[i].tx, verts[i].tx, temp ); + } + else + { + VecMulf ( temp, -correction*0.5 ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + + VECSUB ( verts[i].tx, verts[i].tx, temp ); + } + + collisions = 1; + + if ( !ret ) + { + #pragma omp critical + { + ret = 1; + } + } + } + } + } + } + } + */ //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c deleted file mode 100644 index 3189fe960ad..00000000000 --- a/source/blender/blenkernel/intern/kdop.c +++ /dev/null @@ -1,860 +0,0 @@ -/* kdop.c -* -* -* ***** BEGIN GPL 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. -* -* 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 LICENSE BLOCK ***** -*/ - -#include "MEM_guardedalloc.h" - -#include "BKE_cloth.h" - -#include "DNA_cloth_types.h" -#include "DNA_mesh_types.h" -#include "DNA_scene_types.h" - -#include "BKE_deform.h" -#include "BKE_DerivedMesh.h" -#include "BKE_cdderivedmesh.h" -#include "BKE_effect.h" -#include "BKE_global.h" -#include "BKE_object.h" -#include "BKE_modifier.h" -#include "BKE_utildefines.h" - -#ifdef _OPENMP -#include -#endif - - -//////////////////////////////////////////////////////////////////////// -// 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}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0}, -{1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0}, -{0, 1.0, -1.0} -}; - -///////////// choose bounding volume here! ///////////// - -#define KDOP_26 - - - -#ifdef KDOP_26 -#define KDOP_END 13 -#define KDOP_START 0 -#endif - -#ifdef KDOP_18 -#define KDOP_END 13 -#define KDOP_START 7 -#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 -*/ -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 -*/ -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; - - if(numfaces >0) - { - // for all Axes. - for (i = KDOP_START; i < KDOP_END; i++) - { - bv[(2 * i)] = (tri [0])->bv[(2 * i)]; - bv[(2 * i) + 1] = (tri [0])->bv[(2 * i) + 1]; - } - } - - 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)])) - { - bv[(2 * i)] = newmin; - } - - newmax = (tri [j])->bv[(2 * i) + 1]; - if ((newmax > bv[(2 * i) + 1])) - { - bv[(2 * i) + 1] = newmax; - } - } - } -} - -DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv, CollisionTree *tree) -{ - 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; - } - } - - /* calculate normal of this face */ - /* (code copied from cdderivedmesh.c) */ - /* - if(tempMFace->v4) - CalcNormFloat4(bvh->current_xold[tempMFace->v1].co, bvh->current_xold[tempMFace->v2].co, - bvh->current_xold[tempMFace->v3].co, bvh->current_xold[tempMFace->v4].co, tree->normal); - else - CalcNormFloat(bvh->current_xold[tempMFace->v1].co, bvh->current_xold[tempMFace->v2].co, - bvh->current_xold[tempMFace->v3].co, tree->normal); - - tree->alpha = 0; - */ - } -} - -DO_INLINE void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv, CollisionTree *tree) -{ - MFace *tempMFace = bvh->mfaces; - float *tempBV = bv; - float newminmax; - int i, j, k; - - /* TODO: calculate normals */ - - 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); - - // maximum is 4 since we have a quad tree - max_nodes = MIN2((end-start + 1 ),4); - - for (i = 0; i < max_nodes; i++) - { - tree->count_nodes++; - - if(end-start+1 > 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; - - bvh->flags = 0; - bvh->leaf_tree = NULL; - bvh->leaf_root = NULL; - bvh->tree = NULL; - - if(!bvh->current_x) - { - bvh_free(bvh); - return; - } - - bvh->current_xold = MEM_dupallocN(bvh->current_x); - - tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree"); - - if (tree == NULL) - { - printf("bvh_build: Out of memory for nodes.\n"); - bvh_free(bvh); - return; - } - - BLI_linklist_append(&bvh->tree, tree); - - nlink = bvh->tree; - - bvh->root = bvh->tree->link; - bvh->root->isleaf = 0; - bvh->root->parent = NULL; - bvh->root->nodes[0] = bvh->root->nodes[1] = bvh->root->nodes[1] = bvh->root->nodes[3] = NULL; - - if(bvh->numfaces<=1) - { - 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, tree); - - // 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_overlap_self - is it possbile for 2 bv's to selfcollide ? -DO_INLINE int bvh_overlap_self(CollisionTree * tree1, CollisionTree * tree2) -{ - // printf("overlap: %f, q: %f\n", (saacos(INPR(tree1->normal, tree2->normal)) / 2.0)+MAX2(tree1->alpha, tree2->alpha), saacos(INPR(tree1->normal, tree2->normal))); - - if((saacos(INPR(tree1->normal, tree2->normal)) / 2.0)+MAX2(tree1->alpha, tree2->alpha) > M_PI) - { - return 1; - } - else - return 0; -} - -/** - * 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 ( ModifierData * md1, ModifierData * md2, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response, int selfcollision) -{ - int i = 0, ret=0, overlap = 0; - - /* - // Shouldn't be possible - if(!tree1 || !tree2) - { - printf("Error: no tree there\n"); - return 0; -} - */ - - if(selfcollision) - overlap = bvh_overlap_self(tree1, tree2); - else - overlap = bvh_overlap(tree1->bv, tree2->bv); - - if (overlap) - { - // 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 (md1, md2, 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 (md1, md2, tree1, tree2->nodes[i], step, collision_response, selfcollision)) - ret = 1; - } - } - } - else - { - // Process the quad tree. - for (i = 0; i < 4; i++) - { - // Only traverse nodes that exist. - if (tree1->nodes [i] && bvh_traverse (md1, md2, tree1->nodes[i], tree2, step, collision_response, selfcollision)) - 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; - float max = 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]; - } - } - - /* for selfcollisions */ - /* - if(!i) - { - tree->alpha = tree->nodes[i]->alpha; - VECCOPY(tree->normal, tree->nodes[i]->normal); - } - else - { - tree->alpha += saacos(INPR(tree->normal, tree->nodes[i]->normal)) / 2.0; - VECADD(tree->normal, tree->normal, tree->nodes[i]->normal); - VecMulf(tree->normal, 0.5); - max = MAX2(max, tree->nodes[i]->alpha); - } - */ - - } - else - break; - } - - tree->alpha += max; -} - -// 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, leaf); - else - bvh_calc_DOP_hull_moving(bvh, &leaf, 1, leaf->bv, leaf); - - // 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); - } - } - - } - } -} - diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 2a8ba878c41..472fd951168 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -58,6 +58,7 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_sph_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" @@ -90,6 +91,7 @@ #include "BKE_object.h" #include "BKE_mesh.h" #include "BKE_softbody.h" +#include "BKE_sph.h" #include "BKE_cloth.h" #include "BKE_material.h" #include "BKE_particle.h" @@ -5178,6 +5180,89 @@ static void clothModifier_freeData(ModifierData *md) } } +/* Smooth Particly Hydrodynamics */ + +static void sphModifier_initData(ModifierData *md) +{ + SphModifierData *sphmd = (SphModifierData*) md; + + sphmd->sim_parms = MEM_callocN(sizeof(SphSimSettings), "SPH sim parms"); + sphmd->coll_parms = MEM_callocN(sizeof(SphCollSettings), "SPH coll parms"); + + /* check for alloc failing */ + if(!sphmd->sim_parms || !sphmd->coll_parms) + return; + + sph_init(sphmd); +} + +static DerivedMesh *sphModifier_applyModifier(ModifierData *md, Object *ob, + DerivedMesh *derivedData, int useRenderParams, int isFinalCalc) +{ + SphModifierData *sphmd = (SphModifierData*) md; + DerivedMesh *result=NULL; + + /* check for alloc failing */ + if(!sphmd->sim_parms || !sphmd->coll_parms) + return derivedData; + + result = sphModifier_do(sphmd, ob, derivedData, useRenderParams, isFinalCalc); + + if(result) + { + CDDM_calc_normals(result); + return result; + } + + return derivedData; +} + +static void sphModifier_updateDepgraph( + ModifierData *md, DagForest *forest, Object *ob, + DagNode *obNode) +{ + SphModifierData *sphmd = (SphModifierData*) md; + + Base *base; + +} + +CustomDataMask sphModifier_requiredDataMask(ModifierData *md) +{ + CustomDataMask dataMask = 0; + + /* ask for vertexgroups if we need them */ + dataMask |= (1 << CD_MDEFORMVERT); + + return dataMask; +} + +static void sphModifier_copyData(ModifierData *md, ModifierData *target) +{ + +} + + +static int sphModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + +static void sphModifier_freeData(ModifierData *md) +{ + SphModifierData *sphmd = (SphModifierData*) md; + + if (sphmd) + { + sph_free_modifier(sphmd); + + if(sphmd->sim_parms) + MEM_freeN(sphmd->sim_parms); + if(sphmd->coll_parms) + MEM_freeN(sphmd->coll_parms); + } +} + /* Collision */ static void collisionModifier_initData(ModifierData *md) @@ -5191,7 +5276,7 @@ static void collisionModifier_initData(ModifierData *md) collmd->current_v = NULL; collmd->time = -1; collmd->numverts = 0; - collmd->bvh = NULL; + collmd->bvhtree = NULL; } static void collisionModifier_freeData(ModifierData *md) @@ -5200,8 +5285,8 @@ static void collisionModifier_freeData(ModifierData *md) if (collmd) { - if(collmd->bvh) - bvh_free(collmd->bvh); + if(collmd->bvhtree) + BLI_bvhtree_free(collmd->bvhtree); if(collmd->x) MEM_freeN(collmd->x); if(collmd->xnew) @@ -5212,7 +5297,6 @@ static void collisionModifier_freeData(ModifierData *md) MEM_freeN(collmd->current_xnew); if(collmd->current_v) MEM_freeN(collmd->current_v); - if(collmd->mfaces) MEM_freeN(collmd->mfaces); @@ -5223,7 +5307,7 @@ static void collisionModifier_freeData(ModifierData *md) collmd->current_v = NULL; collmd->time = -1; collmd->numverts = 0; - collmd->bvh = NULL; + collmd->bvhtree = NULL; collmd->mfaces = NULL; } } @@ -5291,9 +5375,8 @@ static void collisionModifier_deformVerts( collmd->mfaces = dm->dupFaceArray(dm); collmd->numfaces = dm->getNumFaces(dm); - // TODO: epsilon // create bounding box hierarchy - collmd->bvh = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft); + collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->x, numverts, ob->pd->pdef_sboft); collmd->time = current_time; } @@ -5316,25 +5399,25 @@ static void collisionModifier_deformVerts( memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert)); /* check if GUI setting has changed for bvh */ - if(collmd->bvh) + if(collmd->bvhtree) { - if(ob->pd->pdef_sboft != collmd->bvh->epsilon) + if(ob->pd->pdef_sboft != BLI_bvhtree_getepsilon(collmd->bvhtree)) { - bvh_free(collmd->bvh); - collmd->bvh = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft); + BLI_bvhtree_free(collmd->bvhtree); + collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft); } } - /* happens on file load (ONLY when i decomment changes in readfile.c */ - if(!collmd->bvh) + /* happens on file load (ONLY when i decomment changes in readfile.c) */ + if(!collmd->bvhtree) { - collmd->bvh = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft); + collmd->bvhtree = bvhtree_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sboft); } else { // recalc static bounding boxes - bvh_update_from_mvert(collmd->bvh, collmd->current_x, numverts, NULL, 0); + bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, NULL, collmd->numverts, 0 ); } collmd->time = current_time; @@ -7106,6 +7189,18 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->requiredDataMask = bevelModifier_requiredDataMask; mti->applyModifier = bevelModifier_applyModifier; mti->applyModifierEM = bevelModifier_applyModifierEM; + + mti = INIT_TYPE(Sph); + mti->type = eModifierTypeType_Nonconstructive; + mti->flags = eModifierTypeFlag_AcceptsMesh + | eModifierTypeFlag_UsesPointCache; + mti->initData = sphModifier_initData; + mti->copyData = sphModifier_copyData; + mti->requiredDataMask = sphModifier_requiredDataMask; + mti->applyModifier = sphModifier_applyModifier; + mti->dependsOnTime = sphModifier_dependsOnTime; + mti->freeData = sphModifier_freeData; + mti->updateDepgraph = sphModifier_updateDepgraph; mti = INIT_TYPE(Displace); mti->type = eModifierTypeType_OnlyDeform; diff --git a/source/blender/blenkernel/intern/sph.c b/source/blender/blenkernel/intern/sph.c new file mode 100644 index 00000000000..3db1a361d5c --- /dev/null +++ b/source/blender/blenkernel/intern/sph.c @@ -0,0 +1,490 @@ +/* pw.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. +* +* Contributor(s): Daniel Genrich +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#include + +#include "MEM_guardedalloc.h" + +#include "BKE_sph.h" + +#include "DNA_sph_types.h" + +#include "sph_extern.h" + +#include "DNA_effect_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_particle_types.h" +#include "DNA_scene_types.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_effect.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_particle.h" + + +// necessary +#include "float.h" +#include "math.h" +#include "BLI_kdtree.h" +#include "BLI_arithb.h" + +// #include "omp.h" + +#ifdef _WIN32 +void ststart ( void ) +{} +void stend ( void ) +{ +} +double stval() +{ + return 0; +} +#else +#include + +static struct timeval _ststart, _stend; +static struct timezone stz; + +void ststart(void) +{ + gettimeofday(&_ststart, &stz); +} +void stend(void) +{ + gettimeofday(&_stend,&stz); +} +double stval() +{ + double t1, t2; + t1 = (double)_ststart.tv_sec + (double)_ststart.tv_usec/(1000*1000); + t2 = (double)_stend.tv_sec + (double)_stend.tv_usec/(1000*1000); + return t2-t1; +} +#endif + +void sph_init (SphModifierData *sphmd) +{ + /* fill modifier with standard settings */ + sphmd->sim_parms->timestep = 0.001; // 0.001 + sphmd->sim_parms->viscosity = 80000.0; + sphmd->sim_parms->incompressibility = 8000000.0; + sphmd->sim_parms->surfacetension = 8000.0; + sphmd->sim_parms->density = 1000.0; + sphmd->sim_parms->gravity[2] = -9.81; + sphmd->sim_parms->gravity[1] = 0.0; + sphmd->sim_parms->gravity[0] = 0.0; + sphmd->sim_parms->samplingdistance = 0.02; // length of one cell? 0.01 + sphmd->sim_parms->smoothinglength = 2.5; + sphmd->sim_parms->flags = SPH_SIMSETTINGS_FLAG_GHOSTS | SPH_SIMSETTINGS_FLAG_OFFLINE | SPH_SIMSETTINGS_FLAG_MULTIRES | SPH_SIMSETTINGS_FLAG_DOMAIN; + sphmd->sim_parms->computesurfaceevery = 5; // 30000000 + sphmd->sim_parms->fastmarchingevery = 5; + sphmd->sim_parms->dumppovrayevery = 300000; + sphmd->sim_parms->dumpimageevery = 30; + sphmd->sim_parms->totaltime = 0.01; // 40.0 + sphmd->sim_parms->tangentialfriction = 0.1; + sphmd->sim_parms->normalfriction = 0.95; + sphmd->sim_parms->initiallevel = 1; + sphmd->sim_parms->rotation_angle = 0.0; + + sphmd->sim_parms->rotation_axis[0] = 1.0; + sphmd->sim_parms->rotation_axis[1] = 1.0; + sphmd->sim_parms->rotation_axis[2] = 1.0; + + sphmd->sim_parms->rotation_center[0] = 0.0; + sphmd->sim_parms->rotation_center[1] = 0.0; + sphmd->sim_parms->rotation_center[2] = 0.0; + + sphmd->sim_parms->scenelowerbound[0] = -1.0; + sphmd->sim_parms->scenelowerbound[1] = -1.0; + sphmd->sim_parms->scenelowerbound[2] = -1.0; + + sphmd->sim_parms->sceneupperbound[0] = 1.0; + sphmd->sim_parms->sceneupperbound[1] = 1.0; + sphmd->sim_parms->sceneupperbound[2] = 1.0; + + sphmd->sim_parms->alpha = 2.0; + sphmd->sim_parms->beta = 3.0; + sphmd->sim_parms->gamma = 1.5; + + sphmd->sim_parms->numverts = 0; + sphmd->sim_parms->numtris = 0; + sphmd->sim_parms->verts = NULL; + sphmd->sim_parms->tris = NULL; + sphmd->sim_parms->normals = NULL; + + sphmd->sim_parms->resolution = 70; + + sphmd->sim_parms->co = NULL; + sphmd->sim_parms->r = NULL; + sphmd->sim_parms->numpart = 0; +} + +void sph_free_modifier (SphModifierData *sphmd) +{ + + // sph_free_cpp(sphmd); + + if(sphmd->sim_parms->verts) + free(sphmd->sim_parms->verts); + if(sphmd->sim_parms->tris) + free(sphmd->sim_parms->tris); + if(sphmd->sim_parms->normals) + free(sphmd->sim_parms->normals); + if(sphmd->sim_parms->co) + MEM_freeN(sphmd->sim_parms->co); + if(sphmd->sim_parms->r) + free(sphmd->sim_parms->r); + +} + + +DerivedMesh *sphModifier_do(SphModifierData *sphmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) +{ + SphSimSettings *sim_parms = sphmd->sim_parms; + DerivedMesh *result = NULL; + MVert *mvert = NULL; + MFace *mface = NULL; + int a = 0; + float mat[4][4], imat[4][4]; + Mat4CpyMat4(mat, ob->obmat); + Mat4Invert(imat, mat); + + // only domain is simulated + if(!(sim_parms->flags & SPH_SIMSETTINGS_FLAG_DOMAIN) && !(sim_parms->flags & SPH_SIMSETTINGS_FLAG_BAKING)) + { + return dm; + } + + ststart(); + + if(!(sim_parms->flags & SPH_SIMSETTINGS_FLAG_INIT)) + { + if(!sph_init_all (sphmd, dm, ob)) + { + sphmd->sim_parms->flags &= ~SPH_SIMSETTINGS_FLAG_INIT; + return dm; + } + } + + + + // sph_simulate_cpp(ob, sphmd, 1.0, NULL); + + stend(); + + printf ( "SPH simulation time: %f\n", ( float ) stval() ); + + if(sim_parms->numverts && sim_parms->numtris) + { + + + result = CDDM_new ( sim_parms->numverts, 0, sim_parms->numtris); + + // copy verts + mvert = CDDM_get_verts(result); + for(a=0; anumverts; a++) { + MVert *mv = &mvert[a]; + float *vbCo = &sim_parms->verts[a*3]; + VECCOPY(mv->co, vbCo); + Mat4MulVecfl(imat, mv->co); + } + + mface = CDDM_get_faces(result); + for(a=0; anumtris; a++) { + MFace *mf = &mface[a]; + int *tri = &sim_parms->tris[a*3]; + mf->v1 = tri[0]; + mf->v2 = tri[1]; + mf->v3 = tri[2]; + test_index_face(mf, NULL, 0, 3); + } + + CDDM_calc_edges ( result ); + CDDM_calc_normals ( result ); + + return result; + } + else + return dm; +} + +static void set_min_max(float *min, float *max, float *co) +{ + // also calc min + max of bounding box for 3d grid + min[0] = MIN2(min[0], co[0]); + min[1] = MIN2(min[1], co[1]); + min[2] = MIN2(min[2], co[2]); + + max[0] = MAX2(max[0], co[0]); + max[1] = MAX2(max[1], co[1]); + max[2] = MAX2(max[2], co[2]); +} + +long calc_distance_field(Object *ob, DerivedMesh *dm, SphModifierData *sphmd, float mat[4][4]) +{ + int numverts = dm->getNumVerts(dm); + int numfaces = dm->getNumFaces(dm); + MVert *mvert = dm->getVertArray(dm); + MFace *mface = dm->getFaceArray(dm); + int i, j, k; + KDTree *tree; + float co[3], co1[3], co2[3], co3[3], co4[3]; + int index; + float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX}, slice, maxdir; + int resx, resy, resz; + int maxres = 20; + float *dist; + float *normals; + int totpart = 0; + float *cos = NULL; + int maxpart = 0; + + printf("calc_distance_field\n"); + + dist = MEM_callocN(maxres*maxres*maxres*sizeof(float), "distance_field"); + normals = MEM_callocN(numfaces*3*sizeof(float), "triangle_normals"); + + ///////////////////////////////////////////////// + // create + fill + balance kdtree + ///////////////////////////////////////////////// + tree = BLI_kdtree_new(numverts); + for(i = 0; i < numfaces; i++) + { + VECCOPY(co1, mvert[mface[i].v1].co); + Mat4MulVecfl(mat, co1); + set_min_max(min, max, co1); + VECCOPY(co2, mvert[mface[i].v2].co); + Mat4MulVecfl(mat, co2); + set_min_max(min, max, co2); + VECCOPY(co3, mvert[mface[i].v3].co); + Mat4MulVecfl(mat, co3); + set_min_max(min, max, co3); + + // calc triangle center + VECCOPY(co, co1); + VECADD(co, co, co2); + VECADD(co, co, co3); + if(mface[i].v4) + { + VECCOPY(co4, mvert[mface[i].v4].co); + Mat4MulVecfl(mat, co4); + set_min_max(min, max, co4); + VECADD(co, co, co4); + VecMulf(co, 0.25); + } + else + VecMulf(co, 1.0 / 3.0); + + if(mface[i].v4) + CalcNormFloat4(mvert[mface[i].v1].co, mvert[mface[i].v2].co, mvert[mface[i].v3].co, mvert[mface[i].v4].co, &normals[i*3]); + else + CalcNormFloat(mvert[mface[i].v1].co, mvert[mface[i].v2].co, mvert[mface[i].v3].co, &normals[i*3]); + + BLI_kdtree_insert(tree, i, co, NULL); + } + BLI_kdtree_balance(tree); + ///////////////////////////////////////////////// + + // calculate slice height + width + maxdir = max[0] - min[0]; + maxdir = MAX2(max[1]-min[1], maxdir); + maxdir = MAX2(max[2]-min[2], maxdir); + slice = maxdir / (float)maxres; + resx = MIN2(maxres, ceil((max[0] - min[0]) / slice)); + resy = MIN2(maxres, ceil((max[1] - min[1]) / slice)); + resz = MIN2(maxres, ceil((max[2] - min[2]) / slice)); + + // adjust max + max[0] = min[0] + slice * resx; + max[1] = min[1] + slice * resy; + max[2] = min[2] + slice * resz; + + if(sphmd->sim_parms->co) + MEM_freeN(sphmd->sim_parms->co); + + cos = sphmd->sim_parms->co = MEM_callocN(sizeof(float)*3*resx*resy*resz, "sph_cos"); + // r = calloc(1, sizeof(float)*resx*resy*resz); + maxpart = sizeof(float)*3*resx*resy*resz; + +// #pragma omp parallel for private(i,j,k) schedule(static) + for(i = 0; i < resx; i ++) + { + for(j = 0; j < resy; j++) + { + for(k = 0; k < resz; k++) + { + KDTreeNearest nearest; + float tco[3]; + tco[0] = min[0] + slice * i + slice * 0.5; + tco[1] = min[1] + slice * j + slice * 0.5; + tco[2] = min[2] + slice * k + slice * 0.5; + + index = BLI_kdtree_find_nearest(tree, tco, NULL, &nearest); + + if(index != -1) + { + float t[3]; + float sgn; + + VECSUB(t, tco, nearest.co); + sgn = INPR(t, &normals[nearest.index*3]); + + if(sgn < 0.0) + sgn = -1.0; + else + sgn = 1.0; + + dist[(i*resy*resz)+(j*resz)+k] = sgn * nearest.dist; + + if((int)sgn < 0) + { + // create particle if inside object + VECCOPY(&cos[totpart*3], tco); + + totpart++; + } + + } + else + { + printf("Error: no nearest point!\n"); + } + } + } + } + printf("maxpart: %d, totpart: %d\n", maxpart, totpart); + + sphmd->sim_parms->numpart = totpart; + MEM_freeN(dist); + MEM_freeN(normals); + BLI_kdtree_free(tree); + return totpart; +} + +/* add constraints, inflows, fluid, ... */ +int sph_init_all (SphModifierData *sphmd, DerivedMesh *dm, Object *ob) +{ + Base *base=NULL; + Object *fobject = NULL; + SphModifierData *fsphmd = NULL; + int fluids = 0; // only one fluid object possible + DerivedMesh *fdm = NULL; + + sphmd->sim_parms->flags |= SPH_SIMSETTINGS_FLAG_INIT; + CDDM_calc_normals ( dm ); + + /* create C++ object */ + // sph_init_cpp(sphmd); + sphmd->sim_parms->numpart = calc_distance_field(ob, dm, sphmd, ob->obmat); + return 1; + + /* create fluid domain */ + // sph_set_domain(sphmd, dm, ob->obmat); + + // check for constraints, fluid, etc. but ignore domains + for ( base = G.scene->base.first; base; base = base->next ) + { + fobject = base->object; + fsphmd = ( SphModifierData * ) modifiers_findByType ( fobject, eModifierType_Sph ); + + // TODO I could check for linked groups, too + if ( !fsphmd ) + { + // TODO + } + else + { + if(fsphmd == sphmd) + continue; + + if(fsphmd->sim_parms) + { + // check for fluid + if(((short)fsphmd->sim_parms->flags == SPH_SIMSETTINGS_FLAG_FLUID) && (!fluids)) + { + // create fluids + // particles have to be created AFTER constraints + // TODO: no particles = crash + + // get derivedmesh from object + fdm = mesh_get_derived_final(fobject, CD_MASK_BAREMESH); + + // create fluid object + /* + if(!sph_add_particles(sphmd, fdm, fobject->obmat, fsphmd->sim_parms->resolution)) + { + fluids--; + } + */ + if(fdm) + fdm->release(fdm); + + fluids++; + } + else if((short)fsphmd->sim_parms->flags & SPH_SIMSETTINGS_FLAG_OBSTACLE) + { + + } + } + } + } + + if(!fluids) + return 0; + + return 1; +} + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h new file mode 100644 index 00000000000..51f87b26aaf --- /dev/null +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -0,0 +1,63 @@ +/** + * + * ***** BEGIN GPL 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. + * + * 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 LICENSE BLOCK ***** + */ + + +#ifndef BLI_KDOPBVH_H +#define BLI_KDOPBVH_H + +#include + +struct BVHTree; +typedef struct BVHTree BVHTree; + +typedef struct BVHTreeOverlap { + int indexA; + int indexB; +} BVHTreeOverlap; + +BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis); +void BLI_bvhtree_free(BVHTree *tree); + +/* construct: first insert points, then call balance */ +int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints); +void BLI_bvhtree_balance(BVHTree *tree); + +/* update: first update points/nodes, then call update_tree to refit the bounding volumes */ +int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints); +void BLI_bvhtree_update_tree(BVHTree *tree); + +/* collision/overlap: check two trees if they overlap, alloc's *overlap with length of the int return value */ +BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result); + +float BLI_bvhtree_getepsilon(BVHTree *tree); + +#endif // BLI_KDOPBVH_H + + + + diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c new file mode 100644 index 00000000000..8be52854a7b --- /dev/null +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -0,0 +1,786 @@ +/* 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): Daniel Genrich +* +* ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#include "math.h" +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "BKE_utildefines.h" + +#include "BLI_kdopbvh.h" + +#ifdef _OPENMP +#include +#endif + +typedef struct BVHNode +{ + struct BVHNode *children[8]; // max 8 children + struct BVHNode *parent; // needed for bottom - top update + float bv[26]; // Bounding volume of all nodes, max 13 axis + int index; /* face, edge, vertex index */ + char totnode; // how many nodes are used, used for speedup + char traversed; // how many nodes already traversed until this level? + char main_axis; +} BVHNode; + +struct BVHTree +{ + BVHNode **nodes; + BVHNode *nodearray; /* pre-alloc branch nodes */ + int *orig_index; /* mapping for orig_index to node_index */ + float epsilon; /* epslion is used for inflation of the k-dop */ + int totleaf; // leafs + int totbranch; + char tree_type; // type of tree (4 => quadtree) + char axis; // kdop type (6 => OBB, 7 => AABB, ...) + char start_axis, stop_axis; // KDOP_AXES array indices according to axis +}; + +typedef struct BVHOverlapData +{ + BVHTree *tree1, *tree2; + BVHTreeOverlap *overlap; + int i, max_overlap; /* i is number of overlaps */ +} BVHOverlapData; +//////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +// 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}, {0, 1.0, 0}, {0, 0, 1.0}, {1.0, 1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, -1.0}, +{1.0, -1.0, -1.0}, {1.0, 1.0, 0}, {1.0, 0, 1.0}, {0, 1.0, 1.0}, {1.0, -1.0, 0}, {1.0, 0, -1.0}, +{0, 1.0, -1.0} +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////// +// 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 +*/ +static void bvh_exchange(BVHNode **a, int i, int j) +{ + BVHNode *t=a[i]; + a[i]=a[j]; + a[j]=t; +} +static int floor_lg(int a) +{ + return (int)(floor(log(a)/log(2))); +} + +/* +* Insertion sort algorithm +*/ +static void bvh_insertionsort(BVHNode **a, int lo, int hi, int axis) +{ + int i,j; + BVHNode *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(BVHNode **a, int lo, int hi, BVHNode * 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(BVHNode **a, int i, int n, int lo, int axis) +{ + BVHNode * 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(BVHNode **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 BVHNode *bvh_medianof3(BVHNode **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 (BVHNode **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; + } +} + +static void sort(BVHNode **a0, int begin, int end, int axis) +{ + if (begin < end) + { + BVHNode **a=a0; + bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis); + bvh_insertionsort(a, begin, end, axis); + } +} +void sort_along_axis(BVHTree *tree, int start, int end, int axis) +{ + sort(tree->nodes, start, end, axis); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////// + +void BLI_bvhtree_free(BVHTree *tree) +{ + if(tree) + { + MEM_freeN(tree->nodes); + MEM_freeN(tree->nodearray); + MEM_freeN(tree->orig_index); + MEM_freeN(tree); + } +} + +BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) +{ + BVHTree *tree; + int numbranches=0, i; + + // only support up to octree + if(tree_type > 8) + return NULL; + + tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree"); + + if(tree) + { + // calculate max number of branches, our bvh kdop is "almost perfect" + for(i = 1; i <= (int)ceil((float)((float)log(maxsize)/(float)log(tree_type))); i++) + numbranches += (pow(tree_type, i) / tree_type); + + tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*(numbranches+maxsize + tree_type), "BVHNodes"); + + if(!tree->nodes) + { + MEM_freeN(tree); + return NULL; + } + + tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)*(numbranches+maxsize + tree_type), "BVHNodeArray"); + + if(!tree->nodearray) + { + MEM_freeN(tree); + MEM_freeN(tree->nodes); + return NULL; + } + + tree->orig_index = (int *)MEM_callocN(sizeof(int)*(numbranches+maxsize + tree_type), "BVHIndexArray"); + + if(!tree->orig_index) + { + MEM_freeN(tree); + MEM_freeN(tree->nodes); + MEM_freeN(tree->nodearray); + return NULL; + } + + tree->epsilon = epsilon; + tree->tree_type = tree_type; + tree->axis = axis; + + if(axis == 26) + { + tree->start_axis = 0; + tree->stop_axis = 13; + } + else if(axis == 18) + { + tree->start_axis = 7; + tree->stop_axis = 13; + } + else if(axis == 14) + { + tree->start_axis = 0; + tree->stop_axis = 7; + } + else if(axis == 8) // AABB + { + tree->start_axis = 0; + tree->stop_axis = 4; + } + else if(axis == 6) // OBB + { + tree->start_axis = 0; + tree->stop_axis = 3; + } + else + { + BLI_bvhtree_free(tree); + return NULL; + } + } + + return tree; +} + +static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoints, int moving) +{ + float newminmax; + int i, k; + + // don't init boudings for the moving case + if(!moving) + { + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + node->bv[2*i] = FLT_MAX; + node->bv[2*i + 1] = -FLT_MAX; + } + } + + for(k = 0; k < numpoints; k++) + { + // for all Axes. + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + newminmax = INPR(&co[k * 3], KDOP_AXES[i]); + if (newminmax < node->bv[2 * i]) + node->bv[2 * i] = newminmax; + if (newminmax > node->bv[(2 * i) + 1]) + node->bv[(2 * i) + 1] = newminmax; + } + } +} + +// depends on the fact that the BVH's for each face is already build +static void refit_kdop_hull(BVHTree *tree, int start, int end, float *bv) +{ + float newmin,newmax; + int i, j; + + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + bv[2*i] = FLT_MAX; + bv[2*i + 1] = -FLT_MAX; + } + + for (j = start; j < end; j++) + { + // for all Axes. + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + newmin = tree->nodes[j]->bv[(2 * i)]; + if ((newmin < bv[(2 * i)])) + bv[(2 * i)] = newmin; + + newmax = tree->nodes[j]->bv[(2 * i) + 1]; + if ((newmax > bv[(2 * i) + 1])) + bv[(2 * i) + 1] = newmax; + } + } +} + +int BLI_bvhtree_insert(BVHTree *tree, int index, float *co, int numpoints) +{ + BVHNode *node= NULL; + int i; + + // insert should only possible as long as tree->totbranch is 0 + if(tree->totbranch > 0) + return 0; + + if(tree->totleaf+1 >= MEM_allocN_len(tree->nodes)) + return 0; + + // TODO check if have enough nodes in array + + node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); + tree->totleaf++; + + create_kdop_hull(tree, node, co, numpoints, 0); + + // inflate the bv with some epsilon + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + node->bv[(2 * i)] -= tree->epsilon; // minimum + node->bv[(2 * i) + 1] += tree->epsilon; // maximum + } + + node->index= index; + + return 1; +} + +// only supports x,y,z axis in the moment +// but we should use a plain and simple function here for speed sake +static char get_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 + } +} + +static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char lastaxis) +{ + char laxis; + int i, tend; + BVHNode *tnode; + int slice = (end-start+tree->tree_type-1)/tree->tree_type; //division rounded up + + // Determine which axis to split along + laxis = get_largest_axis(node->bv); + + // Sort along longest axis + if(laxis!=lastaxis) + sort_along_axis(tree, start, end, laxis); + + // split nodes along longest axis + for (i=0; start < end; start += slice, i++) //i counts the current child + { + tend = start + slice; + + if(tend > end) tend = end; + + if(tend-start == 1) // ok, we have 1 left for this node + { + node->children[i] = tree->nodes[start]; + node->children[i]->parent = node; + } + else + { + tnode = node->children[i] = tree->nodes[tree->totleaf + tree->totbranch] = &(tree->nodearray[tree->totbranch + tree->totleaf]); + tree->totbranch++; + tnode->parent = node; + + refit_kdop_hull(tree, start, tend, tnode->bv); + bvh_div_nodes(tree, tnode, start, tend, laxis); + } + node->totnode++; + } + + return; +} + +static void verify_tree(BVHTree *tree) +{ + int i, j, check = 0; + + // check the pointer list + for(i = 0; i < tree->totleaf; i++) + { + if(tree->nodes[i]->parent == NULL) + printf("Leaf has no parent: %d\n", i); + else + { + for(j = 0; j < tree->tree_type; j++) + { + if(tree->nodes[i]->parent->children[j] == tree->nodes[i]) + check = 1; + } + if(!check) + { + printf("Parent child relationship doesn't match: %d\n", i); + } + check = 0; + } + } + + // check the leaf list + for(i = 0; i < tree->totleaf; i++) + { + if(tree->nodearray[i].parent == NULL) + printf("Leaf has no parent: %d\n", i); + else + { + for(j = 0; j < tree->tree_type; j++) + { + if(tree->nodearray[i].parent->children[j] == &tree->nodearray[i]) + check = 1; + } + if(!check) + { + printf("Parent child relationship doesn't match: %d\n", i); + } + check = 0; + } + } + + printf("branches: %d, leafs: %d, total: %d\n", tree->totbranch, tree->totleaf, tree->totbranch + tree->totleaf); +} + +void BLI_bvhtree_balance(BVHTree *tree) +{ + BVHNode *node; + int i; + + if(tree->totleaf == 0) + return; + + // create root node + node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); + tree->totbranch++; + + // refit root bvh node + refit_kdop_hull(tree, 0, tree->totleaf, tree->nodes[tree->totleaf]->bv); + // create + balance tree + bvh_div_nodes(tree, tree->nodes[tree->totleaf], 0, tree->totleaf, 0); + + // put indices into array for O(1) access + for(i = 0; i < tree->totleaf; i++) + { + tree->orig_index[tree->nodes[i]->index] = i; + } + + verify_tree(tree); +} + +// overlap - is it possbile for 2 bv's to collide ? +static int tree_overlap(float *bv1, float *bv2, int start_axis, int stop_axis) +{ + float *bv1_end = bv1 + (stop_axis<<1); + + bv1 += start_axis<<1; + bv2 += start_axis<<1; + + // test all axis if min + max overlap + for (; bv1 != bv1_end; bv1+=2, bv2+=2) + { + if ((*(bv1) > *(bv2 + 1)) || (*(bv2) > *(bv1 + 1))) + return 0; + } + + return 1; +} + +static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2) +{ + int j; + + if(tree_overlap(node1->bv, node2->bv, MIN2(data->tree1->start_axis, data->tree2->start_axis), MIN2(data->tree1->stop_axis, data->tree2->stop_axis))) + { + // check if node1 is a leaf + if(node1->index) + { + // check if node2 is a leaf + if(node2->index) + { + + if(node1 == node2) + { + return; + } + + if(data->i >= data->max_overlap) + { + // try to make alloc'ed memory bigger + data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap)*data->max_overlap*2); + + if(!data->overlap) + { + printf("Out of Memory in traverse\n"); + return; + } + data->max_overlap *= 2; + } + + // both leafs, insert overlap! + data->overlap[data->i].indexA = node1->index; + data->overlap[data->i].indexB = node2->index; + + data->i++; + } + else + { + for(j = 0; j < data->tree2->tree_type; j++) + { + if(node2->children[j]) + traverse(data, node1, node2->children[j]); + } + } + } + else + { + + for(j = 0; j < data->tree2->tree_type; j++) + { + if(node1->children[j]) + traverse(data, node1->children[j], node2); + } + } + } + return; +} + +BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) +{ + int j, total = 0; + BVHTreeOverlap *overlap = NULL, *to = NULL; + BVHOverlapData *data[tree1->tree_type]; + + // check for compatibility of both trees (can't compare 14-DOP with 18-DOP) + if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14)) + return 0; + + // fast check root nodes for collision before doing big splitting + traversal + if(!tree_overlap(tree1->nodes[tree1->totleaf]->bv, tree2->nodes[tree2->totleaf]->bv, MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis))) + return 0; + + for(j = 0; j < tree1->tree_type; j++) + { + data[j] = (BVHOverlapData *)MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData"); + + // init BVHOverlapData + data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap)*MAX2(tree1->totleaf, tree2->totleaf)); + data[j]->tree1 = tree1; + data[j]->tree2 = tree2; + data[j]->max_overlap = MAX2(tree1->totleaf, tree2->totleaf); + data[j]->i = 0; + } + +#pragma omp parallel for private(j) schedule(static) + for(j = 0; j < tree1->tree_type; j++) + { + traverse(data[j], tree1->nodes[tree1->totleaf]->children[j], tree2->nodes[tree2->totleaf]); + } + + for(j = 0; j < tree1->tree_type; j++) + total += data[j]->i; + + to = overlap = (BVHTreeOverlap *)MEM_callocN(sizeof(BVHTreeOverlap)*total, "BVHTreeOverlap"); + + for(j = 0; j < tree1->tree_type; j++) + { + memcpy(to, data[j]->overlap, data[j]->i*sizeof(BVHTreeOverlap)); + to+=data[j]->i; + } + + for(j = 0; j < tree1->tree_type; j++) + { + free(data[j]->overlap); + MEM_freeN(data[j]); + } + + (*result) = total; + return overlap; +} + + +// bottom up update of bvh tree: +// join the 4 children here +static void node_join(BVHTree *tree, BVHNode *node) +{ + int i, j; + + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + node->bv[2*i] = FLT_MAX; + node->bv[2*i + 1] = -FLT_MAX; + } + + for (i = 0; i < tree->tree_type; i++) + { + if (node->children[i]) + { + for (j = tree->start_axis; j < tree->stop_axis; j++) + { + // update minimum + if (node->children[i]->bv[(2 * j)] < node->bv[(2 * j)]) + node->bv[(2 * j)] = node->children[i]->bv[(2 * j)]; + + // update maximum + if (node->children[i]->bv[(2 * j) + 1] > node->bv[(2 * j) + 1]) + node->bv[(2 * j) + 1] = node->children[i]->bv[(2 * j) + 1]; + } + } + else + break; + } +} + +// call before BLI_bvhtree_update_tree() +int BLI_bvhtree_update_node(BVHTree *tree, int index, float *co, float *co_moving, int numpoints) +{ + BVHNode *node= NULL; + int i = 0; + + // check if index exists + if(index > tree->totleaf) + return 0; + + node = tree->nodes[tree->orig_index[index]]; + + create_kdop_hull(tree, node, co, numpoints, 0); + + if(co_moving) + create_kdop_hull(tree, node, co_moving, numpoints, 1); + + // inflate the bv with some epsilon + for (i = tree->start_axis; i < tree->stop_axis; i++) + { + node->bv[(2 * i)] -= tree->epsilon; // minimum + node->bv[(2 * i) + 1] += tree->epsilon; // maximum + } + + return 1; +} + +// call BLI_bvhtree_update_node() first for every node/point/triangle +void BLI_bvhtree_update_tree(BVHTree *tree) +{ + BVHNode *leaf, *parent; + + // reset tree traversing flag + for (leaf = tree->nodearray + tree->totleaf; leaf != tree->nodearray + tree->totleaf + tree->totbranch; leaf++) + leaf->traversed = 0; + + for (leaf = tree->nodearray; leaf != tree->nodearray + tree->totleaf; leaf++) + { + for (parent = leaf->parent; parent; parent = parent->parent) + { + parent->traversed++; // we tried to go up in hierarchy + if (parent->traversed < parent->totnode) + break; // we do not need to check further + else + node_join(tree, parent); + } + } +} + +float BLI_bvhtree_getepsilon(BVHTree *tree) +{ + return tree->epsilon; +} diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 24606bd822f..e3649a0cc43 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3073,6 +3073,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) clmd->sim_parms= newdataadr(fd, clmd->sim_parms); clmd->coll_parms= newdataadr(fd, clmd->coll_parms); + clmd->point_cache= newdataadr(fd, clmd->point_cache); if(clmd->point_cache) @@ -3082,22 +3083,16 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) if(clmd->sim_parms->presets > 10) clmd->sim_parms->presets = 0; } + else + { + /* Collision modifier without parameters?? */ + + } } 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; @@ -3106,9 +3101,8 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) collmd->current_v = NULL; collmd->time = -1; collmd->numverts = 0; - collmd->bvh = NULL; + collmd->bvhtree = NULL; collmd->mfaces = NULL; - } else if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index 242965a820c..c6482290c86 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -297,6 +297,10 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la /* Cloth sim button defines */ #define B_CLOTH_CHANGEPREROLL 1480 +/* SPH sim button defines */ +#define B_SPH_BAKE 1490 + + /* *********************** */ #define B_WORLDBUTS 1600 diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index b7b43817474..b2d6e8e5756 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -35,6 +35,7 @@ typedef enum ModifierType { eModifierType_Cloth, eModifierType_Collision, eModifierType_Bevel, + eModifierType_Sph, NUM_MODIFIER_TYPES } ModifierType; @@ -374,6 +375,14 @@ typedef struct ClothModifierData { struct PointCache *point_cache; /* definition is in DNA_object_force.h */ } ClothModifierData; +typedef struct SphModifierData { + ModifierData modifier; + + struct SPH *sph; /* pointer to cpp sph sim */ + struct SphSimSettings *sim_parms; /* definition is in DNA_sph_types.h */ + struct SphCollSettings *coll_parms; /* definition is in DNA_sph_types.h */ +} SphModifierData; + typedef struct CollisionModifierData { ModifierData modifier; @@ -390,7 +399,7 @@ typedef struct CollisionModifierData { unsigned int numfaces; int pad; float time; /* cfra time of modifier */ - struct BVH *bvh; /* bounding volume hierarchy for this cloth object */ + struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */ } CollisionModifierData; typedef enum { diff --git a/source/blender/makesdna/DNA_sph_types.h b/source/blender/makesdna/DNA_sph_types.h new file mode 100644 index 00000000000..add3053f612 --- /dev/null +++ b/source/blender/makesdna/DNA_sph_types.h @@ -0,0 +1,102 @@ +/** + * $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_SPH_TYPES_H +#define DNA_SPH_TYPES_H + +// string scene, constraint, backup: missing +// string _file; +// string pov; +// string rendered; +typedef struct SphSimSettings +{ + int flags; // see pw_extern.h + float timestep; + float viscosity; + float incompressibility; /* how incompressible is the fluid? */ + float surfacetension; + float density; + float gravity[3]; /* gravity on the domain */ + float samplingdistance; + float smoothinglength; + + float controlviscosity; + int dumpimageevery; + int computesurfaceevery; + int fastmarchingevery; + int dumppovrayevery; + + float totaltime; + + float tangentialfriction; /* constraint tangential friction */ + float normalfriction; /* constraint normal friction */ + + float rotation_angle; + float rotation_axis[3]; + float rotation_center[3]; + float scenelowerbound[3]; + float sceneupperbound[3]; + + int initiallevel; + + float alpha; + float beta; + float gamma; + + /* needed for better direct resolution input for constraints, fluids,... */ + int resolution; /* can also be calculated by (Max-Min) / samplingdistance */ + int pad; + float *verts; + float *normals; + int *tris; + unsigned int numverts; + unsigned int numtris; + float *co; /* particle positions */ + float *r; /* particle radius */ + long numpart; + int pad2; +} +SphSimSettings; + +typedef struct SphCollSettings +{ + float epsilon; /* min distance for collisions. */ + float self_friction; /* Fiction/damping with self contact. */ + float friction; /* Friction/damping applied on contact with other object.*/ + short self_loop_count; /* How many iterations for the selfcollision loop */ + short loop_count; /* How many iterations for the collision loop. */ + struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */ + int flags; /* collision flags defined in BKE_cloth.h */ + float selfepsilon; /* for selfcollision */ +} +SphCollSettings; + +#endif // DNA_SPH_TYPES_H diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index b02e89233e5..815a9c3869e 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -985,7 +985,7 @@ 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(ELEM3(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Sph)) continue; if((mti->flags&eModifierTypeFlag_AcceptsCVs) || (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) { @@ -1807,6 +1807,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco height = 31; } else if (md->type==eModifierType_Collision) { height = 31; + } else if (md->type==eModifierType_Sph) { + height = 31; } else if (md->type==eModifierType_Boolean) { height = 48; } else if (md->type==eModifierType_Array) { @@ -1837,7 +1839,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 && (md->type!=eModifierType_Cloth)) { + if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth) && (md->type!=eModifierType_Sph)) { 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); } @@ -2229,6 +2231,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiDefBut(block, LABEL, 1, "See Soft Body panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); } else if (md->type==eModifierType_Cloth) { uiDefBut(block, LABEL, 1, "See Cloth panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); + } else if (md->type==eModifierType_Sph) { + uiDefBut(block, LABEL, 1, "See Sph panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); } else if (md->type==eModifierType_Collision) { uiDefBut(block, LABEL, 1, "See Collision panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); } else if (md->type==eModifierType_Boolean) { diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 9a749b6fbd9..4dcc51e03e3 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -52,6 +52,8 @@ #include "BKE_utildefines.h" #include "BKE_particle.h" #include "BKE_pointcache.h" +#include "BKE_sph.h" + #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -107,6 +109,7 @@ #include "DNA_particle_types.h" #include "DNA_radio_types.h" #include "DNA_screen_types.h" +#include "DNA_sph_types.h" #include "DNA_sound_types.h" #include "DNA_texture_types.h" #include "DNA_userdef_types.h" @@ -135,6 +138,7 @@ #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_sound.h" +#include "BKE_sph.h" #include "BKE_texture.h" #include "BKE_utildefines.h" #include "BKE_DerivedMesh.h" @@ -2476,6 +2480,27 @@ void do_object_panels(unsigned short event) allqueue(REDRAWVIEW3D, 0); } break; + case B_SPH_BAKE: + { + SphModifierData *sphmd = (SphModifierData *)modifiers_findByType(ob, eModifierType_Sph); + int i = 0; + + if(sphmd && sphmd->sim_parms) + { + sphmd->sim_parms->flags |= SPH_SIMSETTINGS_FLAG_BAKING; + + // call baking function + for(i = 0; i < 1; i++) + { + CFRA++; + update_for_newframe(); + } + + sphmd->sim_parms->flags &= ~SPH_SIMSETTINGS_FLAG_BAKING; + + } + } + break; } } @@ -5650,6 +5675,116 @@ static void object_panel_cloth_III(Object *ob) } +static void object_sph__enabletoggle(void *ob_v, void *arg2) +{ + Object *ob = ob_v; + ModifierData *md = modifiers_findByType(ob, eModifierType_Sph); + + if (!md) { + // create particle modifier + ParticleSettings *part = psys_new_settings("PSys", G.main); + ParticleSystem *psys = MEM_callocN(sizeof(ParticleSystem), "particle_system"); + ParticleSystemModifierData *psmd; + + md = modifier_new(eModifierType_Sph); + BLI_addtail(&ob->modifiers, md); + + part->type = PART_FLUID; + psys->part = part; + psys->pointcache = BKE_ptcache_add(); + psys->flag |= PSYS_ENABLED; + BLI_addtail(&ob->particlesystem,psys); + md= modifier_new(eModifierType_ParticleSystem); + sprintf(md->name, "SphParticleSystem" ); + psmd= (ParticleSystemModifierData*) md; + psmd->psys=psys; + BLI_addtail(&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_Sph); + + 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_sph(Object *ob) +{ + uiBlock *block=NULL; + uiBut *but=NULL; + static int val; + SphModifierData *sphmd = (SphModifierData *)modifiers_findByType(ob, eModifierType_Sph); + + block= uiNewBlock(&curarea->uiblocks, "object_sph", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Sph ", "Physics", 640, 0, 318, 204)==0) return; + uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + + val = (sphmd ? 1:0); + + + but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Sph", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become Sph"); + uiButSetFunc(but, object_sph__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(sphmd) + { + if(sphmd->sim_parms && (sphmd->sim_parms->flags & SPH_SIMSETTINGS_FLAG_DOMAIN)) + { + uiDefBut(block, BUT, B_SPH_BAKE, "BAKE",10, 180,300,20, NULL, 0.0, 0.0, 10, 0, "Perform simulation and output and surface&preview meshes for each frame."); + } + + uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Domain", 10, 160, 100, 20, (short *)&sphmd->sim_parms->flags, 15.0, SPH_SIMSETTINGS_FLAG_DOMAIN, 0.0, 0.0, " "); + uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Fluid", 110, 160, 100, 20, (short *)&sphmd->sim_parms->flags, 15.0, SPH_SIMSETTINGS_FLAG_FLUID, 0.0, 0.0, " "); + uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Obstacle", 210, 160, 100, 20, (short *)&sphmd->sim_parms->flags, 15.0, SPH_SIMSETTINGS_FLAG_OBSTACLE, 0.0, 0.0, " "); + + if(sphmd->sim_parms && (sphmd->sim_parms->flags & SPH_SIMSETTINGS_FLAG_DOMAIN)) + { + uiDefButBitI(block, TOG, SPH_SIMSETTINGS_FLAG_GHOSTS, REDRAWBUTSOBJECT, "Ghosts",10,140,100,20, &sphmd->sim_parms->flags, 0, 0, 0, 0, " "); + uiDefButBitI(block, TOG, SPH_SIMSETTINGS_FLAG_MULTIRES, REDRAWBUTSOBJECT, "Multires",110,140,100,20, &sphmd->sim_parms->flags, 0, 0, 0, 0, " "); + uiDefButBitI(block, TOG, SPH_SIMSETTINGS_FLAG_VORTICITY, REDRAWBUTSOBJECT, "Vorticity",210,140,100,20, &sphmd->sim_parms->flags, 0, 0, 0, 0, " "); + + // timestep + uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Timestep:",10,120,100,20, &sphmd->sim_parms->timestep, 0.0, 1.0, 0.0001f, 0, " "); + // totaltime + uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Totaltime:",110,120,100,20, &sphmd->sim_parms->totaltime, 0.0, 10000.0, 0.001f, 0, " "); + uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Sampling distance:",210,120,100,20, &sphmd->sim_parms->samplingdistance, 0.0, 1.0, 0.0001f, 0, " "); + uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Smoothing Length:",10,100,100,20, &sphmd->sim_parms->smoothinglength, 0.0, 10.0, 0.1f, 0, " "); + + uiDefButI(block, NUM, REDRAWBUTSOBJECT, "Surface:",110,100,100,20, &sphmd->sim_parms->computesurfaceevery, 0.0, 1000.0, 1.0, 0, " "); + uiDefButI(block, NUM, REDRAWBUTSOBJECT, "Fast Marching:",210,100,100,20, &sphmd->sim_parms->fastmarchingevery, 0.0, 1000.0, 1.0, 0, " "); + } + else if(sphmd->sim_parms && (sphmd->sim_parms->flags & SPH_SIMSETTINGS_FLAG_FLUID)) + { + uiDefButI(block, NUM, REDRAWBUTSOBJECT, "Resolution:",10,120,100,20, &sphmd->sim_parms->resolution, 1.0, 1000.0, 1.0f, 0, " "); + } + } + + + uiBlockEndAlign(block); +} + void object_panels() { Object *ob; @@ -5682,6 +5817,7 @@ void physics_panels() object_panel_cloth(ob); object_panel_cloth_II(ob); object_panel_cloth_III(ob); + object_panel_sph(ob); object_panel_fluidsim(ob); } } diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 561024fb74b..84289be0928 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -1883,11 +1883,13 @@ static void draw_em_measure_stats(Object *ob, EditMesh *em) { EditEdge *eed; EditFace *efa; + EditVert *eve; float v1[3], v2[3], v3[3], v4[3]; float fvec[3]; char val[32]; /* Stores the measurement display text here */ char conv_float[5]; /* Use a float conversion matching the grid size */ float area, col[3]; /* area of the face, color of the text to draw */ + int i = 0; /* make the precission of the pronted value proportionate to the gridsize */ if ((G.vd->grid) < 0.01) @@ -1941,7 +1943,7 @@ static void draw_em_measure_stats(Object *ob, EditMesh *em) if(col[1]> 0.5) {col[0]*=0.7; col[2]*= 0.7;} else col[1]= col[1]*0.7 + 0.3; glColor3fv(col); - + /* for(efa= em->faces.first; efa; efa= efa->next) { if((efa->f & SELECT) || (G.moving && faceselectedOR(efa, SELECT)) ) { VECCOPY(v1, efa->v1->co); @@ -1966,6 +1968,24 @@ static void draw_em_measure_stats(Object *ob, EditMesh *em) glRasterPos3fv(efa->cent); BMF_DrawString( G.fonts, val); } + }*/ + + /* draw IDs of mesh vertexes */ + for(eve = em->verts.first; eve; eve = eve->next) { + char val[32]; + float fvec[3]; + VecLerpf(fvec, ob->loc, eve->co, 1.1); + glRasterPos3f(fvec[0], fvec[1], fvec[2]); + + sprintf(val, "%d", eve->keyindex); + BMF_DrawString(G.fonts, val); + } + for(efa= em->faces.first; efa; efa= efa->next) { + char val[32]; + sprintf(val, "%d", i); + glRasterPos3fv(efa->cent); + BMF_DrawString( G.fonts, val); + i++; } } From e02bca73d78c7a86d383d38052c29f91b8b3d623 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 13 May 2008 00:42:51 +0000 Subject: [PATCH 089/101] New speed imrovements by Mr. Pinto/jaguarandi --- source/blender/blenlib/BLI_kdopbvh.h | 2 +- source/blender/blenlib/intern/BLI_kdopbvh.c | 52 +++++++++++++-------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 3261984da76..c1240da6c3a 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -21,7 +21,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): Daniel Genrich, Jose Pinto + * Contributor(s): Daniel Genrich, Andre Pinto * * ***** END GPL LICENSE BLOCK ***** */ diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 6a1abb5d8ad..75ff1d8f257 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -25,7 +25,7 @@ * * The Original Code is: all of this file. * -* Contributor(s): Daniel Genrich, Jose Pinto +* Contributor(s): Daniel Genrich, Andre Pinto * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -40,6 +40,7 @@ #include "BKE_utildefines.h" #include "BLI_kdopbvh.h" +#include "BLI_arithb.h" #ifdef _OPENMP #include @@ -101,12 +102,6 @@ static int size_threshold = 16; /* * Common methods for all algorithms */ -static void bvh_exchange(BVHNode **a, int i, int j) -{ - BVHNode *t=a[i]; - a[i]=a[j]; - a[j]=t; -} static int floor_lg(int a) { return (int)(floor(log(a)/log(2))); @@ -138,11 +133,11 @@ static int bvh_partition(BVHNode **a, int lo, int hi, BVHNode * x, int axis) 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; + j--; + while (x->bv[axis] < (a[j])->bv[axis]) j--; if(!(i < j)) return i; - bvh_exchange(a, i,j); + SWAP( BVHNode* , a[i], a[j]); i++; } } @@ -177,7 +172,7 @@ static void bvh_heapsort(BVHNode **a, int lo, int hi, int axis) } for (i=n; i>1; i=i-1) { - bvh_exchange(a, lo,lo+i-1); + SWAP(BVHNode*, a[lo],a[lo+i-1]); bvh_downheap(a, 1,i-1,lo, axis); } } @@ -244,6 +239,25 @@ void sort_along_axis(BVHTree *tree, int start, int end, int axis) sort(tree->nodes, start, end, axis); } +//after a call to this function you can expect one of: +// every node to left of a[n] are smaller than it +// every node to the right of a[n-1] are greater than it +void partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis) +{ + int begin = _begin, end = _end; + while(begin < n && end >= n) + { + int mid = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end-1)/2, end-1, axis), axis ); + + if(mid >= n) + end = n-1; + else + begin = n+1; + } + +} + + ////////////////////////////////////////////////////////////////////////////////////////////////////// void BLI_bvhtree_free(BVHTree *tree) @@ -359,10 +373,11 @@ static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoi } // depends on the fact that the BVH's for each face is already build -static void refit_kdop_hull(BVHTree *tree, int start, int end, float *bv) +static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) { float newmin,newmax; int i, j; + float *bv = node->bv; for (i = tree->start_axis; i < tree->stop_axis; i++) { @@ -451,16 +466,14 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char // Determine which axis to split along laxis = get_largest_axis(node->bv); - - // Sort along longest axis - if(laxis!=lastaxis) - sort_along_axis(tree, start, end, laxis); // split nodes along longest axis for (i=0; start < end; start += slice, i++) //i counts the current child { tend = start + slice; + partition_nth_element(tree->nodes, start, end, tend, laxis); + if(tend > end) tend = end; if(tend-start == 1) // ok, we have 1 left for this node @@ -474,7 +487,7 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char tree->totbranch++; tnode->parent = node; - refit_kdop_hull(tree, start, tend, tnode->bv); + partition_nth_element(tree->nodes, start, end, tend, laxis); bvh_div_nodes(tree, tnode, start, tend, laxis); } node->totnode++; @@ -533,7 +546,6 @@ static void verify_tree(BVHTree *tree) void BLI_bvhtree_balance(BVHTree *tree) { BVHNode *node; - int i; if(tree->totleaf == 0) return; @@ -543,11 +555,11 @@ void BLI_bvhtree_balance(BVHTree *tree) tree->totbranch++; // refit root bvh node - refit_kdop_hull(tree, 0, tree->totleaf, tree->nodes[tree->totleaf]->bv); + refit_kdop_hull(tree, tree->nodes[tree->totleaf], 0, tree->totleaf); // create + balance tree bvh_div_nodes(tree, tree->nodes[tree->totleaf], 0, tree->totleaf, 0); - verify_tree(tree); + // verify_tree(tree); } // overlap - is it possbile for 2 bv's to collide ? From 3bb43aaaafdda6fcbd1b7fab1e1ea473afc5e527 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 13 May 2008 22:29:50 +0000 Subject: [PATCH 090/101] bug in bvhkdop (bad diff merged, pointed out by jaguarandi) --- source/blender/blenlib/intern/BLI_kdopbvh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 75ff1d8f257..b80fe2103ed 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -488,6 +488,7 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char tnode->parent = node; partition_nth_element(tree->nodes, start, end, tend, laxis); + refit_kdop_hull(tree, tnode, start, tend); bvh_div_nodes(tree, tnode, start, tend, laxis); } node->totnode++; From 83c2acccfbf311780b7fc3ea7aa8b5e0f4e03242 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 13 May 2008 22:30:59 +0000 Subject: [PATCH 091/101] stupid me - i left the wrong line in. --- source/blender/blenlib/intern/BLI_kdopbvh.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index b80fe2103ed..0d130cd37da 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -487,7 +487,6 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char tree->totbranch++; tnode->parent = node; - partition_nth_element(tree->nodes, start, end, tend, laxis); refit_kdop_hull(tree, tnode, start, tend); bvh_div_nodes(tree, tnode, start, tend, laxis); } From 4d8b5587b867e53c22b4f3f3c56ba8714e9b7bfb Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 14 May 2008 16:09:56 +0000 Subject: [PATCH 092/101] Pre merge commit (includes commented moving stuff) --- source/blender/blenkernel/intern/cloth.c | 40 ++- source/blender/blenkernel/intern/collision.c | 276 ++++++++++++------- source/blender/blenkernel/intern/modifier.c | 2 +- source/blender/blenlib/intern/BLI_kdopbvh.c | 37 ++- 4 files changed, 251 insertions(+), 104 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 192ebd90faa..6eb9f731056 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -47,6 +47,8 @@ #include "BLI_kdopbvh.h" +#include + #ifdef _WIN32 void tstart ( void ) {} @@ -78,6 +80,40 @@ double tval() } #endif + +/* Util macros */ +#define TO_STR(a) #a +#define JOIN(a,b) a##b + +/* Benchmark macros */ +#if 1 + +#define BENCH(a) \ + do { \ + clock_t _clock_init = clock(); \ + (a); \ + printf("%s: %fms\n", #a, (float)(clock()-_clock_init)*1000/CLOCKS_PER_SEC); \ +} while(0) + +#define BENCH_VAR(name) clock_t JOIN(_bench_step,name) = 0, JOIN(_bench_total,name) = 0 +#define BENCH_BEGIN(name) JOIN(_bench_step, name) = clock() +#define BENCH_END(name) JOIN(_bench_total,name) += clock() - JOIN(_bench_step,name) +#define BENCH_RESET(name) JOIN(_bench_total, name) = 0 +#define BENCH_REPORT(name) printf("%s: %fms\n", TO_STR(name), JOIN(_bench_total,name)*1000.0f/CLOCKS_PER_SEC) + +#else + +#define BENCH(a) (a) +#define BENCH_VAR(name) +#define BENCH_BEGIN(name) +#define BENCH_END(name) +#define BENCH_RESET(name) +#define BENCH_REPORT(name) + +#endif + + + /* Our available solvers. */ // 255 is the magic reserved number, so NEVER try to put 255 solvers in here! // 254 = MAX! @@ -178,7 +214,7 @@ BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) return NULL; // create quadtree with k=26 - bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 4, 26); + bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 8, 6); // fill tree for(i = 0; i < cloth->numfaces; i++, mfaces++) @@ -866,7 +902,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if(!first) implicit_set_positions(clmd); - clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); + BENCH(clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon )); return 1; } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 9ba47874d3c..1e8b8706658 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -608,22 +608,9 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier result = 1; } } - - return result; } -int cloth_collision_response_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd ) -{ - return 1; -} - - -int cloth_collision_response_moving_edges ( ClothModifierData *clmd, ClothModifierData *coll_clmd ) -{ - return 1; -} - //Determines collisions on overlap, collisions are writen to collpair[i] and collision+number_collision_found is returned CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap *overlap, CollPair *collpair ) { @@ -743,25 +730,148 @@ int cloth_are_edges_adjacent ( ClothModifierData *clmd, CollisionModifierData *c cloth1 = clmd->clothObject; verts1 = cloth1->verts; - VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].co ); + VECSUB ( temp, verts1[edgecollpair->p11].txold, verts2[edgecollpair->p21].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].co ); + VECSUB ( temp, verts1[edgecollpair->p11].txold, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].co ); + VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p21].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - VECSUB ( temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].co ); + VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; + + VECSUB ( temp, verts1[edgecollpair->p11].txold, verts1[edgecollpair->p12].txold ); + if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) + return 1; + + VECSUB ( temp, verts2[edgecollpair->p21].co, verts2[edgecollpair->p22].co ); + if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) + return 1; + return 0; } +int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) +{ + int result = 0; + Cloth *cloth1; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + float epsilon2 = BLI_bvhtree_getepsilon ( collmd->bvhtree ); + + cloth1 = clmd->clothObject; + + for ( ; collpair != collision_end; collpair++ ) + { + // only handle static collisions here + if ( collpair->flag & COLLISION_IN_FUTURE ) + continue; + + // compute barycentric coordinates for both collision points + collision_compute_barycentric ( collpair->pa, + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3 ); + + // was: txold + collision_compute_barycentric ( collpair->pb, + collmd->current_x[collpair->bp1].co, + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, + &u1, &u2, &u3 ); + + // Calculate relative "velocity". + collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 ); + + collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 ); + + VECSUB ( relativeVelocity, v2, v1 ); + + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). + magrelVel = INPR ( relativeVelocity, collpair->normal ); + + // printf("magrelVel: %f\n", magrelVel); + + // Calculate masses of points. + // TODO + + // If v_n_mag < 0 the edges are approaching each other. + if ( magrelVel > ALMOST_ZERO ) + { + // Calculate Impulse magnitude to stop all motion in normal direction. + float magtangent = 0, repulse = 0, d = 0; + double impulse = 0.0; + float vrel_t_pre[3]; + float temp[3]; + + // calculate tangential velocity + VECCOPY ( temp, collpair->normal ); + VecMulf ( temp, magrelVel ); + VECSUB ( vrel_t_pre, relativeVelocity, temp ); + + // Decrease in magnitude of relative tangential velocity due to coulomb friction + // in original formula "magrelVel" should be the "change of relative velocity in normal direction" + magtangent = MIN2 ( clmd->coll_parms->friction * 0.01 * magrelVel,sqrt ( INPR ( vrel_t_pre,vrel_t_pre ) ) ); + + // Apply friction impulse. + if ( magtangent > ALMOST_ZERO ) + { + Normalize ( vrel_t_pre ); + + impulse = 2.0 * magtangent / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); + VECADDMUL ( cloth1->verts[collpair->ap1].impulse, vrel_t_pre, w1 * impulse ); + VECADDMUL ( cloth1->verts[collpair->ap2].impulse, vrel_t_pre, w2 * impulse ); + VECADDMUL ( cloth1->verts[collpair->ap3].impulse, vrel_t_pre, w3 * impulse ); + } + + // Apply velocity stopping impulse + // I_c = m * v_N / 2.0 + // no 2.0 * magrelVel normally, but looks nicer DG + impulse = magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); + + VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse ); + cloth1->verts[collpair->ap1].impulse_count++; + + VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse ); + cloth1->verts[collpair->ap2].impulse_count++; + + VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse ); + cloth1->verts[collpair->ap3].impulse_count++; + + // Apply repulse impulse if distance too short + // I_r = -min(dt*kd, m(0,1d/dt - v_n)) + /* + d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance; + if ( ( magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame ) && ( d > ALMOST_ZERO ) ) + { + repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel ); + + // stay on the safe side and clamp repulse + if ( impulse > ALMOST_ZERO ) + repulse = MIN2 ( repulse, 5.0*impulse ); + repulse = MAX2 ( impulse, repulse ); + + impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25 + VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse ); + VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse ); + VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse ); + } +*/ + result = 1; + } + } + return result; +} + int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) { EdgeCollPair edgecollpair; @@ -781,53 +891,6 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat cloth1 = clmd->clothObject; verts1 = cloth1->verts; - /* - double p[4][3] = {{0,0,0},{0,2,0},{1,1,-1},{1,1,1}}; - double v[4][3] = {{0,0,0},{1,0,0},{-2,0,0},{-2,0,0}}; - - double pp[2][3] = {{-1,-1,-1}, {2,2,2}}; - - - VECSUB ( x1, p[1], p[0] ); - VECSUB ( v1, v[1], v[0] ); - - VECSUB ( x2, p[2], p[0] ); - VECSUB ( v2, v[2], v[0] ); - - VECSUB ( x3, p[3], p[0] ); - VECSUB ( v3, v[3], v[0] ); - - printf("x1 x: %f, y: %f, z: %f\n", x1[0], x1[1], x1[2]); - printf("x2 x: %f, y: %f, z: %f\n", x2[0], x2[1], x2[2]); - printf("x3 x: %f, y: %f, z: %f\n", x3[0], x3[1], x3[2]); - - printf("v1 x: %f, y: %f, z: %f\n", v1[0], v1[1], v1[2]); - printf("v2 x: %f, y: %f, z: %f\n", v2[0], v2[1], v2[2]); - printf("v3 x: %f, y: %f, z: %f\n", v3[0], v3[1], v3[2]); - - numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution ); - - for ( k = 0; k < numsolutions; k++ ) - printf("mintime: %f\n", solution[k]); - - mintime = solution[0]; - - // move triangles to collision point in time - VECADDS(triA[0], pp[0], v[0], solution[0]); - VECADDS(triA[1], p[0], v[0], solution[0]); - VECADDS(triA[2], p[1], v[1], solution[0]); - - VECADDS(triB[0], pp[1], v[0], solution[0]); - VECADDS(triB[1], p[2], v[2], solution[0]); - VECADDS(triB[2], p[3], v[3], solution[0]); - - // check distance there - distance = plNearestPoints (triA[0], triA[1], triA[2], triB[0], triB[1], triB[2], collpair->pa,collpair->pb,collpair->vector ); - - printf("mintime: %f, dist: %f\n", mintime, distance); - - exit(0); - */ for(i = 0; i < 9; i++) { // 9 edge - edge possibilities @@ -916,19 +979,12 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat VECSUB ( x3, verts2[edgecollpair.p22].co, verts1[edgecollpair.p11].txold ); VECSUB ( v3, velocity2[edgecollpair.p22].co, verts1[edgecollpair.p11].tv ); - /* - printf("A x: %f, y: %f, z: %f\n", a[0], a[1], a[2]); - printf("B x: %f, y: %f, z: %f\n", b[0], b[1], b[2]); - printf("C x: %f, y: %f, z: %f\n", c[0], c[1], c[2]); - printf("D x: %f, y: %f, z: %f\n", d[0], d[1], d[2]); - printf("E x: %f, y: %f, z: %f\n", e[0], e[1], e[2]); - printf("F x: %f, y: %f, z: %f\n", f[0], f[1], f[2]); - exit(0); - */ + numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution ); for ( k = 0; k < numsolutions; k++ ) { + // printf("sol %d: %lf\n", k, solution[k]); if ( ( solution[k] >= DBL_EPSILON ) && ( solution[k] <= 1.0 ) ) { //float out_collisionTime = solution[k]; @@ -939,8 +995,6 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat mintime = MIN2(mintime, (float)solution[k]); -// printf("mt: %f, %lf, %f\n", mintime, solution[k], (float)solution[k]); - result = 1; break; } @@ -962,12 +1016,25 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat // check distance there distance = plNearestPoints (triA[0], triA[1], triA[2], triB[0], triB[1], triB[2], collpair->pa,collpair->pb,collpair->vector ); - printf("mintime: %f, dist: %f\n", mintime, distance); + if(distance <= (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO)) + { + CollPair *next = collpair; + next++; + + collpair->distance = clmd->coll_parms->epsilon; + collpair->time = mintime; + + VECCOPY ( collpair->normal, collpair->vector ); + Normalize ( collpair->normal ); + + cloth_collision_response_moving ( clmd, collmd, collpair, next ); + } } return result; } +/* void cloth_collision_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 ) { CollPair collpair; @@ -1060,16 +1127,6 @@ void cloth_collision_moving_tris ( ClothModifierData *clmd, ClothModifierData *c } } } - -/* -void cloth_collision_moving ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 ) -{ - // TODO: check for adjacent - cloth_collision_moving_edges ( clmd, coll_clmd, tree1, tree2 ); - - cloth_collision_moving_tris ( clmd, coll_clmd, tree1, tree2 ); - cloth_collision_moving_tris ( coll_clmd, clmd, tree2, tree1 ); -} */ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) @@ -1150,24 +1207,43 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData if ( collmd->bvhtree ) { result += cloth_collision_response_static ( clmd, collmd, collisions, collisions_index ); - result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); - } - // apply impulses in parallel - if ( result ) - { - for ( i = 0; i < numverts; i++ ) + // apply impulses in parallel + if ( result ) { - // calculate "velocities" (just xnew = xold + v; no dt in v) - if ( verts[i].impulse_count ) + for ( i = 0; i < numverts; i++ ) { - VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count ); - VECCOPY ( verts[i].impulse, tnull ); - verts[i].impulse_count = 0; - - ret++; + // calculate "velocities" (just xnew = xold + v; no dt in v) + if ( verts[i].impulse_count ) + { + VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count ); + VECCOPY ( verts[i].impulse, tnull ); + verts[i].impulse_count = 0; + + ret++; + } } } + /* + result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); + + // apply impulses in parallel + if ( result ) + { + for ( i = 0; i < numverts; i++ ) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if ( verts[i].impulse_count ) + { + VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count ); + VECCOPY ( verts[i].impulse, tnull ); + verts[i].impulse_count = 0; + + ret++; + } + } + } + */ } } @@ -1207,7 +1283,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// // update cloth bvh - bvhtree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) + bvhtree_update_from_cloth ( clmd, 1 ); // 0 means STATIC, 1 means MOVING (see later in this function) do { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index a29c10a95ac..b481055ff16 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5417,7 +5417,7 @@ static void collisionModifier_deformVerts( else { // recalc static bounding boxes - bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, NULL, collmd->numverts, 0 ); + bvhtree_update_from_mvert ( collmd->bvhtree, collmd->mfaces, collmd->numfaces, collmd->current_x, collmd->current_xnew, collmd->numverts, 1 ); } collmd->time = current_time; diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 0d130cd37da..b3f11039ce1 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -46,6 +46,41 @@ #include #endif +#include + +/* Util macros */ +#define TO_STR(a) #a +#define JOIN(a,b) a##b + +/* Benchmark macros */ +#if 1 + +#define BENCH(a) \ + do { \ + clock_t _clock_init = clock(); \ + (a); \ + printf("%s: %fms\n", #a, (float)(clock()-_clock_init)*1000/CLOCKS_PER_SEC); \ +} while(0) + +#define BENCH_VAR(name) clock_t JOIN(_bench_step,name) = 0, JOIN(_bench_total,name) = 0 +#define BENCH_BEGIN(name) JOIN(_bench_step, name) = clock() +#define BENCH_END(name) JOIN(_bench_total,name) += clock() - JOIN(_bench_step,name) +#define BENCH_RESET(name) JOIN(_bench_total, name) = 0 +#define BENCH_REPORT(name) printf("%s: %fms\n", TO_STR(name), JOIN(_bench_total,name)*1000.0f/CLOCKS_PER_SEC) + +#else + +#define BENCH(a) (a) +#define BENCH_VAR(name) +#define BENCH_BEGIN(name) +#define BENCH_END(name) +#define BENCH_RESET(name) +#define BENCH_REPORT(name) + +#endif + + + typedef struct BVHNode { struct BVHNode *children[8]; // max 8 children @@ -61,7 +96,7 @@ struct BVHTree { BVHNode **nodes; BVHNode *nodearray; /* pre-alloc branch nodes */ - float epsilon; /* epslion is used for inflation of the k-dop */ + float epsilon; /* epsilon is used for inflation of the k-dop */ int totleaf; // leafs int totbranch; char tree_type; // type of tree (4 => quadtree) From 4bf01e8162dd3c30791a8a1d5d20fc80fbdef1ac Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 23 May 2008 20:20:14 +0000 Subject: [PATCH 093/101] Commit of selfcollisions using new kdop design. Should result in nice speedup. --- source/blender/blenkernel/BKE_cloth.h | 3 +- source/blender/blenkernel/intern/cloth.c | 103 ++++++++++++++++++- source/blender/blenkernel/intern/collision.c | 75 +++++++++++++- source/blender/blenlib/intern/BLI_kdopbvh.c | 87 ++++++++++------ 4 files changed, 234 insertions(+), 34 deletions(-) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index f01ed6bbea4..6575b8b873b 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -106,7 +106,7 @@ typedef struct Cloth unsigned char pad2; short pad3; struct BVHTree *bvhtree; /* collision tree for this cloth object */ - struct RayTree *selftree; /* collision tree for this cloth object */ + struct BVHTree *bvhselftree; /* collision tree for this cloth object */ struct MFace *mfaces; struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ struct Implicit_Data *implicitEM; /* our implicit solver connects to this pointer */ @@ -245,6 +245,7 @@ void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int tot // needed for collision.c void bvhtree_update_from_cloth ( ClothModifierData *clmd, int moving ); +void bvhselftree_update_from_cloth ( ClothModifierData *clmd, int moving ); // needed for editmesh.c void cloth_write_cache ( Object *ob, ClothModifierData *clmd, float framenr ); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 6eb9f731056..916e3d6d3e8 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -189,6 +189,47 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->goalfrict = 0.0f; } +BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) +{ + int i; + BVHTree *bvhtree; + Cloth *cloth = clmd->clothObject; + ClothVertex *verts; + MFace *mfaces; + float co[12]; + + if(!clmd) + return NULL; + + cloth = clmd->clothObject; + + if(!cloth) + return NULL; + + verts = cloth->verts; + mfaces = cloth->mfaces; + + // in the moment, return zero if no faces there + if(!cloth->numfaces) + return NULL; + + // create quadtree with k=26 + bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 4, 6); + + // fill tree + for(i = 0; i < cloth->numverts; i++, verts++) + { + VECCOPY(&co[0*3], verts->xold); + + BLI_bvhtree_insert(bvhtree, i, co, 1); + } + + // balance tree + BLI_bvhtree_balance(bvhtree); + + return bvhtree; +} + BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) { int i; @@ -214,7 +255,7 @@ BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon) return NULL; // create quadtree with k=26 - bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 8, 6); + bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 4, 26); // fill tree for(i = 0; i < cloth->numfaces; i++, mfaces++) @@ -289,6 +330,50 @@ void bvhtree_update_from_cloth(ClothModifierData *clmd, int moving) } } +void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving) +{ + unsigned int i = 0; + Cloth *cloth = clmd->clothObject; + BVHTree *bvhtree = cloth->bvhselftree; + ClothVertex *verts = cloth->verts; + MFace *mfaces; + float co[12], co_moving[12]; + int ret = 0; + + if(!bvhtree) + return; + + mfaces = cloth->mfaces; + + // update vertex position in bvh tree + if(verts && mfaces) + { + for(i = 0; i < cloth->numverts; i++, verts++) + { + VECCOPY(&co[0*3], verts->txold); + + // copy new locations into array + if(moving) + { + // update moving positions + VECCOPY(&co_moving[0*3], verts->tx); + + ret = BLI_bvhtree_update_node(bvhtree, i, co, co_moving, 1); + } + else + { + ret = BLI_bvhtree_update_node(bvhtree, i, co, NULL, 1); + } + + // check if tree is already full + if(!ret) + break; + } + + BLI_bvhtree_update_tree(bvhtree); + } +} + int modifiers_indexInObject(Object *ob, ModifierData *md_seek); int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) @@ -599,6 +684,9 @@ void cloth_free_modifier ( Object *ob, ClothModifierData *clmd ) // free BVH collision tree if ( cloth->bvhtree ) BLI_bvhtree_free ( cloth->bvhtree ); + + if ( cloth->bvhselftree ) + BLI_bvhtree_free ( cloth->bvhselftree ); // we save our faces for collision objects if ( cloth->mfaces ) @@ -669,6 +757,9 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd ) // free BVH collision tree if ( cloth->bvhtree ) BLI_bvhtree_free ( cloth->bvhtree ); + + if ( cloth->bvhselftree ) + BLI_bvhtree_free ( cloth->bvhselftree ); // we save our faces for collision objects if ( cloth->mfaces ) @@ -807,6 +898,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d ClothVertex *verts = NULL; float tnull[3] = {0,0,0}; Cloth *cloth = NULL; + float maxdist = 0; // If we have a clothObject, free it. if ( clmd->clothObject != NULL ) @@ -876,7 +968,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d // apply / set vertex groups // has to be happen before springs are build! cloth_apply_vgroup (clmd, dm); - + if ( !cloth_build_springs ( clmd, dm ) ) { @@ -904,6 +996,13 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d BENCH(clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon )); + for(i = 0; i < dm->getNumVerts(dm); i++) + { + maxdist = MAX2(maxdist, clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len*2.0)); + } + + clmd->clothObject->bvhselftree = bvhselftree_build_from_cloth ( clmd, maxdist ); + return 1; } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 1e8b8706658..4d49ccc9eb3 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1260,7 +1260,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) Cloth *cloth=NULL; Object *coll_ob=NULL; BVHTree *cloth_bvh=NULL; - long i=0, j = 0, numfaces = 0, numverts = 0; + long i=0, j = 0, k = 0, numfaces = 0, numverts = 0; unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; int ret = 0; @@ -1284,6 +1284,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) // update cloth bvh bvhtree_update_from_cloth ( clmd, 1 ); // 0 means STATIC, 1 means MOVING (see later in this function) + bvhselftree_update_from_cloth ( clmd, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) do { @@ -1357,12 +1358,82 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) if ( clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { - MFace *mface = clmd->clothObject->mfaces; + MFace *mface = cloth->mfaces; + BVHTreeOverlap *overlap = NULL; collisions = 1; verts = cloth->verts; // needed for openMP + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + verts = cloth->verts; + + if ( cloth->bvhselftree ) + { + /* search for overlapping collision pairs */ + overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); + + for ( k = 0; k < result; k++ ) + { + float temp[3]; + float length = 0; + float mindistance; + + i = overlap[k].indexA; + j = overlap[k].indexB; + + mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); + + if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + { + if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) + { + continue; + } + } + + VECSUB ( temp, verts[i].tx, verts[j].tx ); + + if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; + + // check for adjacent points (i must be smaller j) + if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) + { + continue; + } + + length = Normalize ( temp ); + + if ( length < mindistance ) + { + float correction = mindistance - length; + + if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, -correction ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + } + else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) + { + VecMulf ( temp, correction ); + VECADD ( verts[i].tx, verts[i].tx, temp ); + } + else + { + VecMulf ( temp, -correction*0.5 ); + VECADD ( verts[j].tx, verts[j].tx, temp ); + + VECSUB ( verts[i].tx, verts[i].tx, temp ); + } + } + } + + if ( overlap ) + MEM_freeN ( overlap ); + + } /* for ( count = 0; count < clmd->coll_parms->self_loop_count; count++ ) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index b3f11039ce1..83afe258aad 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -80,12 +80,11 @@ #endif - typedef struct BVHNode { - struct BVHNode *children[8]; // max 8 children + struct BVHNode **children; // max 8 children struct BVHNode *parent; // needed for bottom - top update - float bv[26]; // Bounding volume of all nodes, max 13 axis + float *bv; // Bounding volume of all nodes, max 13 axis int index; /* face, edge, vertex index */ char totnode; // how many nodes are used, used for speedup char traversed; // how many nodes already traversed until this level? @@ -96,7 +95,9 @@ struct BVHTree { BVHNode **nodes; BVHNode *nodearray; /* pre-alloc branch nodes */ - float epsilon; /* epsilon is used for inflation of the k-dop */ + BVHNode **nodechild; // pre-alloc childs for nodes + float *nodebv; // pre-alloc bounding-volumes for nodes + float epsilon; /* epslion is used for inflation of the k-dop */ int totleaf; // leafs int totbranch; char tree_type; // type of tree (4 => quadtree) @@ -301,6 +302,8 @@ void BLI_bvhtree_free(BVHTree *tree) { MEM_freeN(tree->nodes); MEM_freeN(tree->nodearray); + MEM_freeN(tree->nodebv); + MEM_freeN(tree->nodechild); MEM_freeN(tree); } } @@ -318,27 +321,6 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) if(tree) { - // calculate max number of branches, our bvh kdop is "almost perfect" - for(i = 1; i <= (int)ceil((float)((float)log(maxsize)/(float)log(tree_type))); i++) - numbranches += (pow(tree_type, i) / tree_type); - - tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*(numbranches+maxsize + tree_type), "BVHNodes"); - - if(!tree->nodes) - { - MEM_freeN(tree); - return NULL; - } - - tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)*(numbranches+maxsize + tree_type), "BVHNodeArray"); - - if(!tree->nodearray) - { - MEM_freeN(tree); - MEM_freeN(tree->nodes); - return NULL; - } - tree->epsilon = epsilon; tree->tree_type = tree_type; tree->axis = axis; @@ -370,14 +352,62 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) } else { - BLI_bvhtree_free(tree); + MEM_freeN(tree); return NULL; } + + + // calculate max number of branches, our bvh kdop is "almost perfect" + for(i = 1; i <= (int)ceil((float)((float)log(maxsize)/(float)log(tree_type))); i++) + numbranches += (pow(tree_type, i) / tree_type); + + tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *)*(numbranches+maxsize + tree_type), "BVHNodes"); + + if(!tree->nodes) + { + MEM_freeN(tree); + return NULL; + } + + tree->nodebv = (float*)MEM_callocN(sizeof(float)* axis * (numbranches+maxsize + tree_type), "BVHNodeBV"); + if(!tree->nodebv) + { + MEM_freeN(tree->nodes); + MEM_freeN(tree); + } + + tree->nodechild = (BVHNode**)MEM_callocN(sizeof(BVHNode*) * tree_type * (numbranches+maxsize + tree_type), "BVHNodeBV"); + if(!tree->nodechild) + { + MEM_freeN(tree->nodebv); + MEM_freeN(tree->nodes); + MEM_freeN(tree); + } + + tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode)*(numbranches+maxsize + tree_type), "BVHNodeArray"); + + if(!tree->nodearray) + { + MEM_freeN(tree->nodechild); + MEM_freeN(tree->nodebv); + MEM_freeN(tree->nodes); + MEM_freeN(tree); + return NULL; + } + + //link the dynamic bv and child links + for(i=0; i< numbranches+maxsize + tree_type; i++) + { + tree->nodearray[i].bv = tree->nodebv + i * axis; + tree->nodearray[i].children = tree->nodechild + i * tree_type; + } + } return tree; } + static void create_kdop_hull(BVHTree *tree, BVHNode *node, float *co, int numpoints, int moving) { float newminmax; @@ -507,8 +537,6 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char { tend = start + slice; - partition_nth_element(tree->nodes, start, end, tend, laxis); - if(tend > end) tend = end; if(tend-start == 1) // ok, we have 1 left for this node @@ -521,7 +549,8 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char tnode = node->children[i] = tree->nodes[tree->totleaf + tree->totbranch] = &(tree->nodearray[tree->totbranch + tree->totleaf]); tree->totbranch++; tnode->parent = node; - + + partition_nth_element(tree->nodes, start, end, tend, laxis); refit_kdop_hull(tree, tnode, start, tend); bvh_div_nodes(tree, tnode, start, tend, laxis); } From fcea4573dde1ba64dffed2301447154647924b6a Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 25 May 2008 13:15:54 +0000 Subject: [PATCH 094/101] =?UTF-8?q?-=3D=3D=20Cloth=20/=20kdop=20=3D=3D-=20?= =?UTF-8?q?1.=20Bugfix=20for=20crash=20on=20enabling=20cloth=20on=20object?= =?UTF-8?q?=202.=20Correcting=20kdop=20nth=20element=20sorting=20function?= =?UTF-8?q?=20(fix=20provided=20by=20Andr=C3=A9=20Pinto)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/blender/blenkernel/intern/cloth.c | 4 +-- source/blender/blenlib/intern/BLI_kdopbvh.c | 37 ++++++++++++--------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 916e3d6d3e8..55d89e5f0dd 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -210,11 +210,11 @@ BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon) mfaces = cloth->mfaces; // in the moment, return zero if no faces there - if(!cloth->numfaces) + if(!cloth->numverts) return NULL; // create quadtree with k=26 - bvhtree = BLI_bvhtree_new(cloth->numfaces, epsilon, 4, 6); + bvhtree = BLI_bvhtree_new(cloth->numverts, epsilon, 4, 6); // fill tree for(i = 0; i < cloth->numverts; i++, verts++) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 83afe258aad..5c3849d1210 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -276,21 +276,22 @@ void sort_along_axis(BVHTree *tree, int start, int end, int axis) } //after a call to this function you can expect one of: -// every node to left of a[n] are smaller than it -// every node to the right of a[n-1] are greater than it -void partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis) -{ - int begin = _begin, end = _end; - while(begin < n && end >= n) - { - int mid = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end-1)/2, end-1, axis), axis ); - - if(mid >= n) - end = n-1; - else - begin = n+1; - } +// every node to left of a[n] are smaller or equal to it +// every node to the right of a[n] are greater or equal to it +int partition_nth_element(BVHNode **a, int _begin, int _end, int n, int axis){ + int begin = _begin, end = _end, cut; + int i; + while(end-begin > 3) + { + cut = bvh_partition(a, begin, end, bvh_medianof3(a, begin, (begin+end)/2, end-1, axis), axis ); + if(cut <= n) + begin = cut; + else + end = cut; + } + bvh_insertionsort(a, begin, end, axis); + return n; } @@ -550,7 +551,8 @@ static void bvh_div_nodes(BVHTree *tree, BVHNode *node, int start, int end, char tree->totbranch++; tnode->parent = node; - partition_nth_element(tree->nodes, start, end, tend, laxis); + if(tend != end) + partition_nth_element(tree->nodes, start, end, tend, laxis); refit_kdop_hull(tree, tnode, start, tend); bvh_div_nodes(tree, tnode, start, tend, laxis); } @@ -707,7 +709,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) { int j, total = 0; BVHTreeOverlap *overlap = NULL, *to = NULL; - BVHOverlapData *data[tree1->tree_type]; + BVHOverlapData **data; // check for compatibility of both trees (can't compare 14-DOP with 18-DOP) if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14)) @@ -716,6 +718,8 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) // fast check root nodes for collision before doing big splitting + traversal if(!tree_overlap(tree1->nodes[tree1->totleaf]->bv, tree2->nodes[tree2->totleaf]->bv, MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis))) return 0; + + *data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star"); for(j = 0; j < tree1->tree_type; j++) { @@ -751,6 +755,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) free(data[j]->overlap); MEM_freeN(data[j]); } + MEM_freeN(*data); (*result) = total; return overlap; From 2666ff7075bfd9b5be349b55243697afbfc1967b Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sun, 25 May 2008 14:34:03 +0000 Subject: [PATCH 095/101] -== kdop ==- 1. fix crash on collision --- source/blender/blenlib/intern/BLI_kdopbvh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 5c3849d1210..cf326f3f460 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -719,7 +719,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) if(!tree_overlap(tree1->nodes[tree1->totleaf]->bv, tree2->nodes[tree2->totleaf]->bv, MIN2(tree1->start_axis, tree2->start_axis), MIN2(tree1->stop_axis, tree2->stop_axis))) return 0; - *data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star"); + data = MEM_callocN(sizeof(BVHOverlapData *)* tree1->tree_type, "BVHOverlapData_star"); for(j = 0; j < tree1->tree_type; j++) { @@ -755,7 +755,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) free(data[j]->overlap); MEM_freeN(data[j]); } - MEM_freeN(*data); + MEM_freeN(data); (*result) = total; return overlap; From cb378cbceb22ca95b4e60e46208bd1922641f00b Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 26 May 2008 09:39:32 +0000 Subject: [PATCH 096/101] -= Cloth =- 1. Fix selfcollisions (reported by nudelZ) --- source/blender/blenkernel/intern/cloth.c | 11 +- source/blender/blenkernel/intern/collision.c | 697 +++++++++++-------- 2 files changed, 424 insertions(+), 284 deletions(-) diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 55d89e5f0dd..4fb8eeda78d 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -499,15 +499,15 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul Mat4MulVecfl(ob->obmat, verts->xconst); } - tstart(); + // tstart(); /* call the solver. */ if(solvers [clmd->sim_parms->solver_type].solver) - ret = solvers[clmd->sim_parms->solver_type].solver(ob, framenr, clmd, effectors); + BENCH(ret = solvers[clmd->sim_parms->solver_type].solver(ob, framenr, clmd, effectors)); - tend(); + // tend(); - printf ( "Cloth simulation time: %f\n", ( float ) tval() ); + // printf ( "Cloth simulation time: %f\n", ( float ) tval() ); return ret; } @@ -969,7 +969,6 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d // has to be happen before springs are build! cloth_apply_vgroup (clmd, dm); - if ( !cloth_build_springs ( clmd, dm ) ) { cloth_free_modifier ( ob, clmd ); @@ -994,7 +993,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d if(!first) implicit_set_positions(clmd); - BENCH(clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon )); + clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); for(i = 0; i < dm->getNumVerts(dm); i++) { diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 4d49ccc9eb3..edf8fec9ae1 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -178,16 +178,16 @@ Collision modifier code end ***********************************/ /** - * gsl_poly_solve_cubic - - * - * copied from SOLVE_CUBIC.C --> GSL - */ +* gsl_poly_solve_cubic - +* +* copied from SOLVE_CUBIC.C --> GSL +*/ #define mySWAP(a,b) do { double tmp = b ; b = a ; a = tmp ; } while(0) int - gsl_poly_solve_cubic (double a, double b, double c, - double *x0, double *x1, double *x2) +gsl_poly_solve_cubic (double a, double b, double c, + double *x0, double *x1, double *x2) { double q = (a * a - 3 * b); double r = (2 * a * a * a - 9 * a * b + 27 * c); @@ -210,10 +210,10 @@ int } else if (CR2 == CQ3) { - /* this test is actually R2 == Q3, written in a form suitable + /* this test is actually R2 == Q3, written in a form suitable for exact computation with integers */ - /* Due to finite precision some double roots may be missed, and + /* Due to finite precision some double roots may be missed, and considered to be a pair of complex roots z = x +/- epsilon i close to the real axis. */ @@ -242,20 +242,20 @@ int *x0 = norm * cos (theta / 3) - a / 3; *x1 = norm * cos ((theta + 2.0 * M_PI) / 3) - a / 3; *x2 = norm * cos ((theta - 2.0 * M_PI) / 3) - a / 3; - + /* Sort *x0, *x1, *x2 into increasing order */ if (*x0 > *x1) mySWAP(*x0, *x1) ; - + if (*x1 > *x2) { mySWAP(*x1, *x2) ; - + if (*x0 > *x1) mySWAP(*x0, *x1) ; } - + return 3; } else @@ -271,13 +271,13 @@ int /** - * gsl_poly_solve_quadratic - * - * copied from GSL - */ +* gsl_poly_solve_quadratic +* +* copied from GSL +*/ int - gsl_poly_solve_quadratic (double a, double b, double c, - double *x0, double *x1) +gsl_poly_solve_quadratic (double a, double b, double c, + double *x0, double *x1) { double disc = b * b - 4 * a * c; @@ -338,55 +338,55 @@ int /* - * See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation" - * page 4, left column - */ +* See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation" +* page 4, left column +*/ int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3], double e[3], double f[3], double solution[3] ) { int num_sols = 0; // x^0 - checked double g = a[0] * c[1] * e[2] - a[0] * c[2] * e[1] + - a[1] * c[2] * e[0] - a[1] * c[0] * e[2] + - a[2] * c[0] * e[1] - a[2] * c[1] * e[0]; - + a[1] * c[2] * e[0] - a[1] * c[0] * e[2] + + a[2] * c[0] * e[1] - a[2] * c[1] * e[0]; + // x^1 double h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] + - a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] + - a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] + - b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] - - a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] - - a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2]; + a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] + + a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] + + b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] - + a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] - + a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2]; // x^2 double i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] + - b[2] * d[0] * e[1] - b[0] * d[2] * e[1] - - b[1] * d[0] * e[2] + b[0] * d[1] * e[2] - - b[2] * c[1] * f[0] + b[1] * c[2] * f[0] - - a[2] * d[1] * f[0] + a[1] * d[2] * f[0] + - b[2] * c[0] * f[1] - b[0] * c[2] * f[1] + - a[2] * d[0] * f[1] - a[0] * d[2] * f[1] - - b[1] * c[0] * f[2] + b[0] * c[1] * f[2] - - a[1] * d[0] * f[2] + a[0] * d[1] * f[2]; - + b[2] * d[0] * e[1] - b[0] * d[2] * e[1] - + b[1] * d[0] * e[2] + b[0] * d[1] * e[2] - + b[2] * c[1] * f[0] + b[1] * c[2] * f[0] - + a[2] * d[1] * f[0] + a[1] * d[2] * f[0] + + b[2] * c[0] * f[1] - b[0] * c[2] * f[1] + + a[2] * d[0] * f[1] - a[0] * d[2] * f[1] - + b[1] * c[0] * f[2] + b[0] * c[1] * f[2] - + a[1] * d[0] * f[2] + a[0] * d[1] * f[2]; + // x^3 - checked double j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] + - b[2] * d[0] * f[1] - b[0] * d[2] * f[1] - - b[1] * d[0] * f[2] + b[0] * d[1] * f[2]; - + b[2] * d[0] * f[1] - b[0] * d[2] * f[1] - + b[1] * d[0] * f[2] + b[0] * d[1] * f[2]; + /* printf("r1: %lf\n", a[0] * c[1] * e[2] - a[0] * c[2] * e[1]); printf("r2: %lf\n", a[1] * c[2] * e[0] - a[1] * c[0] * e[2]); printf("r3: %lf\n", a[2] * c[0] * e[1] - a[2] * c[1] * e[0]); - + printf("x1 x: %f, y: %f, z: %f\n", a[0], a[1], a[2]); printf("x2 x: %f, y: %f, z: %f\n", c[0], c[1], c[2]); printf("x3 x: %f, y: %f, z: %f\n", e[0], e[1], e[2]); - + printf("v1 x: %f, y: %f, z: %f\n", b[0], b[1], b[2]); printf("v2 x: %f, y: %f, z: %f\n", d[0], d[1], d[2]); printf("v3 x: %f, y: %f, z: %f\n", f[0], f[1], f[2]); - + printf("t^3: %lf, t^2: %lf, t^1: %lf, t^0: %lf\n", j, i, h, g); */ @@ -517,17 +517,17 @@ int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifier // compute barycentric coordinates for both collision points collision_compute_barycentric ( collpair->pa, - cloth1->verts[collpair->ap1].txold, - cloth1->verts[collpair->ap2].txold, - cloth1->verts[collpair->ap3].txold, - &w1, &w2, &w3 ); + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3 ); // was: txold collision_compute_barycentric ( collpair->pb, - collmd->current_x[collpair->bp1].co, - collmd->current_x[collpair->bp2].co, - collmd->current_x[collpair->bp3].co, - &u1, &u2, &u3 ); + collmd->current_x[collpair->bp1].co, + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, + &u1, &u2, &u3 ); // Calculate relative "velocity". collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 ); @@ -696,7 +696,7 @@ CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap #ifdef WITH_BULLET // calc distance + normal distance = plNearestPoints ( - verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector ); + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, collmd->current_x[collpair->bp3].co, collpair->pa,collpair->pb,collpair->vector ); #else // just be sure that we don't add anything distance = 2.0 * ( epsilon1 + epsilon2 + ALMOST_ZERO ); @@ -745,15 +745,15 @@ int cloth_are_edges_adjacent ( ClothModifierData *clmd, CollisionModifierData *c VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - + VECSUB ( temp, verts1[edgecollpair->p11].txold, verts1[edgecollpair->p12].txold ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - + VECSUB ( temp, verts2[edgecollpair->p21].co, verts2[edgecollpair->p22].co ); if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) return 1; - + return 0; } @@ -771,23 +771,19 @@ int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierD for ( ; collpair != collision_end; collpair++ ) { - // only handle static collisions here - if ( collpair->flag & COLLISION_IN_FUTURE ) - continue; - // compute barycentric coordinates for both collision points collision_compute_barycentric ( collpair->pa, - cloth1->verts[collpair->ap1].txold, - cloth1->verts[collpair->ap2].txold, - cloth1->verts[collpair->ap3].txold, - &w1, &w2, &w3 ); + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3 ); // was: txold collision_compute_barycentric ( collpair->pb, - collmd->current_x[collpair->bp1].co, - collmd->current_x[collpair->bp2].co, - collmd->current_x[collpair->bp3].co, - &u1, &u2, &u3 ); + collmd->current_x[collpair->bp1].co, + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, + &u1, &u2, &u3 ); // Calculate relative "velocity". collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 ); @@ -853,25 +849,250 @@ int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierD d = clmd->coll_parms->epsilon*8.0/9.0 + epsilon2*8.0/9.0 - collpair->distance; if ( ( magrelVel < 0.1*d*clmd->sim_parms->stepsPerFrame ) && ( d > ALMOST_ZERO ) ) { - repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel ); + repulse = MIN2 ( d*1.0/clmd->sim_parms->stepsPerFrame, 0.1*d*clmd->sim_parms->stepsPerFrame - magrelVel ); - // stay on the safe side and clamp repulse - if ( impulse > ALMOST_ZERO ) - repulse = MIN2 ( repulse, 5.0*impulse ); - repulse = MAX2 ( impulse, repulse ); + // stay on the safe side and clamp repulse + if ( impulse > ALMOST_ZERO ) + repulse = MIN2 ( repulse, 5.0*impulse ); + repulse = MAX2 ( impulse, repulse ); - impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25 - VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse ); - VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse ); - VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse ); + impulse = repulse / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); // original 2.0 / 0.25 + VECADDMUL ( cloth1->verts[collpair->ap1].impulse, collpair->normal, impulse ); + VECADDMUL ( cloth1->verts[collpair->ap2].impulse, collpair->normal, impulse ); + VECADDMUL ( cloth1->verts[collpair->ap3].impulse, collpair->normal, impulse ); } -*/ + */ result = 1; } } return result; } +static float projectPointOntoLine(float *p, float *a, float *b) +{ + float ba[3], pa[3]; + VECSUB(ba, b, a); + VECSUB(pa, p, a); + return INPR(pa, ba) / INPR(ba, ba); +} + +static void calculateEENormal(float *np1, float *np2, float *np3, float *np4,float *out_normal) +{ + float line1[33], line2[3]; + float length; + + VECSUB(line1, np2, np1); + VECSUB(line2, np3, np1); + + Crossf(out_normal, line1, line2); + length = Normalize(out_normal); + if (length <= FLT_EPSILON) + { // lines are collinear + VECSUB(out_normal, np2, np1); + Normalize(out_normal); + } +} + +static void findClosestPointsEE(float *x1, float *x2, float *x3, float *x4, float *w1, float *w2) +{ + float temp[3], temp2[3]; + + double a, b, c, e, f; + + VECSUB(temp, x2, x1); + a = INPR(temp, temp); + + VECSUB(temp2, x4, x3); + b = -INPR(temp, temp2); + + c = INPR(temp2, temp2); + + VECSUB(temp2, x3, x1); + e = INPR(temp, temp2); + + VECSUB(temp, x4, x3); + f = -INPR(temp, temp2); + + *w1 = (e * c - b * f) / (a * c - b * b); + *w2 = (f - b * *w1) / c; + +} + +// calculates the distance of 2 edges +float edgedge_distance(float np11[3], float np12[3], float np21[3], float np22[3], float *out_a1, float *out_a2, float *out_normal) +{ + float line1[3], line2[3], cross[3]; + float length; + float temp[3], temp2[3]; + float dist_a1, dist_a2; + + VECSUB(line1, np12, np11); + VECSUB(line2, np22, np21); + + Crossf(cross, line1, line2); + length = INPR(cross, cross); + + if (length < FLT_EPSILON) + { + *out_a2 = projectPointOntoLine(np11, np21, np22); + if ((*out_a2 >= -FLT_EPSILON) && (*out_a2 <= 1.0 + FLT_EPSILON)) + { + *out_a1 = 0; + calculateEENormal(np11, np12, np21, np22, out_normal); + VECSUB(temp, np22, np21); + VecMulf(temp, *out_a2); + VECADD(temp2, temp, np21); + VECADD(temp2, temp2, np11); + return INPR(temp2, temp2); + } + + CLAMP(*out_a2, 0.0, 1.0); + if (*out_a2 > .5) + { // == 1.0 + *out_a1 = projectPointOntoLine(np22, np11, np12); + if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON)) + { + calculateEENormal(np11, np12, np21, np22, out_normal); + + // return (np22 - (np11 + (np12 - np11) * out_a1)).lengthSquared(); + VECSUB(temp, np12, np11); + VecMulf(temp, *out_a1); + VECADD(temp2, temp, np11); + VECSUB(temp2, np22, temp2); + return INPR(temp2, temp2); + } + } + else + { // == 0.0 + *out_a1 = projectPointOntoLine(np21, np11, np12); + if ((*out_a1 >= -FLT_EPSILON) && (*out_a1 <= 1.0 + FLT_EPSILON)) + { + calculateEENormal(np11, np11, np21, np22, out_normal); + + // return (np21 - (np11 + (np12 - np11) * out_a1)).lengthSquared(); + VECSUB(temp, np12, np11); + VecMulf(temp, *out_a1); + VECADD(temp2, temp, np11); + VECSUB(temp2, np21, temp2); + return INPR(temp2, temp2); + } + } + + CLAMP(*out_a1, 0.0, 1.0); + calculateEENormal(np11, np12, np21, np22, out_normal); + if(*out_a1 > .5) + { + if(*out_a2 > .5) + { + VECSUB(temp, np12, np22); + } + else + { + VECSUB(temp, np12, np21); + } + } + else + { + if(*out_a2 > .5) + { + VECSUB(temp, np11, np22); + } + else + { + VECSUB(temp, np11, np21); + } + } + + return INPR(temp, temp); + } + else + { + + // If the lines aren't parallel (but coplanar) they have to intersect + + findClosestPointsEE(np11, np12, np21, np22, out_a1, out_a2); + + // If both points are on the finite edges, we're done. + if (*out_a1 >= 0.0 && *out_a1 <= 1.0 && *out_a2 >= 0.0 && *out_a2 <= 1.0) + { + float p1[3], p2[3]; + + // p1= np11 + (np12 - np11) * out_a1; + VECSUB(temp, np12, np11); + VecMulf(temp, *out_a1); + VECADD(p1, np11, temp); + + // p2 = np21 + (np22 - np21) * out_a2; + VECSUB(temp, np22, np21); + VecMulf(temp, *out_a2); + VECADD(p2, np21, temp); + + calculateEENormal(np11, np12, np21, np22, out_normal); + VECSUB(temp, p1, p2); + return INPR(temp, temp); + } + + + /* + * Clamp both points to the finite edges. + * The one that moves most during clamping is one part of the solution. + */ + dist_a1 = *out_a1; + CLAMP(dist_a1, 0.0, 1.0); + dist_a2 = *out_a2; + CLAMP(dist_a2, 0.0, 1.0); + + // Now project the "most clamped" point on the other line. + if (dist_a1 > dist_a2) + { + /* keep out_a1 */ + float p1[3]; + + // p1 = np11 + (np12 - np11) * out_a1; + VECSUB(temp, np12, np11); + VecMulf(temp, *out_a1); + VECADD(p1, np11, temp); + + *out_a2 = projectPointOntoLine(p1, np21, np22); + CLAMP(*out_a2, 0.0, 1.0); + + calculateEENormal(np11, np12, np21, np22, out_normal); + + // return (p1 - (np21 + (np22 - np21) * out_a2)).lengthSquared(); + VECSUB(temp, np22, np21); + VecMulf(temp, *out_a2); + VECADD(temp, temp, np21); + VECSUB(temp, p1, temp); + return INPR(temp, temp); + } + else + { + /* keep out_a2 */ + float p2[3]; + + // p2 = np21 + (np22 - np21) * out_a2; + VECSUB(temp, np22, np21); + VecMulf(temp, *out_a2); + VECADD(p2, np21, temp); + + *out_a1 = projectPointOntoLine(p2, np11, np12); + CLAMP(*out_a1, 0.0, 1.0); + + calculateEENormal(np11, np12, np21, np22, out_normal); + + // return ((np11 + (np12 - np11) * out_a1) - p2).lengthSquared(); + VECSUB(temp, np12, np11); + VecMulf(temp, *out_a1); + VECADD(temp, temp, np11); + VECSUB(temp, temp, p2); + return INPR(temp, temp); + } + } + + printf("Error in edgedge_distance: end of function\n"); + return 0; +} + int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) { EdgeCollPair edgecollpair; @@ -890,16 +1111,16 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat cloth1 = clmd->clothObject; verts1 = cloth1->verts; - + for(i = 0; i < 9; i++) { // 9 edge - edge possibilities - + if(i == 0) // cloth edge: 1-2; coll edge: 1-2 { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap2; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp2; } @@ -907,7 +1128,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap2; - + edgecollpair.p21 = collpair->bp2; edgecollpair.p22 = collpair->bp3; } @@ -915,7 +1136,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap2; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp3; } @@ -923,7 +1144,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap2; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp2; } @@ -931,7 +1152,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap2; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp2; edgecollpair.p22 = collpair->bp3; } @@ -939,7 +1160,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap2; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp3; } @@ -947,7 +1168,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp2; } @@ -955,7 +1176,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp2; edgecollpair.p22 = collpair->bp3; } @@ -963,171 +1184,144 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { edgecollpair.p11 = collpair->ap1; edgecollpair.p12 = collpair->ap3; - + edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp3; } - + if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) ) { // always put coll points in p21/p22 VECSUB ( x1, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold ); VECSUB ( v1, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv ); - + VECSUB ( x2, verts2[edgecollpair.p21].co, verts1[edgecollpair.p11].txold ); VECSUB ( v2, velocity2[edgecollpair.p21].co, verts1[edgecollpair.p11].tv ); - + VECSUB ( x3, verts2[edgecollpair.p22].co, verts1[edgecollpair.p11].txold ); VECSUB ( v3, velocity2[edgecollpair.p22].co, verts1[edgecollpair.p11].tv ); - + numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution ); - + for ( k = 0; k < numsolutions; k++ ) { // printf("sol %d: %lf\n", k, solution[k]); if ( ( solution[k] >= DBL_EPSILON ) && ( solution[k] <= 1.0 ) ) { - //float out_collisionTime = solution[k]; - + float a,b; + float out_normal[3]; + float distance; + + // move verts + VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, mintime); + VECADDS(triA[1], verts1[edgecollpair.p12].txold, verts1[edgecollpair.p12].tv, mintime); + + VECADDS(triB[0], collmd->current_x[edgecollpair.p21].co, collmd->current_v[edgecollpair.p21].co, mintime); + VECADDS(triB[1], collmd->current_x[edgecollpair.p22].co, collmd->current_v[edgecollpair.p22].co, mintime); + // TODO: check for collisions - - // TODO: put into (edge) collision list + distance = edgedge_distance(triA[0], triA[1], triB[0], triB[1], &a, &b, out_normal); + if ((distance <= clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO) && (INPR(out_normal, out_normal) > 0)) + { + // printf("found edge, dist: %f\n", distance); + + /* Inelastic repulsion impulse. */ +/* + // Calculate which normal velocity we need. + float desiredVn = (normalVelocity * (float)solution[k] - (.1 * (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree )) - sqrt(squaredDistance)) - ALMOST_ZERO); + + // Now calculate what impulse we need to reach that velocity. + float m1 = interpolateOnEdge(cloth1.getVertexWeight(v11idx), cloth1.getVertexWeight(v12idx), a1); + float m2 = interpolateOnEdge(cloth2.getVertexWeight(v21idx), cloth2.getVertexWeight(v22idx), a2); + float I_mag = (normalVelocity - desiredVn) / (1/m1 + 1/m2); + + // Finally apply that impulse. + applyInterpolatedImpulsesEdge(out_impulses1[v11idx], out_impulses1[v12idx], out_impulses2[v21idx], out_impulses2[v22idx], + a1, a2, -I_mag, normal); + ++out_impulseCounter1[v11idx]; ++out_impulseCounter1[v12idx]; + ++out_impulseCounter2[v21idx]; ++out_impulseCounter2[v22idx]; + + */ // return true; + result = 1; + } + mintime = MIN2(mintime, (float)solution[k]); - - result = 1; + break; } } } } - +/* if(result) { // move triangles to collision point in time VECADDS(triA[0], verts1[collpair->ap1].txold, verts1[collpair->ap1].tv, mintime); VECADDS(triA[1], verts1[collpair->ap2].txold, verts1[collpair->ap2].tv, mintime); VECADDS(triA[2], verts1[collpair->ap3].txold, verts1[collpair->ap3].tv, mintime); - + VECADDS(triB[0], collmd->current_x[collpair->bp1].co, collmd->current_v[collpair->bp1].co, mintime); VECADDS(triB[1], collmd->current_x[collpair->bp2].co, collmd->current_v[collpair->bp2].co, mintime); VECADDS(triB[2], collmd->current_x[collpair->bp3].co, collmd->current_v[collpair->bp3].co, mintime); - + // check distance there distance = plNearestPoints (triA[0], triA[1], triA[2], triB[0], triB[1], triB[2], collpair->pa,collpair->pb,collpair->vector ); - + if(distance <= (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO)) { CollPair *next = collpair; next++; - + collpair->distance = clmd->coll_parms->epsilon; collpair->time = mintime; - + VECCOPY ( collpair->normal, collpair->vector ); Normalize ( collpair->normal ); - - cloth_collision_response_moving ( clmd, collmd, collpair, next ); + + // cloth_collision_response_moving ( clmd, collmd, collpair, next ); + } } - +*/ return result; } -/* -void cloth_collision_moving_tris ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2 ) +int cloth_collision_moving_tris ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair ) { - CollPair collpair; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; + EdgeCollPair edgecollpair; + Cloth *cloth1=NULL; + ClothVertex *verts1=NULL; unsigned int i = 0, j = 0, k = 0; int numsolutions = 0; - float a[3], b[3], c[3], d[3], e[3], f[3]; + double x1[3], v1[3], x2[3], v2[3], x3[3], v3[3]; double solution[3]; + MVert *verts2 = collmd->current_x; // old x + MVert *velocity2 = collmd->current_v; // velocity + float mintime = FLT_MAX; + float distance; + float triA[3][3], triB[3][3]; + int result = 0; - for ( i = 0; i < 2; i++ ) + cloth1 = clmd->clothObject; + verts1 = cloth1->verts; + + for(i = 0; i < 9; i++) { - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; + // 9 edge - edge possibilities - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - face1 = & ( cloth1->mfaces[tree1->tri_index] ); - face2 = & ( cloth2->mfaces[tree2->tri_index] ); - - // check all possible pairs of triangles - if ( i == 0 ) + if(i == 0) { - collpair.ap1 = face1->v1; - collpair.ap2 = face1->v2; - collpair.ap3 = face1->v3; - - collpair.pointsb[0] = face2->v1; - collpair.pointsb[1] = face2->v2; - collpair.pointsb[2] = face2->v3; - collpair.pointsb[3] = face2->v4; - } - - if ( i == 1 ) - { - if ( face1->v4 ) - { - collpair.ap1 = face1->v3; - collpair.ap2 = face1->v4; - collpair.ap3 = face1->v1; - - collpair.pointsb[0] = face2->v1; - collpair.pointsb[1] = face2->v2; - collpair.pointsb[2] = face2->v3; - collpair.pointsb[3] = face2->v4; - } - else - i++; - } - - // calc SIPcode (?) - - if ( i < 2 ) - { - VECSUB ( a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold ); - VECSUB ( b, verts1[collpair.ap2].v, verts1[collpair.ap1].v ); - VECSUB ( c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold ); - VECSUB ( d, verts1[collpair.ap3].v, verts1[collpair.ap1].v ); - - for ( j = 0; j < 4; j++ ) - { - if ( ( j==3 ) && ! ( face2->v4 ) ) - break; - - VECSUB ( e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold ); - VECSUB ( f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v ); - - numsolutions = cloth_get_collision_time ( a, b, c, d, e, f, solution ); - - for ( k = 0; k < numsolutions; k++ ) - { - if ( ( solution[k] >= ALMOST_ZERO ) && ( solution[k] <= 1.0 ) ) - { - //float out_collisionTime = solution[k]; - - // TODO: check for collisions - - // TODO: put into (point-face) collision list - - // printf("Moving found!\n"); - - } - } - - // TODO: check borders for collisions - } + edgecollpair.p11 = collpair->ap1; + edgecollpair.p12 = collpair->ap2; + edgecollpair.p21 = collpair->bp1; + edgecollpair.p22 = collpair->bp2; } } + + return result; } -*/ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { @@ -1145,10 +1339,11 @@ int cloth_collision_moving ( ClothModifierData *clmd, CollisionModifierData *col // only handle moving collisions here if (!( collpair->flag & COLLISION_IN_FUTURE )) continue; - + cloth_collision_moving_edges ( clmd, collmd, collpair); + // cloth_collision_moving_tris ( clmd, collmd, collpair); } - + return 1; } @@ -1219,14 +1414,14 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count ); VECCOPY ( verts[i].impulse, tnull ); verts[i].impulse_count = 0; - + ret++; } } } - /* +/* result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); - + // apply impulses in parallel if ( result ) { @@ -1238,12 +1433,12 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count ); VECCOPY ( verts[i].impulse, tnull ); verts[i].impulse_count = 0; - + ret++; } } } - */ +*/ } } @@ -1371,24 +1566,25 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) if ( cloth->bvhselftree ) { - /* search for overlapping collision pairs */ + // search for overlapping collision pairs overlap = BLI_bvhtree_overlap ( cloth->bvhselftree, cloth->bvhselftree, &result ); +// #pragma omp parallel for private(k, i, j) schedule(static) for ( k = 0; k < result; k++ ) { float temp[3]; float length = 0; float mindistance; - + i = overlap[k].indexA; j = overlap[k].indexB; - + mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) { if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) + && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) { continue; } @@ -1427,87 +1623,18 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) VECSUB ( verts[i].tx, verts[i].tx, temp ); } + ret = 1; + } + else + { + // check for approximated time collisions } } - + if ( overlap ) MEM_freeN ( overlap ); - - } - /* - for ( count = 0; count < clmd->coll_parms->self_loop_count; count++ ) - { - if ( collisions ) - { - collisions = 0; - #pragma omp parallel for private(i,j, collisions) shared(verts, ret) - for ( i = 0; i < cloth->numverts; i++ ) - { - for ( j = i + 1; j < cloth->numverts; j++ ) - { - float temp[3]; - float length = 0; - float mindistance = clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len + cloth->verts[j].avg_spring_len ); - - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - { - if ( ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - && ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) ) - { - continue; } - } - - VECSUB ( temp, verts[i].tx, verts[j].tx ); - - if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; - - // check for adjacent points (i must be smaller j) - if ( BLI_edgehash_haskey ( cloth->edgehash, i, j ) ) - { - continue; - } - - length = Normalize ( temp ); - - if ( length < mindistance ) - { - float correction = mindistance - length; - - if ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, -correction ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - } - else if ( cloth->verts [j].flags & CLOTH_VERT_FLAG_PINNED ) - { - VecMulf ( temp, correction ); - VECADD ( verts[i].tx, verts[i].tx, temp ); - } - else - { - VecMulf ( temp, -correction*0.5 ); - VECADD ( verts[j].tx, verts[j].tx, temp ); - - VECSUB ( verts[i].tx, verts[i].tx, temp ); - } - - collisions = 1; - - if ( !ret ) - { - #pragma omp critical - { - ret = 1; - } - } - } - } - } - } - } - */ //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// @@ -1517,8 +1644,10 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) { for ( i = 0; i < cloth->numverts; i++ ) { - if ( ! ( cloth->verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) + if ( ! ( verts [i].flags & CLOTH_VERT_FLAG_PINNED ) ) + { VECSUB ( verts[i].tv, verts[i].tx, verts[i].txold ); + } } } //////////////////////////////////////////////////////////// @@ -1528,3 +1657,15 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) return MIN2 ( ret, 1 ); } + + +/* +if ( verts[i].impulse_count ) +{ + VECADDMUL ( verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count ); + VECCOPY ( verts[i].impulse, tnull ); + verts[i].impulse_count = 0; + + ret++; +} +*/ \ No newline at end of file From 391c7615d19561555ab29c090fcfd56447942548 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 26 May 2008 10:36:14 +0000 Subject: [PATCH 097/101] -= Collisions =- 1. fix for collisions (were working better with selfcolls enabled, now generally better) --- source/blender/blenkernel/intern/collision.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index edf8fec9ae1..0b291aaa695 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1458,7 +1458,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) long i=0, j = 0, k = 0, numfaces = 0, numverts = 0; unsigned int result = 0, rounds = 0; // result counts applied collisions; ic is for debug output; ClothVertex *verts = NULL; - int ret = 0; + int ret = 0, ret2 = 0; ClothModifierData *tclmd; int collisions = 0, count = 0; @@ -1484,6 +1484,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) do { result = 0; + ret2 = 0; // check all collision objects for ( base = G.scene->base.first; base; base = base->next ) @@ -1512,6 +1513,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) continue; ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt ); + ret2 += ret; } } } @@ -1522,6 +1524,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) continue; ret += cloth_bvh_objcollisions_do ( clmd, collmd, step, dt ); + ret2 += ret; } } rounds++; @@ -1624,6 +1627,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) VECSUB ( verts[i].tx, verts[i].tx, temp ); } ret = 1; + ret2 += ret; } else { @@ -1640,7 +1644,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// // SELFCOLLISIONS: update velocities //////////////////////////////////////////////////////////// - if ( ret ) + if ( ret2 ) { for ( i = 0; i < cloth->numverts; i++ ) { @@ -1653,7 +1657,7 @@ int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ) //////////////////////////////////////////////////////////// } } - while ( result && ( clmd->coll_parms->loop_count>rounds ) ); + while ( ret2 && ( clmd->coll_parms->loop_count>rounds ) ); return MIN2 ( ret, 1 ); } From da36e8abca19b667d1c300a154e6e6798af119e9 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 27 May 2008 22:42:38 +0000 Subject: [PATCH 098/101] -= KDOP / Collisions =- 1. Fix for face with index=0 not handled --- source/blender/blenlib/intern/BLI_kdopbvh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index cf326f3f460..c884b97b182 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -653,10 +653,10 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2) if(tree_overlap(node1->bv, node2->bv, MIN2(data->tree1->start_axis, data->tree2->start_axis), MIN2(data->tree1->stop_axis, data->tree2->stop_axis))) { // check if node1 is a leaf - if(node1->index) + if(!node1->totnode) { // check if node2 is a leaf - if(node2->index) + if(!node2->totnode) { if(node1 == node2) From ed42c9a6768712c1eeba3b36af09620f668d663b Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 27 May 2008 22:46:57 +0000 Subject: [PATCH 099/101] -= Collisions -= 1. Test for fast moving edges --- source/blender/blenkernel/intern/collision.c | 102 ++++++++++--------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 0b291aaa695..37784b43cf9 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -498,6 +498,7 @@ DO_INLINE void collision_interpolateOnTriangle ( float to[3], float v1[3], float VECADDMUL ( to, v3, w3 ); } + int cloth_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { int result = 0; @@ -1189,8 +1190,16 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat edgecollpair.p22 = collpair->bp3; } + if((edgecollpair.p11 == 3) && (edgecollpair.p12 == 6)) + printf("Ahier!\n"); + if((edgecollpair.p11 == 6) && (edgecollpair.p12 == 3)) + printf("Ahier!\n"); + if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) ) { + // printf("Collision between:\n"); + // printf("p11: %d, p12: %d, p21: %d, p22: %d\n", edgecollpair.p11, edgecollpair.p12, edgecollpair.p21, edgecollpair.p22); + // always put coll points in p21/p22 VECSUB ( x1, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold ); VECSUB ( v1, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv ); @@ -1206,11 +1215,14 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat for ( k = 0; k < numsolutions; k++ ) { // printf("sol %d: %lf\n", k, solution[k]); - if ( ( solution[k] >= DBL_EPSILON ) && ( solution[k] <= 1.0 ) ) + if ( ( solution[k] >= ALMOST_ZERO ) && ( solution[k] <= 1.0 ) && ( solution[k] > ALMOST_ZERO)) { float a,b; float out_normal[3]; float distance; + float impulse = 0; + float I_mag; + float m1, m2; // move verts VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, mintime); @@ -1224,28 +1236,57 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat if ((distance <= clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO) && (INPR(out_normal, out_normal) > 0)) { - // printf("found edge, dist: %f\n", distance); + float vrel_1_to_2[3], temp[3], temp2[3], out_normalVelocity; + float desiredVn; + + VECCOPY(vrel_1_to_2, verts1[edgecollpair.p11].tv); + VecMulf(vrel_1_to_2, 1.0 - a); + VECCOPY(temp, verts1[edgecollpair.p12].tv); + VecMulf(temp, a); + + VECADD(vrel_1_to_2, vrel_1_to_2, temp); + + VECCOPY(temp, verts1[edgecollpair.p21].tv); + VecMulf(temp, 1.0 - b); + VECCOPY(temp2, verts1[edgecollpair.p22].tv); + VecMulf(temp2, b); + VECADD(temp, temp, temp2); + + VECSUB(vrel_1_to_2, vrel_1_to_2, temp); + + out_normalVelocity = INPR(vrel_1_to_2, out_normal); + + if(out_normalVelocity < 0.0) + { + out_normalVelocity*= -1.0; + VecMulf(out_normal, -1.0); + } /* Inelastic repulsion impulse. */ -/* + // Calculate which normal velocity we need. - float desiredVn = (normalVelocity * (float)solution[k] - (.1 * (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree )) - sqrt(squaredDistance)) - ALMOST_ZERO); + desiredVn = (out_normalVelocity * (float)solution[k] - (.1 * (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree )) - sqrt(distance)) - ALMOST_ZERO); // Now calculate what impulse we need to reach that velocity. - float m1 = interpolateOnEdge(cloth1.getVertexWeight(v11idx), cloth1.getVertexWeight(v12idx), a1); - float m2 = interpolateOnEdge(cloth2.getVertexWeight(v21idx), cloth2.getVertexWeight(v22idx), a2); - float I_mag = (normalVelocity - desiredVn) / (1/m1 + 1/m2); + I_mag = (out_normalVelocity - desiredVn) / 2.0; // / (1/m1 + 1/m2); // Finally apply that impulse. - applyInterpolatedImpulsesEdge(out_impulses1[v11idx], out_impulses1[v12idx], out_impulses2[v21idx], out_impulses2[v22idx], - a1, a2, -I_mag, normal); - ++out_impulseCounter1[v11idx]; ++out_impulseCounter1[v12idx]; - ++out_impulseCounter2[v21idx]; ++out_impulseCounter2[v22idx]; + impulse = (2.0 * -I_mag) / (a*a + (1.0-a)*(1.0-a) + b*b + (1.0-b)*(1.0-b)); - */ // return true; + VECADDMUL ( verts1[edgecollpair.p11].impulse, out_normal, (1.0-a) * impulse ); + verts1[edgecollpair.p11].impulse_count++; + + VECADDMUL ( verts1[edgecollpair.p12].impulse, out_normal, a * impulse ); + verts1[edgecollpair.p12].impulse_count++; + + // return true; result = 1; + break; + } + else + { + // missing from collision.hpp } - mintime = MIN2(mintime, (float)solution[k]); break; @@ -1253,37 +1294,6 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat } } } -/* - if(result) - { - // move triangles to collision point in time - VECADDS(triA[0], verts1[collpair->ap1].txold, verts1[collpair->ap1].tv, mintime); - VECADDS(triA[1], verts1[collpair->ap2].txold, verts1[collpair->ap2].tv, mintime); - VECADDS(triA[2], verts1[collpair->ap3].txold, verts1[collpair->ap3].tv, mintime); - - VECADDS(triB[0], collmd->current_x[collpair->bp1].co, collmd->current_v[collpair->bp1].co, mintime); - VECADDS(triB[1], collmd->current_x[collpair->bp2].co, collmd->current_v[collpair->bp2].co, mintime); - VECADDS(triB[2], collmd->current_x[collpair->bp3].co, collmd->current_v[collpair->bp3].co, mintime); - - // check distance there - distance = plNearestPoints (triA[0], triA[1], triA[2], triB[0], triB[1], triB[2], collpair->pa,collpair->pb,collpair->vector ); - - if(distance <= (clmd->coll_parms->epsilon + BLI_bvhtree_getepsilon ( collmd->bvhtree ) + ALMOST_ZERO)) - { - CollPair *next = collpair; - next++; - - collpair->distance = clmd->coll_parms->epsilon; - collpair->time = mintime; - - VECCOPY ( collpair->normal, collpair->vector ); - Normalize ( collpair->normal ); - - // cloth_collision_response_moving ( clmd, collmd, collpair, next ); - - } - } -*/ return result; } @@ -1419,7 +1429,7 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData } } } -/* + result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); // apply impulses in parallel @@ -1438,7 +1448,7 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData } } } -*/ + } } From f1d54f892b7480b746b6423d4388455fe7ede2b9 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 29 May 2008 14:23:08 +0000 Subject: [PATCH 100/101] -= Collisions =- Getting some weird results on moving fast edges. This is a backup commit, will try another thing --- source/blender/blenkernel/intern/collision.c | 127 ++++++++++--------- 1 file changed, 66 insertions(+), 61 deletions(-) diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 37784b43cf9..36cc37eab44 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -388,8 +388,8 @@ int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3 printf("v3 x: %f, y: %f, z: %f\n", f[0], f[1], f[2]); printf("t^3: %lf, t^2: %lf, t^1: %lf, t^0: %lf\n", j, i, h, g); - */ - + +*/ // Solve cubic equation to determine times t1, t2, t3, when the collision will occur. if ( ABS ( j ) > DBL_EPSILON ) { @@ -453,6 +453,7 @@ int cloth_get_collision_time ( double a[3], double b[3], double c[3], double d[3 return num_sols; } + // w3 is not perfect void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3 ) { @@ -713,52 +714,43 @@ CollPair* cloth_collision ( ModifierData *md1, ModifierData *md2, BVHTreeOverlap } else { - // check for collision in the future - collpair->flag |= COLLISION_IN_FUTURE; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; + + // calc relative velocity + + // compute barycentric coordinates for both collision points + collision_compute_barycentric ( collpair->pa, + verts1[collpair->ap1].txold, + verts1[collpair->ap2].txold, + verts1[collpair->ap3].txold, + &w1, &w2, &w3 ); + + // was: txold + collision_compute_barycentric ( collpair->pb, + collmd->current_x[collpair->bp1].co, + collmd->current_x[collpair->bp2].co, + collmd->current_x[collpair->bp3].co, + &u1, &u2, &u3 ); + + // Calculate relative "velocity". + collision_interpolateOnTriangle ( v1, verts1[collpair->ap1].tv, verts1[collpair->ap2].tv, verts1[collpair->ap3].tv, w1, w2, w3 ); + + collision_interpolateOnTriangle ( v2, collmd->current_v[collpair->bp1].co, collmd->current_v[collpair->bp2].co, collmd->current_v[collpair->bp3].co, u1, u2, u3 ); + + VECSUB ( relativeVelocity, v2, v1 ); + + if(sqrt(INPR(relativeVelocity, relativeVelocity)) >= distance) + { + // check for collision in the future + collpair->flag |= COLLISION_IN_FUTURE; + } } collpair++; } return collpair; } -int cloth_are_edges_adjacent ( ClothModifierData *clmd, CollisionModifierData *collmd, EdgeCollPair *edgecollpair ) -{ - Cloth *cloth1 = NULL; - ClothVertex *verts1 = NULL; - float temp[3]; - MVert *verts2 = collmd->current_x; // old x - - cloth1 = clmd->clothObject; - verts1 = cloth1->verts; - - VECSUB ( temp, verts1[edgecollpair->p11].txold, verts2[edgecollpair->p21].co ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; - - VECSUB ( temp, verts1[edgecollpair->p11].txold, verts2[edgecollpair->p22].co ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; - - VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p21].co ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; - - VECSUB ( temp, verts1[edgecollpair->p12].txold, verts2[edgecollpair->p22].co ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; - - VECSUB ( temp, verts1[edgecollpair->p11].txold, verts1[edgecollpair->p12].txold ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; - - VECSUB ( temp, verts2[edgecollpair->p21].co, verts2[edgecollpair->p22].co ); - if ( ABS ( INPR ( temp, temp ) ) < ALMOST_ZERO ) - return 1; - - - return 0; -} - int cloth_collision_response_moving( ClothModifierData *clmd, CollisionModifierData *collmd, CollPair *collpair, CollPair *collision_end ) { int result = 0; @@ -879,13 +871,18 @@ static float projectPointOntoLine(float *p, float *a, float *b) static void calculateEENormal(float *np1, float *np2, float *np3, float *np4,float *out_normal) { - float line1[33], line2[3]; + float line1[3], line2[3]; float length; VECSUB(line1, np2, np1); VECSUB(line2, np3, np1); + // printf("l1: %f, l1: %f, l2: %f, l2: %f\n", line1[0], line1[1], line2[0], line2[1]); + Crossf(out_normal, line1, line2); + + + length = Normalize(out_normal); if (length <= FLT_EPSILON) { // lines are collinear @@ -1102,10 +1099,9 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat unsigned int i = 0, j = 0, k = 0; int numsolutions = 0; double x1[3], v1[3], x2[3], v2[3], x3[3], v3[3]; - double solution[3]; + double solution[3], solution2[3]; MVert *verts2 = collmd->current_x; // old x MVert *velocity2 = collmd->current_v; // velocity - float mintime = FLT_MAX; float distance; float triA[3][3], triB[3][3]; int result = 0; @@ -1189,17 +1185,15 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat edgecollpair.p21 = collpair->bp1; edgecollpair.p22 = collpair->bp3; } - - if((edgecollpair.p11 == 3) && (edgecollpair.p12 == 6)) + /* + if((edgecollpair.p11 == 3) && (edgecollpair.p12 == 16)) printf("Ahier!\n"); - if((edgecollpair.p11 == 6) && (edgecollpair.p12 == 3)) + if((edgecollpair.p11 == 16) && (edgecollpair.p12 == 3)) printf("Ahier!\n"); + */ - if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) ) + // if ( !cloth_are_edges_adjacent ( clmd, collmd, &edgecollpair ) ) { - // printf("Collision between:\n"); - // printf("p11: %d, p12: %d, p21: %d, p22: %d\n", edgecollpair.p11, edgecollpair.p12, edgecollpair.p21, edgecollpair.p22); - // always put coll points in p21/p22 VECSUB ( x1, verts1[edgecollpair.p12].txold, verts1[edgecollpair.p11].txold ); VECSUB ( v1, verts1[edgecollpair.p12].tv, verts1[edgecollpair.p11].tv ); @@ -1212,6 +1206,16 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat numsolutions = cloth_get_collision_time ( x1, v1, x2, v2, x3, v3, solution ); + if((edgecollpair.p11 == 3 && edgecollpair.p12==16)|| (edgecollpair.p11==16 && edgecollpair.p12==3)) + { + if(edgecollpair.p21==6 || edgecollpair.p22 == 6) + { + printf("dist: %f, sol[k]: %lf, sol2[k]: %lf\n", distance, solution[k], solution2[k]); + printf("a1: %f, a2: %f, b1: %f, b2: %f\n", x1[0], x2[0], x3[0], v1[0]); + printf("b21: %d, b22: %d\n", edgecollpair.p21, edgecollpair.p22); + } + } + for ( k = 0; k < numsolutions; k++ ) { // printf("sol %d: %lf\n", k, solution[k]); @@ -1225,11 +1229,11 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat float m1, m2; // move verts - VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, mintime); - VECADDS(triA[1], verts1[edgecollpair.p12].txold, verts1[edgecollpair.p12].tv, mintime); + VECADDS(triA[0], verts1[edgecollpair.p11].txold, verts1[edgecollpair.p11].tv, solution[k]); + VECADDS(triA[1], verts1[edgecollpair.p12].txold, verts1[edgecollpair.p12].tv, solution[k]); - VECADDS(triB[0], collmd->current_x[edgecollpair.p21].co, collmd->current_v[edgecollpair.p21].co, mintime); - VECADDS(triB[1], collmd->current_x[edgecollpair.p22].co, collmd->current_v[edgecollpair.p22].co, mintime); + VECADDS(triB[0], collmd->current_x[edgecollpair.p21].co, collmd->current_v[edgecollpair.p21].co, solution[k]); + VECADDS(triB[1], collmd->current_x[edgecollpair.p22].co, collmd->current_v[edgecollpair.p22].co, solution[k]); // TODO: check for collisions distance = edgedge_distance(triA[0], triA[1], triB[0], triB[1], &a, &b, out_normal); @@ -1255,13 +1259,14 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat VECSUB(vrel_1_to_2, vrel_1_to_2, temp); out_normalVelocity = INPR(vrel_1_to_2, out_normal); - +/* + // this correction results in wrong normals sometimes? if(out_normalVelocity < 0.0) { out_normalVelocity*= -1.0; VecMulf(out_normal, -1.0); } - +*/ /* Inelastic repulsion impulse. */ // Calculate which normal velocity we need. @@ -1287,7 +1292,7 @@ int cloth_collision_moving_edges ( ClothModifierData *clmd, CollisionModifierDat { // missing from collision.hpp } - mintime = MIN2(mintime, (float)solution[k]); + // mintime = MIN2(mintime, (float)solution[k]); break; } @@ -1429,7 +1434,7 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData } } } - +/* result += cloth_collision_moving ( clmd, collmd, collisions, collisions_index ); // apply impulses in parallel @@ -1448,7 +1453,7 @@ int cloth_bvh_objcollisions_do ( ClothModifierData * clmd, CollisionModifierData } } } - +*/ } } From 74903b77f48c9c2ec9c226fc6ae34381d258e47e Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Sat, 31 May 2008 21:23:57 +0000 Subject: [PATCH 101/101] Merging revisions 15020-15073 of https://svn.blender.org/svnroot/bf-blender/trunk/blender --- config/win32-vc-config.py | 2 +- release/windows/installer/00.sconsblender.nsi | 6 +- source/blender/blenkernel/intern/object.c | 9 +- source/blender/blenlib/intern/util.c | 1 + source/blender/include/BIF_editseq.h | 4 +- source/blender/include/transform.h | 1 + source/blender/makesdna/intern/makesdna.c | 10 +- source/blender/python/api2_2x/Draw.c | 2 + source/blender/python/api2_2x/Node.c | 2 +- source/blender/python/api2_2x/Scene.c | 27 +++-- source/blender/python/api2_2x/sceneRender.c | 10 +- .../render/extern/include/RE_raytrace.h | 2 +- .../blender/render/intern/source/pipeline.c | 1 + .../blender/render/intern/source/rayshade.c | 22 ++-- source/blender/src/drawobject.c | 83 +++++++++++--- source/blender/src/drawseq.c | 2 +- source/blender/src/drawview.c | 22 ++-- source/blender/src/editarmature.c | 46 ++++++-- source/blender/src/editseq.c | 93 ++++++++++------ source/blender/src/filesel.c | 2 +- source/blender/src/fluidsim.c | 33 +++++- source/blender/src/meshtools.c | 6 + source/blender/src/transform_conversions.c | 2 +- source/blender/src/transform_manipulator.c | 49 ++------ source/blender/src/transform_orientations.c | 105 +++++++++++++++++- source/blender/src/view.c | 2 + 26 files changed, 388 insertions(+), 156 deletions(-) diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py index 32b6597b5d5..02e5dbb7f8f 100644 --- a/config/win32-vc-config.py +++ b/config/win32-vc-config.py @@ -157,7 +157,7 @@ REL_CCFLAGS = ['-O2', '-DNDEBUG'] C_WARN = [] CC_WARN = [] -LLIBS = 'ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shell32 ole32 oleaut32 uuid' +LLIBS = 'ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid' PLATFORM_LINKFLAGS = ''' /SUBSYSTEM:CONSOLE diff --git a/release/windows/installer/00.sconsblender.nsi b/release/windows/installer/00.sconsblender.nsi index c4e504a5bff..338075c1b18 100644 --- a/release/windows/installer/00.sconsblender.nsi +++ b/release/windows/installer/00.sconsblender.nsi @@ -32,7 +32,7 @@ Name "Blender VERSION" !insertmacro MUI_PAGE_DIRECTORY Page custom DataLocation DataLocationOnLeave -Page custom AppDataChoice AppDataChoiceOnLeave +;Page custom AppDataChoice AppDataChoiceOnLeave Page custom PreMigrateUserSettings MigrateUserSettings !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH @@ -271,7 +271,9 @@ Function DataLocationOnLeave StrCpy $SETUSERCONTEXT "false" ${NSD_GetState} $HWND_APPDATA $R0 ${If} $R0 == "1" - StrCpy $SETUSERCONTEXT "true" + ; FIXME: disabled 'all users' until fully multi-user compatible + ;StrCpy $SETUSERCONTEXT "true" + Call SetWinXPPathCurrentUser ${Else} ${NSD_GetState} $HWND_INSTDIR $R0 ${If} $R0 == "1" diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index ab1bc5a2265..4f901ba7216 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1614,7 +1614,7 @@ static void give_parvert(Object *par, int nr, float *vec) for(eve= em->verts.first; eve; eve= eve->next) { if(eve->keyindex==nr) { - memcpy(vec, eve->co, 12); + memcpy(vec, eve->co, sizeof(float)*3); break; } } @@ -1652,18 +1652,20 @@ static void give_parvert(Object *par, int nr, float *vec) Curve *cu; BPoint *bp; BezTriple *bezt; + int found= 0; cu= par->data; nu= cu->nurb.first; if(par==G.obedit) nu= editNurb.first; count= 0; - while(nu) { + while(nu && !found) { if((nu->type & 7)==CU_BEZIER) { bezt= nu->bezt; a= nu->pntsu; while(a--) { if(count==nr) { + found= 1; VECCOPY(vec, bezt->vec[1]); break; } @@ -1676,7 +1678,8 @@ static void give_parvert(Object *par, int nr, float *vec) a= nu->pntsu*nu->pntsv; while(a--) { if(count==nr) { - memcpy(vec, bp->vec, 12); + found= 1; + memcpy(vec, bp->vec, sizeof(float)*3); break; } count++; diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index c85849b5ed4..3610813f2da 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1166,6 +1166,7 @@ int BLI_convertstringcode(char *path, const char *basepath) MEM_freeN(filepart); } + BLI_cleanup_file(NULL, tmp); strcpy(path, tmp); #ifdef WIN32 diff --git a/source/blender/include/BIF_editseq.h b/source/blender/include/BIF_editseq.h index 0d1e792eb1c..b353e7bb45c 100644 --- a/source/blender/include/BIF_editseq.h +++ b/source/blender/include/BIF_editseq.h @@ -92,8 +92,8 @@ start and end are from the start and fixed length of the sequence. int seq_tx_get_start(struct Sequence *seq); int seq_tx_get_end(struct Sequence *seq); -int seq_tx_get_final_left(struct Sequence *seq); -int seq_tx_get_final_right(struct Sequence *seq); +int seq_tx_get_final_left(struct Sequence *seq, int metaclip); +int seq_tx_get_final_right(struct Sequence *seq, int metaclip); void seq_tx_set_final_left(struct Sequence *seq, int i); void seq_tx_set_final_right(struct Sequence *seq, int i); diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 982a2f25df7..82adb1ac12a 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -515,6 +515,7 @@ int handleNDofInput(NDofInput *n, unsigned short event, short val); int manageObjectSpace(int confirm, int set); int manageMeshSpace(int confirm, int set); +int manageBoneSpace(int confirm, int set); /* Those two fill in mat and return non-zero on success */ int createSpaceNormal(float mat[3][3], float normal[3]); diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 9b837f9f988..83f4e633fa1 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -688,18 +688,18 @@ static int calculate_structlens(int firststruct) /* 4-8 aligned/ */ if(sizeof(void *) == 4) { if (len % 4) { - printf("Align pointer error in struct: %s %s\n", types[structtype], cp); + printf("Align pointer error in struct (len4): %s %s\n", types[structtype], cp); dna_error = 1; } } else { if (len % 8) { - printf("Align pointer error in struct: %s %s\n", types[structtype], cp); + printf("Align pointer error in struct (len8): %s %s\n", types[structtype], cp); dna_error = 1; } } if (alphalen % 8) { - printf("Align pointer error in struct: %s %s\n", types[structtype],cp); + printf("Align pointer error in struct (alphalen8): %s %s\n", types[structtype],cp); dna_error = 1; } @@ -748,13 +748,13 @@ static int calculate_structlens(int firststruct) // has_pointer is set or alphalen != len if (has_pointer || alphalen != len) { if (alphalen % 8) { - printf("Sizeerror in struct: %s (add %d bytes)\n", types[structtype], alphalen%8); + printf("Sizeerror 8 in struct: %s (add %d bytes)\n", types[structtype], alphalen%8); dna_error = 1; } } if(len % 4) { - printf("Sizeerror in struct: %s (add %d bytes)\n", types[structtype], len%4); + printf("Sizeerror 4 in struct: %s (add %d bytes)\n", types[structtype], len%4); dna_error = 1; } diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c index 3d4546613be..047a035fb8b 100644 --- a/source/blender/python/api2_2x/Draw.c +++ b/source/blender/python/api2_2x/Draw.c @@ -613,6 +613,8 @@ static void exit_pydraw( SpaceScript * sc, short err ) PyErr_Print( ); script->flags = 0; /* mark script struct for deletion */ SCRIPT_SET_NULL(script); + script->scriptname[0] = '\0'; + script->scriptarg[0] = '\0'; error_pyscript(); scrarea_queue_redraw( sc->area ); } diff --git a/source/blender/python/api2_2x/Node.c b/source/blender/python/api2_2x/Node.c index 92529023b7e..792b2331508 100644 --- a/source/blender/python/api2_2x/Node.c +++ b/source/blender/python/api2_2x/Node.c @@ -848,7 +848,7 @@ static int Sockoutmap_assign_subscript(BPy_SockMap *self, PyObject *pyidx, PyObj if (PyInt_Check(pyidx)) { idx = (int)PyInt_AsLong(pyidx); - if (idx < 0 || idx >= Sockinmap_len(self)) + if (idx < 0 || idx >= Sockoutmap_len(self)) return EXPP_ReturnIntError(PyExc_IndexError, "index out of range"); } else if (PyString_Check(pyidx)) { diff --git a/source/blender/python/api2_2x/Scene.c b/source/blender/python/api2_2x/Scene.c index 7ef351b1127..eba951b8813 100644 --- a/source/blender/python/api2_2x/Scene.c +++ b/source/blender/python/api2_2x/Scene.c @@ -1355,16 +1355,29 @@ static PyObject *SceneObSeq_item( BPy_SceneObSeq * self, int i ) for (base= scene->base.first; base && i!=index; base= base->next, index++) {} /* selected */ else if (self->mode==EXPP_OBSEQ_SELECTED) { - for (base= scene->base.first; base && i!=index; base= base->next) - if (base->flag & SELECT) - index++; + for (base= scene->base.first; base; base= base->next) { + if (base->flag & SELECT) { + if (i==index) { + break; + } else { + index++; + } + } + } } /* context */ else if (self->mode==EXPP_OBSEQ_CONTEXT) { - if (G.vd) - for (base= scene->base.first; base && i!=index; base= base->next) - if TESTBASE(base) - index++; + if (G.vd) { + for (base= scene->base.first; base; base= base->next) { + if (TESTBASE(base)) { + if (i==index) { + break; + } else { + index++; + } + } + } + } } if (!(base)) diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index f54c2cd4e3b..bfad069f943 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -478,9 +478,11 @@ PyObject *RenderData_Render( BPy_RenderData * self ) } else { /* background mode (blender -b file.blend -P script) */ - Render *re= RE_NewRender("Render"); + Render *re= RE_NewRender(G.scene->id.name); - int end_frame = G.scene->r.efra; /* is of type short currently */ + + + int end_frame = G.scene->r.efra; if (G.scene != self->scene) return EXPP_ReturnPyObjError (PyExc_RuntimeError, @@ -490,7 +492,7 @@ PyObject *RenderData_Render( BPy_RenderData * self ) RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra); - G.scene->r.efra = (short)end_frame; + G.scene->r.efra = end_frame; } Py_RETURN_NONE; @@ -571,7 +573,7 @@ PyObject *RenderData_RenderAnim( BPy_RenderData * self ) set_scene( oldsce ); } else { /* background mode (blender -b file.blend -P script) */ - Render *re= RE_NewRender("Render"); + Render *re= RE_NewRender(G.scene->id.name); if (G.scene != self->scene) return EXPP_ReturnPyObjError (PyExc_RuntimeError, diff --git a/source/blender/render/extern/include/RE_raytrace.h b/source/blender/render/extern/include/RE_raytrace.h index aec1c69b3dc..8f429f7dd90 100644 --- a/source/blender/render/extern/include/RE_raytrace.h +++ b/source/blender/render/extern/include/RE_raytrace.h @@ -70,7 +70,7 @@ typedef struct Isect { int ob_last; short isect; /* which half of quad */ - short mode; /* RE_RAYSHADOW, RE_RAYMIRROR, RE_RAYSHADOW_TRA */ + short mode; /* RE_RAY_SHADOW, RE_RAY_MIRROR, RE_RAY_SHADOW_TRA */ int lay; /* -1 default, set for layer lamps */ /* only used externally */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index fb699f5b382..ebb52c49132 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -993,6 +993,7 @@ RenderStats *RE_GetStats(Render *re) return &re->i; } +/* Note, when rendering from a scene, ALWAYS use G.scene->id.name, else compositing wont work */ Render *RE_NewRender(const char *name) { Render *re; diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 8fd07001bd1..1155d2ea817 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -1473,14 +1473,15 @@ static float *sphere_sampler(int type, int resol, int thread, int xs, int ys) int tot; float *vec; - if(resol>16) resol= 16; - tot= 2*resol*resol; if (type & WO_AORNDSMP) { - static float sphere[2*3*256]; + float *sphere; int a; + // always returns table + sphere= threadsafe_table_sphere(0, thread, xs, ys, tot); + /* total random sampling. NOT THREADSAFE! (should be removed, is not useful) */ vec= sphere; for (a=0; avlr; isec.oborig= RAY_OBJECT_SET(&R, shi->obi); @@ -1690,14 +1692,16 @@ void ray_ao_spheresamp(ShadeInput *shi, float *shadfac) if(shi->mat->mode & MA_ONLYSHADOW) aocolor= WO_AOPLAIN; - vec= sphere_sampler(R.wrld.aomode, R.wrld.aosamp, shi->thread, shi->xs, shi->ys); + if(resol>32) resol= 32; + + vec= sphere_sampler(R.wrld.aomode, resol, shi->thread, shi->xs, shi->ys); // warning: since we use full sphere now, and dotproduct is below, we do twice as much - tot= 2*R.wrld.aosamp*R.wrld.aosamp; + tot= 2*resol*resol; if(aocolor == WO_AOSKYTEX) { - dxyview[0]= 1.0f/(float)R.wrld.aosamp; - dxyview[1]= 1.0f/(float)R.wrld.aosamp; + dxyview[0]= 1.0f/(float)resol; + dxyview[1]= 1.0f/(float)resol; dxyview[2]= 0.0f; } diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 0b042fc542f..0bb9e5f9e55 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -2922,7 +2922,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3]; int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0; int path_possible=0, keys_possible=0, draw_keys=0, totchild=0; - int select=ob->flag&SELECT; + int select=ob->flag&SELECT, create_cdata=0; GLint polygonmode[2]; char val[32]; @@ -2976,8 +2976,10 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) if(select) cpack(0xFFFFFF); - else if((ma) && (part->draw&PART_DRAW_MAT_COL)) + else if((ma) && (part->draw&PART_DRAW_MAT_COL)) { glColor3f(ma->r,ma->g,ma->b); + create_cdata = 1; + } else cpack(0); @@ -3085,19 +3087,25 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) if(draw_as!=PART_DRAW_CIRC){ switch(draw_as){ case PART_DRAW_AXIS: - cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata"); - /* no break! */ case PART_DRAW_CROSS: + if(draw_as!=PART_DRAW_CROSS || create_cdata) + cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_cdata"); vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*6*3*sizeof(float), "particle_vdata"); break; case PART_DRAW_LINE: + if(create_cdata) + cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_cdata"); vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*2*3*sizeof(float), "particle_vdata"); break; case PART_DRAW_BB: + if(create_cdata) + cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_cdata"); vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata"); ndata=MEM_callocN((totpart+totchild)*(path_nbr+1)*4*3*sizeof(float), "particle_vdata"); break; default: + if(create_cdata) + cdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_cdata"); vdata=MEM_callocN((totpart+totchild)*(path_nbr+1)*3*sizeof(float), "particle_vdata"); } } @@ -3122,9 +3130,17 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) pa_time=(cfra-pa->time)/pa->lifetime; - if((part->flag&PART_ABS_TIME)==0 && part->ipo){ - calc_ipo(part->ipo, 100*pa_time); - execute_ipo((ID *)part, part->ipo); + if((part->flag&PART_ABS_TIME)==0){ + if(ma && ma->ipo){ + /* correction for lifetime */ + calc_ipo(ma->ipo, 100.0f*pa_time); + execute_ipo((ID *)ma, ma->ipo); + } + if(part->ipo) { + /* correction for lifetime */ + calc_ipo(part->ipo, 100*pa_time); + execute_ipo((ID *)part, part->ipo); + } } pa_size=pa->size; @@ -3141,9 +3157,17 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) pa_time=psys_get_child_time(psys,cpa,cfra); - if((part->flag&PART_ABS_TIME)==0 && part->ipo){ - calc_ipo(part->ipo, 100*pa_time); - execute_ipo((ID *)part, part->ipo); + if((part->flag&PART_ABS_TIME)==0) { + if(ma && ma->ipo){ + /* correction for lifetime */ + calc_ipo(ma->ipo, 100.0f*pa_time); + execute_ipo((ID *)ma, ma->ipo); + } + if(part->ipo) { + /* correction for lifetime */ + calc_ipo(part->ipo, 100*pa_time); + execute_ipo((ID *)part, part->ipo); + } } pa_size=psys_get_child_size(psys,cpa,cfra,0); @@ -3181,6 +3205,12 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) switch(draw_as){ case PART_DRAW_DOT: + if(cd) { + cd[0]=ma->r; + cd[1]=ma->g; + cd[2]=ma->b; + cd+=3; + } if(vd){ VECCOPY(vd,state.co) vd+=3; } @@ -3201,7 +3231,15 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) VECCOPY(vec2,state.co); } - else VECSUB(vec2,state.co,vec); + else { + if(cd) { + cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma->r; + cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma->g; + cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma->b; + cd+=18; + } + VECSUB(vec2,state.co,vec); + } VECADD(vec,state.co,vec); VECCOPY(vd,vec); vd+=3; @@ -3239,11 +3277,25 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) VecMulf(vec,VecLength(state.vel)); VECADDFAC(vd,state.co,vec,-part->draw_line[0]); vd+=3; VECADDFAC(vd,state.co,vec,part->draw_line[1]); vd+=3; + if(cd) { + cd[0]=cd[3]=ma->r; + cd[1]=cd[4]=ma->g; + cd[2]=cd[5]=ma->b; + cd+=3; + } break; case PART_DRAW_CIRC: + if(create_cdata) + glColor3f(ma->r,ma->g,ma->b); drawcircball(GL_LINE_LOOP, state.co, pixsize, imat); break; case PART_DRAW_BB: + if(cd) { + cd[0]=cd[3]=cd[6]=cd[9]=ma->r; + cd[1]=cd[4]=cd[7]=cd[10]=ma->g; + cd[2]=cd[5]=cd[8]=cd[11]=ma->b; + cd+=12; + } if(part->draw&PART_DRAW_BB_LOCK && part->bb_align==PART_BB_VIEW){ VECCOPY(xvec,bb_ob->obmat[0]); Normalize(xvec); @@ -3439,13 +3491,14 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) glDisable(GL_LIGHTING); } + if(cdata){ + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(3, GL_FLOAT, 0, cdata); + } + switch(draw_as){ case PART_DRAW_AXIS: case PART_DRAW_CROSS: - if(cdata){ - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(3, GL_FLOAT, 0, cdata); - } glDrawArrays(GL_LINES, 0, 6*totpoint); break; case PART_DRAW_LINE: diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index e979f6e16fc..e554b91dd52 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -691,7 +691,7 @@ static void draw_seq_strip(Sequence *seq, ScrArea *sa, SpaceSeq *sseq, int outli /* draw the main strip body */ if (is_single_image) /* single image */ - draw_shadedstrip(seq, col, seq_tx_get_final_left(seq), y1, seq_tx_get_final_right(seq), y2); + draw_shadedstrip(seq, col, seq_tx_get_final_left(seq, 0), y1, seq_tx_get_final_right(seq, 0), y2); else /* normal operation */ draw_shadedstrip(seq, col, x1, y1, x2, y2); diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 52e0d3d6f05..e83ecb13960 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -3732,18 +3732,22 @@ int play_anim(int mode) else viewmove(0); } } else if (event==WHEELDOWNMOUSE || (val && event==PADMINUS)) { /* copied from persptoetsen */ - /* this min and max is also in viewmove() */ - if(G.vd->persp==V3D_CAMOB) { - G.vd->camzoom-= 10; - if(G.vd->camzoom<-30) G.vd->camzoom= -30; + if (G.vd) { /* when using the sequencer this can be NULL */ + /* this min and max is also in viewmove() */ + if(G.vd->persp==V3D_CAMOB) { + G.vd->camzoom-= 10; + if(G.vd->camzoom<-30) G.vd->camzoom= -30; + } + else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2f; } - else if(G.vd->dist<10.0*G.vd->far) G.vd->dist*=1.2f; } else if (event==WHEELUPMOUSE || (val && event==PADPLUSKEY)) { /* copied from persptoetsen */ - if(G.vd->persp==V3D_CAMOB) { - G.vd->camzoom+= 10; - if(G.vd->camzoom>300) G.vd->camzoom= 300; + if (G.vd) { + if(G.vd->persp==V3D_CAMOB) { + G.vd->camzoom+= 10; + if(G.vd->camzoom>300) G.vd->camzoom= 300; + } + else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333f; } - else if(G.vd->dist> 0.001*G.vd->grid) G.vd->dist*=.83333f; } else if(event==MKEY) { if(val) add_marker(CFRA-1); } diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index c166a9df762..39f93510358 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -2396,6 +2396,7 @@ void fill_bones_armature(void) else if (count == 2) { EditBonePoint *ebp, *ebp2; float head[3], tail[3]; + short headtail = 0; /* check that the points don't belong to the same bone */ ebp= (EditBonePoint *)points.first; @@ -2420,7 +2421,7 @@ void fill_bones_armature(void) float distA, distB; /* get cursor location */ - VECCOPY (curs, give_cursor()); + VECCOPY(curs, give_cursor()); Mat4Invert(G.obedit->imat, G.obedit->obmat); Mat4MulVecfl(G.obedit->imat, curs); @@ -2432,26 +2433,47 @@ void fill_bones_armature(void) distB= VecLength(vecB); /* compare distances - closer one therefore acts as direction for bone to go */ - if (distA < distB) { - VECCOPY(head, ebp2->vec); - VECCOPY(tail, ebp->vec); - } - else { - VECCOPY(head, ebp->vec); - VECCOPY(tail, ebp2->vec); - } + headtail= (distA < distB) ? 2 : 1; } else if (ebp->head_owner) { + headtail = 1; + } + else if (ebp2->head_owner) { + headtail = 2; + } + + /* assign head/tail combinations */ + if (headtail == 2) { VECCOPY(head, ebp->vec); VECCOPY(tail, ebp2->vec); } - else if (ebp2->head_owner) { + else if (headtail == 1) { VECCOPY(head, ebp2->vec); VECCOPY(tail, ebp->vec); } - /* add new bone */ - newbone= add_points_bone(head, tail); + /* add new bone and parent it to the appropriate end */ + if (headtail) { + newbone= add_points_bone(head, tail); + + /* do parenting (will need to set connected flag too) */ + if (headtail == 2) { + /* ebp tail or head - tail gets priority */ + if (ebp->tail_owner) + newbone->parent= ebp->tail_owner; + else + newbone->parent= ebp->head_owner; + } + else { + /* ebp2 tail or head - tail gets priority */ + if (ebp2->tail_owner) + newbone->parent= ebp2->tail_owner; + else + newbone->parent= ebp2->head_owner; + } + + newbone->flag |= BONE_CONNECTED; + } } else { // FIXME.. figure out a method for multiple bones diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index bb706f1aa3f..fb0fac4489d 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -184,13 +184,24 @@ int seq_tx_get_end(Sequence *seq) return seq->start+seq->len; } -int seq_tx_get_final_left(Sequence *seq) +int seq_tx_get_final_left(Sequence *seq, int metaclip) { - return (seq->start - seq->startstill) + seq->startofs; + if (metaclip && seq->tmp) { + /* return the range clipped by the parents range */ + return MAX2( seq_tx_get_final_left(seq, 0), seq_tx_get_final_left((Sequence *)seq->tmp, 1) ); + } else { + return (seq->start - seq->startstill) + seq->startofs; + } + } -int seq_tx_get_final_right(Sequence *seq) +int seq_tx_get_final_right(Sequence *seq, int metaclip) { - return ((seq->start+seq->len) + seq->endstill) - seq->endofs; + if (metaclip && seq->tmp) { + /* return the range clipped by the parents range */ + return MIN2( seq_tx_get_final_right(seq, 0), seq_tx_get_final_right((Sequence *)seq->tmp, 1) ); + } else { + return ((seq->start+seq->len) + seq->endstill) - seq->endofs; + } } void seq_tx_set_final_left(Sequence *seq, int val) @@ -260,12 +271,12 @@ static void fix_single_image_seq(Sequence *seq) /* make sure the image is always at the start since there is only one, adjusting its start should be ok */ - left = seq_tx_get_final_left(seq); + left = seq_tx_get_final_left(seq, 0); start = seq->start; if (start != left) { offset = left - start; - seq_tx_set_final_left( seq, seq_tx_get_final_left(seq) - offset ); - seq_tx_set_final_right( seq, seq_tx_get_final_right(seq) - offset ); + seq_tx_set_final_left( seq, seq_tx_get_final_left(seq, 0) - offset ); + seq_tx_set_final_right( seq, seq_tx_get_final_right(seq, 0) - offset ); seq->start += offset; } } @@ -2927,34 +2938,34 @@ static int seq_get_snaplimit(void) static void transform_grab_xlimits(Sequence *seq, int leftflag, int rightflag) { if(leftflag) { - if (seq_tx_get_final_left(seq) >= seq_tx_get_final_right(seq)) { - seq_tx_set_final_left(seq, seq_tx_get_final_right(seq)-1); + if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_final_right(seq, 0)) { + seq_tx_set_final_left(seq, seq_tx_get_final_right(seq, 0)-1); } if (check_single_seq(seq)==0) { - if (seq_tx_get_final_left(seq) >= seq_tx_get_end(seq)) { + if (seq_tx_get_final_left(seq, 0) >= seq_tx_get_end(seq)) { seq_tx_set_final_left(seq, seq_tx_get_end(seq)-1); } /* dosnt work now - TODO */ /* - if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq)) { + if (seq_tx_get_start(seq) >= seq_tx_get_final_right(seq, 0)) { int ofs; - ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq); + ofs = seq_tx_get_start(seq) - seq_tx_get_final_right(seq, 0); seq->start -= ofs; - seq_tx_set_final_left(seq, seq_tx_get_final_left(seq) + ofs ); + seq_tx_set_final_left(seq, seq_tx_get_final_left(seq, 0) + ofs ); }*/ } } if(rightflag) { - if (seq_tx_get_final_right(seq) <= seq_tx_get_final_left(seq)) { - seq_tx_set_final_right(seq, seq_tx_get_final_left(seq)+1); + if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_final_left(seq, 0)) { + seq_tx_set_final_right(seq, seq_tx_get_final_left(seq, 0)+1); } if (check_single_seq(seq)==0) { - if (seq_tx_get_final_right(seq) <= seq_tx_get_start(seq)) { + if (seq_tx_get_final_right(seq, 0) <= seq_tx_get_start(seq)) { seq_tx_set_final_right(seq, seq_tx_get_start(seq)+1); } } @@ -3033,9 +3044,24 @@ void transform_seq(int mode, int context) for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { if((seq->flag & SELECT) && !(seq->depth==0 && seq->flag & SEQ_LOCK)) totstrip++; + /* only needed for extend but can set here anyway since were alredy looping */ + seq->tmp= NULL; } } + /* for extending we need the metastrip clipped left/right values, set the metastrips as parents in seq->tmp */ + if (mode=='e') { + Sequence *meta_seq; + for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { + if (seq->type == SEQ_META) { + for (meta_seq = seq->seqbase.first; meta_seq; meta_seq= meta_seq->next){ + meta_seq->tmp= (void *)seq; + } + } + } + } + + if (sseq->flag & SEQ_MARKER_TRANS) { for(marker= G.scene->markers.first; marker; marker= marker->next) { if(marker->flag & SELECT) totmark++; @@ -3064,8 +3090,8 @@ void transform_seq(int mode, int context) /* for extend only */ if (mode=='e') { - ts->final_left = seq_tx_get_final_left(seq); - ts->final_right = seq_tx_get_final_right(seq); + ts->final_left = seq_tx_get_final_left(seq, 1); + ts->final_right = seq_tx_get_final_right(seq, 1); } ts++; } @@ -3151,9 +3177,9 @@ void transform_seq(int mode, int context) snap_point_num=0; if (last_seq && (last_seq->flag & SELECT)) { /* active seq bounds */ if(seq_tx_check_left(last_seq)) - snap_points[snap_point_num++] = seq_tx_get_final_left(last_seq); + snap_points[snap_point_num++] = seq_tx_get_final_left(last_seq, 0); if(seq_tx_check_right(last_seq)) - snap_points[snap_point_num++] = seq_tx_get_final_right(last_seq); + snap_points[snap_point_num++] = seq_tx_get_final_right(last_seq, 0); } if (totstrip > 1) { /* selection bounds */ @@ -3163,9 +3189,9 @@ void transform_seq(int mode, int context) for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { if(seq->flag & SELECT) { if(seq_tx_check_left(seq)) - bounds_left = MIN2(bounds_left, seq_tx_get_final_left(seq)); + bounds_left = MIN2(bounds_left, seq_tx_get_final_left(seq, 0)); if(seq_tx_check_right(seq)) - bounds_right = MAX2(bounds_right,seq_tx_get_final_right(seq)); + bounds_right = MAX2(bounds_right,seq_tx_get_final_right(seq, 0)); } } @@ -3214,13 +3240,13 @@ void transform_seq(int mode, int context) if (snap_dist && last_seq && seq_tx_check_left(last_seq)) { seq = find_next_prev_sequence(last_seq, 1, 0); /* left */ if(seq && !seq_tx_check_right(seq)) - TESTSNAP(seq_tx_get_final_right(seq)); + TESTSNAP(seq_tx_get_final_right(seq, 0)); } if (snap_dist && last_seq && seq_tx_check_right(last_seq)) { seq = find_next_prev_sequence(last_seq, 2, 0); /* right */ if(seq && !seq_tx_check_left(seq)) - TESTSNAP(seq_tx_get_final_left(seq)); + TESTSNAP(seq_tx_get_final_left(seq, 0)); } #undef TESTSNAP @@ -3242,20 +3268,23 @@ void transform_seq(int mode, int context) for(seq_index=0, seq=seqar[0]; seq_index < totseq_index; seq=seqar[++seq_index]) { if(seq->flag & SELECT && !(seq->depth==0 && seq->flag & SEQ_LOCK)) { int myofs; + /* flag, ignores lefsel/rightsel for nested strips */ + int sel_flag = (seq->depth==0) ? seq->flag : seq->flag & ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); + // SEQ_DEBUG_INFO(seq); /* X Transformation */ - if(seq->flag & SEQ_LEFTSEL) { + if((seq->depth==0) && (sel_flag & SEQ_LEFTSEL)) { myofs = (ts->startofs - ts->startstill); seq_tx_set_final_left(seq, ts->start + (myofs + ix)); } - if(seq->flag & SEQ_RIGHTSEL) { + if((seq->depth==0) && (sel_flag & SEQ_RIGHTSEL)) { myofs = (ts->endstill - ts->endofs); seq_tx_set_final_right(seq, ts->start + seq->len + (myofs + ix)); } - transform_grab_xlimits(seq, seq->flag & SEQ_LEFTSEL, seq->flag & SEQ_RIGHTSEL); + transform_grab_xlimits(seq, sel_flag & SEQ_LEFTSEL, sel_flag & SEQ_RIGHTSEL); - if( (seq->flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0 ) { + if( (sel_flag & (SEQ_LEFTSEL+SEQ_RIGHTSEL))==0 ) { if(sequence_is_free_transformable(seq)) seq->start= ts->start+ ix; /* Y Transformation */ @@ -3300,8 +3329,8 @@ void transform_seq(int mode, int context) //SEQ_DEBUG_INFO(seq); - final_left = seq_tx_get_final_left(seq); - final_right = seq_tx_get_final_right(seq); + final_left = seq_tx_get_final_left(seq, 1); + final_right = seq_tx_get_final_right(seq, 1); /* Only X Axis moving */ @@ -3591,8 +3620,8 @@ void seq_separate_images(void) BLI_remlink(ed->seqbasep, seq); if(seq->ipo) seq->ipo->id.us--; - start_ofs = cfra = seq_tx_get_final_left(seq); - frame_end = seq_tx_get_final_right(seq); + start_ofs = cfra = seq_tx_get_final_left(seq, 0); + frame_end = seq_tx_get_final_right(seq, 0); while (cfra < frame_end) { /* new seq */ diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index 9689ffdafeb..2ba5745b19b 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -1591,7 +1591,7 @@ static void do_filesel_buttons(short event, SpaceFile *sfile) BLI_del_slash(butname); if(sfile->type & FILE_UNIX) { - if (!BLI_exists(butname)) { + if (butname[0] != '\0' && !BLI_exists(butname)) { if (okee("Makedir")) { BLI_recurdir_fileops(butname); if (!BLI_exists(butname)) parent(sfile); diff --git a/source/blender/src/fluidsim.c b/source/blender/src/fluidsim.c index a7361a9ffca..8b9c89656fb 100644 --- a/source/blender/src/fluidsim.c +++ b/source/blender/src/fluidsim.c @@ -481,6 +481,7 @@ void fluidsimBake(struct Object *ob) struct Object *fsDomain = NULL; FluidsimSettings *domainSettings; struct Object *obit = NULL; /* object iterator */ + Base *base; int origFrame = G.scene->r.cfra; char debugStrBuffer[256]; int dirExist = 0; @@ -522,7 +523,7 @@ void fluidsimBake(struct Object *ob) float *channelObjMove[256][3]; // object movments , 0=trans, 1=rot, 2=scale float *channelObjInivel[256]; // initial velocities float *channelObjActive[256]; // obj active channel - + if(getenv(strEnvName)) { int dlevel = atoi(getenv(strEnvName)); elbeemSetDebugLevel(dlevel); @@ -545,7 +546,6 @@ void fluidsimBake(struct Object *ob) /* no object pointer, find in selected ones.. */ if(!ob) { - Base *base; for(base=G.scene->base.first; base; base= base->next) { if ( ((base)->flag & SELECT) // ignore layer setting for now? && ((base)->lay & G.vd->lay) @@ -561,8 +561,26 @@ void fluidsimBake(struct Object *ob) if(!ob) return; } + channelObjCount = 0; + for(base=G.scene->base.first; base; base= base->next) { + obit = base->object; + //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG + if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && + (obit->type==OB_MESH) && + (obit->fluidsimSettings->type != OB_FLUIDSIM_DOMAIN) && // if has to match 3 places! // CHECKMATCH + (obit->fluidsimSettings->type != OB_FLUIDSIM_PARTICLE) ) { + channelObjCount++; + } + } + + if (channelObjCount>=255) { + pupmenu("Fluidsim Bake Error%t|Cannot bake with more then 256 objects"); + return; + } + /* check if there's another domain... */ - for(obit= G.main->object.first; obit; obit= obit->id.next) { + for(base=G.scene->base.first; base; base= base->next) { + obit = base->object; if((obit->fluidsimFlag & OB_FLUIDSIM_ENABLE)&&(obit->type==OB_MESH)) { if(obit->fluidsimSettings->type == OB_FLUIDSIM_DOMAIN) { if(obit != ob) { @@ -605,7 +623,8 @@ void fluidsimBake(struct Object *ob) // check if theres any fluid // abort baking if not... - for(obit= G.main->object.first; obit; obit= obit->id.next) { + for(base=G.scene->base.first; base; base= base->next) { + obit = base->object; if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (obit->type==OB_MESH) && ( (obit->fluidsimSettings->type == OB_FLUIDSIM_FLUID) || @@ -749,7 +768,8 @@ void fluidsimBake(struct Object *ob) // init obj movement channels channelObjCount=0; - for(obit= G.main->object.first; obit; obit= obit->id.next) { + for(base=G.scene->base.first; base; base= base->next) { + obit = base->object; //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (obit->type==OB_MESH) && @@ -952,7 +972,8 @@ void fluidsimBake(struct Object *ob) // init objects channelObjCount = 0; - for(obit= G.main->object.first; obit; obit= obit->id.next) { + for(base=G.scene->base.first; base; base= base->next) { + obit = base->object; //{ snprintf(debugStrBuffer,256,"DEBUG object name=%s, type=%d ...\n", obit->id.name, obit->type); elbeemDebugOut(debugStrBuffer); } // DEBUG if( (obit->fluidsimFlag & OB_FLUIDSIM_ENABLE) && // if has to match 3 places! // CHECKMATCH (obit->type==OB_MESH) && diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c index e27e772edee..ac165d6aeb2 100644 --- a/source/blender/src/meshtools.c +++ b/source/blender/src/meshtools.c @@ -957,6 +957,12 @@ int *mesh_get_x_mirror_faces(Object *ob) mirrormf.v3= mirrorverts[mf->v1]; mirrormf.v4= (mf->v4)? mirrorverts[mf->v4]: 0; + /* make sure v4 is not 0 if a quad */ + if(mf->v4 && mirrormf.v4==0) { + SWAP(int, mirrormf.v1, mirrormf.v3); + SWAP(int, mirrormf.v2, mirrormf.v4); + } + hashmf= BLI_ghash_lookup(fhash, &mirrormf); if(hashmf) { mirrorfaces[a*2]= hashmf - mface; diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 4be525f4945..dcebf6b7557 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -1365,7 +1365,7 @@ static void createTransCurveVerts(TransInfo *t) tail++; } if( propmode || - ((bezt->f1 & SELECT) && (G.f & G_HIDDENHANDLES)) || + ((bezt->f2 & SELECT) && (G.f & G_HIDDENHANDLES)) || ((bezt->f3 & SELECT) && (G.f & G_HIDDENHANDLES)==0) ) { VECCOPY(td->iloc, bezt->vec[2]); diff --git a/source/blender/src/transform_manipulator.c b/source/blender/src/transform_manipulator.c index 5c06aaea890..050360887b4 100644 --- a/source/blender/src/transform_manipulator.c +++ b/source/blender/src/transform_manipulator.c @@ -158,7 +158,7 @@ static void protectflag_to_drawflags(short protectflag, short *drawflags) } /* for pose mode */ -static void stats_pose(View3D *v3d, bPoseChannel *pchan, float *normal, float *plane) +static void stats_pose(View3D *v3d, bPoseChannel *pchan) { Bone *bone= pchan->bone; @@ -166,9 +166,6 @@ static void stats_pose(View3D *v3d, bPoseChannel *pchan, float *normal, float *p if (bone->flag & BONE_TRANSFORM) { calc_tw_center(pchan->pose_head); protectflag_to_drawflags(pchan->protectflag, &v3d->twdrawflag); - - VecAddf(normal, normal, pchan->pose_mat[2]); - VecAddf(plane, plane, pchan->pose_mat[1]); } } } @@ -349,26 +346,24 @@ int calc_manipulator_stats(ScrArea *sa) } } else if(ob && (ob->flag & OB_POSEMODE)) { - bArmature *arm= ob->data; + bArmature *arm = ob->data; bPoseChannel *pchan; int mode; if((ob->lay & G.vd->lay)==0) return 0; - mode= Trans.mode; - Trans.mode= TFM_ROTATION; // mislead counting bones... bah + mode = Trans.mode; + Trans.mode = TFM_ROTATION; // mislead counting bones... bah /* count total, we use same method as transform will do */ Trans.total= 0; count_bone_select(&Trans, arm, &arm->bonebase, 1); - totsel= Trans.total; + totsel = Trans.total; if(totsel) { /* use channels to get stats */ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - stats_pose(v3d, pchan, normal, plane); + stats_pose(v3d, pchan); } - //VecMulf(normal, -1.0); - VecMulf(plane, -1.0); VecMulf(G.scene->twcent, 1.0f/(float)totsel); // centroid! Mat4MulVecfl(ob->obmat, G.scene->twcent); @@ -376,7 +371,7 @@ int calc_manipulator_stats(ScrArea *sa) Mat4MulVecfl(ob->obmat, G.scene->twmax); } /* restore, mode can be TFM_INIT */ - Trans.mode= mode; + Trans.mode = mode; } else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE)) { ; @@ -433,7 +428,7 @@ int calc_manipulator_stats(ScrArea *sa) break; case V3D_MANIP_NORMAL: - if(G.obedit) { + if(G.obedit || ob->flag & OB_POSEMODE) { float mat[3][3]; int type; @@ -479,34 +474,6 @@ int calc_manipulator_stats(ScrArea *sa) } break; } - /* pose mode is a bit weird, so keep it separated */ - else if (ob->flag & OB_POSEMODE) - { - strcpy(t->spacename, "normal"); - if(normal[0]!=0.0 || normal[1]!=0.0 || normal[2]!=0.0) { - float imat[3][3], mat[3][3]; - - /* we need the transpose of the inverse for a normal... */ - Mat3CpyMat4(imat, ob->obmat); - - Mat3Inv(mat, imat); - Mat3Transp(mat); - Mat3MulVecfl(mat, normal); - Mat3MulVecfl(mat, plane); - - Normalize(normal); - if(0.0==Normalize(plane)) VECCOPY(plane, mat[1]); - - VECCOPY(mat[2], normal); - Crossf(mat[0], normal, plane); - Crossf(mat[1], mat[2], mat[0]); - - Mat4CpyMat3(v3d->twmat, mat); - Mat4Ortho(v3d->twmat); - - break; - } - } /* no break we define 'normal' as 'local' in Object mode */ case V3D_MANIP_LOCAL: strcpy(t->spacename, "local"); diff --git a/source/blender/src/transform_orientations.c b/source/blender/src/transform_orientations.c index 6696fcf95d6..9c7a2f67b89 100644 --- a/source/blender/src/transform_orientations.c +++ b/source/blender/src/transform_orientations.c @@ -27,6 +27,7 @@ #include "MEM_guardedalloc.h" #include "DNA_armature_types.h" +#include "DNA_action_types.h" #include "DNA_curve_types.h" #include "DNA_listBase.h" #include "DNA_object_types.h" @@ -68,11 +69,17 @@ void BIF_clearTransformOrientation(void) } void BIF_manageTransformOrientation(int confirm, int set) { + Object *ob = OBACT; int index = -1; if (G.obedit) { if (G.obedit->type == OB_MESH) index = manageMeshSpace(confirm, set); + else if (G.obedit->type == OB_ARMATURE) + index = manageBoneSpace(confirm, set); + } + else if (ob && (ob->flag & OB_POSEMODE)) { + index = manageBoneSpace(confirm, set); } else { index = manageObjectSpace(confirm, set); @@ -122,6 +129,31 @@ int confirmSpace(int set, char text[]) } } +int manageBoneSpace(int confirm, int set) { + float mat[3][3]; + float normal[3], plane[3]; + char name[36] = ""; + int index; + + getTransformOrientation(normal, plane, 0); + + if (confirm == 0 && confirmSpace(set, "Bone") == 0) { + return -1; + } + + if (createSpaceNormalTangent(mat, normal, plane) == 0) { + error("Cannot use zero-length bone"); + return -1; + } + + strcpy(name, "Bone"); + + /* Input name */ + sbutton(name, 1, 35, "name: "); + + index = addMatrixSpace(mat, name); + return index; +} int manageMeshSpace(int confirm, int set) { float mat[3][3]; @@ -363,6 +395,29 @@ void applyTransformOrientation() { } } +static int count_bone_select(bArmature *arm, ListBase *lb, int do_it) +{ + Bone *bone; + int do_next; + int total = 0; + + for(bone= lb->first; bone; bone= bone->next) { + bone->flag &= ~BONE_TRANSFORM; + do_next = do_it; + if(do_it) { + if(bone->layer & arm->layer) { + if (bone->flag & BONE_SELECTED) { + bone->flag |= BONE_TRANSFORM; + total++; + do_next= 0; // no transform on children if one parent bone is selected + } + } + } + total += count_bone_select(arm, &bone->childbase, do_next); + } + + return total; +} int getTransformOrientation(float normal[3], float plane[3], int activeOnly) { @@ -375,6 +430,14 @@ int getTransformOrientation(float normal[3], float plane[3], int activeOnly) if(G.obedit) { + float imat[3][3], mat[3][3]; + + /* we need the transpose of the inverse for a normal... */ + Mat3CpyMat4(imat, ob->obmat); + + Mat3Inv(mat, imat); + Mat3Transp(mat); + ob= G.obedit; if(G.obedit->type==OB_MESH) @@ -639,12 +702,48 @@ int getTransformOrientation(float normal[3], float plane[3], int activeOnly) } } - - Mat4Mul3Vecfl(G.obedit->obmat, plane); - Mat4Mul3Vecfl(G.obedit->obmat, normal); + + /* Vectors from edges don't need the special transpose inverse multiplication */ + if (result == ORIENTATION_EDGE) + { + Mat4Mul3Vecfl(ob->obmat, normal); + Mat4Mul3Vecfl(ob->obmat, plane); + } + else + { + Mat3MulVecfl(mat, normal); + Mat3MulVecfl(mat, plane); + } } else if(ob && (ob->flag & OB_POSEMODE)) { + bArmature *arm= ob->data; + bPoseChannel *pchan; + int totsel; + + totsel = count_bone_select(arm, &arm->bonebase, 1); + if(totsel) { + float imat[3][3], mat[3][3]; + + /* use channels to get stats */ + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) { + VecAddf(normal, normal, pchan->pose_mat[2]); + VecAddf(plane, plane, pchan->pose_mat[1]); + } + } + VecMulf(plane, -1.0); + + /* we need the transpose of the inverse for a normal... */ + Mat3CpyMat4(imat, ob->obmat); + + Mat3Inv(mat, imat); + Mat3Transp(mat); + Mat3MulVecfl(mat, normal); + Mat3MulVecfl(mat, plane); + + result = ORIENTATION_EDGE; + } } else if(G.f & (G_VERTEXPAINT + G_TEXTUREPAINT + G_WEIGHTPAINT + G_SCULPTMODE)) { diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 2904ca60a12..1e45f2bf3e0 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -1448,6 +1448,8 @@ void obmat_to_viewmat(Object *ob, short smooth) float bmat[4][4]; float tmat[3][3]; + G.vd->view= 0; /* dont show the grid */ + Mat4CpyMat4(bmat, ob->obmat); Mat4Ortho(bmat); Mat4Invert(G.vd->viewmat, bmat);