Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErwin Coumans <blender@erwincoumans.com>2008-09-03 06:27:16 +0400
committerErwin Coumans <blender@erwincoumans.com>2008-09-03 06:27:16 +0400
commit1926e846500212d11061c23cacdbd08d88e375da (patch)
treead72fe64632cfc22a4878e065578b66d52de218d /extern/bullet2/src
parent33ac84e888ee3e3217f15f955e1b389a9c4bb230 (diff)
Finally upgraded to latest Bullet subversion, about to release 2.71. Some recent changes in extern/bullet2 need to be re-applied, will check with Benoit. Ray tests in 0_FPS_Template.blend is broken, didn't figure out why yet.
HELP BUILD SYSTEM MAINTAINERS: Please help with updating all build systems: the newly added files need to be added. Note that the src/SoftBody has been added for future extension of real-time soft bodies.
Diffstat (limited to 'extern/bullet2/src')
-rw-r--r--extern/bullet2/src/Bullet-C-Api.h136
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp636
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h865
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h28
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h55
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp2
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h11
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp1320
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h1101
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp344
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h103
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h22
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp466
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h144
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp505
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h351
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h40
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp1025
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h486
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp236
-rw-r--r--extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h101
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp15
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h6
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp85
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h66
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp683
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h44
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h47
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h2
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp237
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h62
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp10
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h71
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp629
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h210
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp36
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h28
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp27
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h24
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp20
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h25
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp108
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h71
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp281
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h112
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h10
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp30
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h29
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp129
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h14
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp19
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h23
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp19
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h18
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp18
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h18
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h6
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp11
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h104
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp221
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h40
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp36
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h77
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp9
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h45
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp61
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h75
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h6
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h12
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h20
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp78
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h98
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp59
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h87
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp5
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h17
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp14
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h20
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.cpp2
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h14
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp107
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h17
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h34
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp6
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h12
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h13
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp45
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h124
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp655
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h297
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp42
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h14
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp164
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h56
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp2
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h20
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp5
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h16
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp6
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.h12
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h6
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp9
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.h10
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h4
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp45
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h40
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp86
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h84
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp109
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h62
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp14
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h17
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h18
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp114
-rw-r--r--extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h88
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp41
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h6
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h18
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h4
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h6
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp160
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h10
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp10
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h8
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp943
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h71
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp13
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h2
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp11
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h12
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h26
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp7
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h2
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp38
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h62
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp74
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h27
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h4
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp80
-rw-r--r--extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp2
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp27
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h3
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h13
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp32
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h4
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h54
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp749
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h487
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp267
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h97
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h4
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp15
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h18
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp820
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h46
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp414
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h215
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h4
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h64
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h21
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp15
-rw-r--r--extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h38
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp368
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp193
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h46
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp455
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h42
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h86
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp214
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h189
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp52
-rw-r--r--extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h32
-rw-r--r--extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp72
-rw-r--r--extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h14
-rw-r--r--extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h2
-rw-r--r--extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h4
-rw-r--r--extern/bullet2/src/BulletSoftBody/CMakeLists.txt21
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBody.cpp2590
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBody.h810
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp410
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h118
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp656
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h107
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h895
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp108
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h48
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp79
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h75
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp126
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h73
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp46
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h69
-rw-r--r--extern/bullet2/src/BulletSoftBody/btSparseSDF.h306
-rw-r--r--extern/bullet2/src/LinearMath/btAabbUtil2.h49
-rw-r--r--extern/bullet2/src/LinearMath/btAlignedAllocator.cpp179
-rw-r--r--extern/bullet2/src/LinearMath/btAlignedAllocator.h28
-rw-r--r--extern/bullet2/src/LinearMath/btAlignedObjectArray.h69
-rw-r--r--extern/bullet2/src/LinearMath/btDefaultMotionState.h2
-rw-r--r--extern/bullet2/src/LinearMath/btGeometryUtil.cpp9
-rw-r--r--extern/bullet2/src/LinearMath/btGeometryUtil.h1
-rw-r--r--extern/bullet2/src/LinearMath/btIDebugDraw.h16
-rw-r--r--extern/bullet2/src/LinearMath/btMatrix3x3.h11
-rw-r--r--extern/bullet2/src/LinearMath/btMinMax.h12
-rw-r--r--extern/bullet2/src/LinearMath/btMotionState.h2
-rw-r--r--extern/bullet2/src/LinearMath/btQuadWord.h71
-rw-r--r--extern/bullet2/src/LinearMath/btQuaternion.h10
-rw-r--r--extern/bullet2/src/LinearMath/btQuickprof.cpp302
-rw-r--r--extern/bullet2/src/LinearMath/btQuickprof.h820
-rw-r--r--extern/bullet2/src/LinearMath/btScalar.h253
-rw-r--r--extern/bullet2/src/LinearMath/btStackAlloc.h19
-rw-r--r--extern/bullet2/src/LinearMath/btTransform.h19
-rw-r--r--extern/bullet2/src/LinearMath/btTransformUtil.h12
-rw-r--r--extern/bullet2/src/LinearMath/btVector3.h51
-rw-r--r--extern/bullet2/src/btBulletCollisionCommon.h7
-rw-r--r--extern/bullet2/src/btBulletDynamicsCommon.h8
217 files changed, 24840 insertions, 5141 deletions
diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h
index 078dcae63bb..a196f6417bc 100644
--- a/extern/bullet2/src/Bullet-C-Api.h
+++ b/extern/bullet2/src/Bullet-C-Api.h
@@ -23,11 +23,145 @@ subject to the following restrictions:
#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
-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]);
+/* 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 */
#ifdef __cplusplus
}
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 <assert.h>
-#ifdef DEBUG_BROADPHASE
-#include <stdio.h>
-void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality)
+btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache)
+:btAxisSweep3Internal<unsigned short int>(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;i<numEdges+1;i++)
- {
- Edge* pEdge = m_pEdges[axis] + i;
- Handle* pHandlePrev = getHandle(pEdge->m_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<Handle*>(proxy);
- removeHandle(handle->m_handleId);
-}
-
-void btAxisSweep3::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)
-{
- Handle* handle = static_cast<Handle*>(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;i<m_overlappingPairArray.size();i++)
- {
-
- btBroadphasePair& pair = m_overlappingPairArray[i];
-
- bool isDuplicate = (pair == previousPair);
-
- previousPair = pair;
-
- bool needsRemoval = false;
-
- if (!isDuplicate)
- {
- bool hasOverlap = testOverlap(pair.m_pProxy0,pair.m_pProxy1);
-
- if (hasOverlap)
- {
- needsRemoval = callback->processOverlap(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<Handle*>(proxy0);
- const Handle* pHandleB = static_cast<Handle*>(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++;
- }
-
+ btAssert(maxHandles > 1 && maxHandles < 32767);
}
-// 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)
+bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache )
+:btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache)
{
- 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..e7c5fb5b6cf 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h
@@ -19,34 +19,25 @@
#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
+/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
+/// It uses quantized integers to represent the begin and end points for each of the 3 axis.
+/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
+template <typename BP_FP_INT_TYPE>
+class btAxisSweep3Internal : public btBroadphaseInterface
{
+protected:
+
+ BP_FP_INT_TYPE m_bpHandleMask;
+ BP_FP_INT_TYPE m_handleSentinel;
public:
@@ -57,40 +48,52 @@ 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;}
+ BP_FP_INT_TYPE IsMax() const {return static_cast<BP_FP_INT_TYPE>(m_pos & 1);}
};
public:
+ //This breaks the Intel compiler, see http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30253577.aspx
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
+ void* m_pHandlesRawPtr;
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)
+ void* m_pEdgesRawPtr[3];
+
+ 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;
+ int m_invalidPair;
// allocation/deallocation
BP_FP_INT_TYPE allocHandle();
@@ -108,29 +111,801 @@ 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();
+
+ BP_FP_INT_TYPE getNumHandles() const
+ {
+ return m_numHandles;
+ }
+
+ 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* multiSapProxy);
+ 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,void* multiSapProxy);
+ 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;
+ }
+
+ ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+ ///will add some transform later
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ aabbMin = m_worldAabbMin;
+ aabbMax = m_worldAabbMax;
+ }
+
+ virtual void printStats()
+ {
+/* printf("btAxisSweep3.h\n");
+ printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+ printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
+ m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
+ */
+
+ }
+
+};
+
+////////////////////////////////////////////////////////////////////
+
+
+
+
+#ifdef DEBUG_BROADPHASE
+#include <stdio.h>
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3<BP_FP_INT_TYPE>::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;i<numEdges+1;i++)
+ {
+ Edge* pEdge = m_pEdges[axis] + i;
+ Handle* pHandlePrev = getHandle(pEdge->m_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 <typename BP_FP_INT_TYPE>
+btBroadphaseProxy* btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
+{
+ (void)shapeType;
+ BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy);
+
+ Handle* handle = getHandle(handleId);
+
+ return handle;
+}
+
+
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+ Handle* handle = static_cast<Handle*>(proxy);
+ removeHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), dispatcher);
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+{
+ Handle* handle = static_cast<Handle*>(proxy);
+ updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax,dispatcher);
+
+}
+
+
+
+
+
+template <typename BP_FP_INT_TYPE>
+btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache )
+:m_bpHandleMask(handleMask),
+m_handleSentinel(handleSentinel),
+m_pairCache(pairCache),
+m_userPairCallback(0),
+m_ownsPairCache(false),
+m_invalidPair(0)
+{
+ BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles+1);//need to add one sentinel handle
+
+ if (!m_pairCache)
+ {
+ void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
+ m_pairCache = new(ptr) btHashedOverlappingPairCache();
+ 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
+ m_pHandlesRawPtr = btAlignedAlloc(sizeof(Handle)*maxHandles,16);
+ m_pHandles = new(m_pHandlesRawPtr) 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(static_cast<BP_FP_INT_TYPE>(i + 1));
+ m_pHandles[maxHandles - 1].SetNextFree(0);
+ }
+
+ {
+ // allocate edge buffers
+ for (int i = 0; i < 3; i++)
+ {
+ m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
+ m_pEdges[i] = new(m_pEdgesRawPtr[i]) 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 <typename BP_FP_INT_TYPE>
+btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
+{
+
+ for (int i = 2; i >= 0; i--)
+ {
+ btAlignedFree(m_pEdgesRawPtr[i]);
+ }
+ btAlignedFree(m_pHandlesRawPtr);
+
+ if (m_ownsPairCache)
+ {
+ m_pairCache->~btOverlappingPairCache();
+ btAlignedFree(m_pairCache);
+ }
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::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 <typename BP_FP_INT_TYPE>
+BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
+{
+ assert(m_firstFreeHandle);
+
+ BP_FP_INT_TYPE handle = m_firstFreeHandle;
+ m_firstFreeHandle = getHandle(handle)->GetNextFree();
+ m_numHandles++;
+
+ return handle;
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
+{
+ assert(handle > 0 && handle < m_maxHandles);
+
+ getHandle(handle)->SetNextFree(m_firstFreeHandle);
+ m_firstFreeHandle = handle;
+
+ m_numHandles--;
+}
+
+
+template <typename BP_FP_INT_TYPE>
+BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
+{
+ // 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 = static_cast<int>(handle);
+ //pHandle->m_pOverlaps = 0;
+ pHandle->m_clientObject = pOwner;
+ pHandle->m_collisionFilterGroup = collisionFilterGroup;
+ pHandle->m_collisionFilterMask = collisionFilterMask;
+ pHandle->m_multiSapParentProxy = multiSapProxy;
+
+ // compute current limit of edge arrays
+ BP_FP_INT_TYPE limit = static_cast<BP_FP_INT_TYPE>(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] = static_cast<BP_FP_INT_TYPE>(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 <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::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
+ if (!m_pairCache->hasDeferredRemoval())
+ {
+ m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
+ }
+
+ // compute current limit of edge arrays
+ int limit = static_cast<int>(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 <stdio.h>
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+
+ if (m_pairCache->hasDeferredRemoval())
+ {
+
+ btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(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;i<overlappingPairArray.size();i++)
+ {
+
+ btBroadphasePair& pair = overlappingPairArray[i];
+
+ bool isDuplicate = (pair == previousPair);
+
+ previousPair = pair;
+
+ bool needsRemoval = false;
+
+ if (!isDuplicate)
+ {
+ bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+ if (hasOverlap)
+ {
+ needsRemoval = false;//callback->processOverlap(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.quickSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+ #endif//CLEAN_INVALID_PAIRS
+
+ //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+ }
+
+
+
+
+
+}
+
+
+template <typename BP_FP_INT_TYPE>
+bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ const Handle* pHandleA = static_cast<Handle*>(proxy0);
+ const Handle* pHandleB = static_cast<Handle*>(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 <typename BP_FP_INT_TYPE>
+bool btAxisSweep3Internal<BP_FP_INT_TYPE>::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 <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::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 <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::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 <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::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())
+ {
+
+ // 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,dispatcher);
+
+ }
+
+
+ // 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 <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::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
+
+ 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,dispatcher);
+
+
+
+ }
+
+ // 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 <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::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++;
+ }
+
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+
+
+/// The 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 or btDbvtBroadphase 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<unsigned short int>
+{
+public:
+
+ btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0);
+
+};
+
+/// The 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<unsigned int>
+{
+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..200ac365329 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
@@ -20,20 +20,34 @@ subject to the following restrictions:
struct btDispatcherInfo;
class btDispatcher;
-struct btBroadphaseProxy;
-#include "../../LinearMath/btVector3.h"
+#include "btBroadphaseProxy.h"
+class btOverlappingPairCache;
-///BroadphaseInterface for aabb-overlapping object pairs
+#include "LinearMath/btVector3.h"
+
+///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs.
+///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase.
+///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class.
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,void* multiSapProxy) =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;
+
+ ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+ ///will add some transform later
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+ virtual void printStats() = 0;
};
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
index 40d9748ffa9..e0bb67f8521 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
@@ -50,6 +52,8 @@ CONCAVE_SHAPES_START_HERE,
TERRAIN_SHAPE_PROXYTYPE,
///Used for GIMPACT Trimesh integration
GIMPACT_SHAPE_PROXYTYPE,
+///Multimaterial mesh
+ MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
EMPTY_SHAPE_PROXYTYPE,
STATIC_PLANE_PROXYTYPE,
@@ -57,13 +61,18 @@ CONCAVE_SHAPES_END_HERE,
COMPOUND_SHAPE_PROXYTYPE,
+ SOFTBODY_SHAPE_PROXYTYPE,
+
MAX_BROADPHASE_COLLISION_TYPES
};
-///btBroadphaseProxy
-struct btBroadphaseProxy
+///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
+///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
+ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
{
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
///optional filtering to cull potential collisions
enum CollisionFilterGroups
@@ -73,44 +82,60 @@ struct btBroadphaseProxy
KinematicFilter = 4,
DebrisFilter = 8,
SensorTrigger = 16,
- AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
+ AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
};
//Usually the client btCollisionObject or Rigidbody class
void* m_clientObject;
+
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.
+
+ SIMD_FORCE_INLINE int getUid() const
+ {
+ return m_uniqueId;
+ }
+
//used for memory pools
- btBroadphaseProxy() :m_clientObject(0){}
+ btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0)
+ {
+ }
- btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask)
+ btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0)
:m_clientObject(userPtr),
m_collisionFilterGroup(collisionFilterGroup),
m_collisionFilterMask(collisionFilterMask)
{
+ m_multiSapParentProxy = multiSapParentProxy;
}
- 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);
}
@@ -124,8 +149,9 @@ struct btBroadphaseProxy;
-/// contains a pair of aabb-overlapping objects
-struct btBroadphasePair
+///The btBroadphasePair class contains a pair of aabb-overlapping objects.
+///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes.
+ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
{
btBroadphasePair ()
:
@@ -136,6 +162,8 @@ struct btBroadphasePair
{
}
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
btBroadphasePair(const btBroadphasePair& other)
: m_pProxy0(other.m_pProxy0),
m_pProxy1(other.m_pProxy1),
@@ -181,6 +209,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..1618ad9fdd3 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
@@ -16,7 +16,8 @@ subject to the following restrictions:
#ifndef COLLISION_ALGORITHM_H
#define COLLISION_ALGORITHM_H
-#include "../../LinearMath/btScalar.h"
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
struct btBroadphaseProxy;
class btDispatcher;
@@ -25,21 +26,22 @@ class btCollisionObject;
struct btDispatcherInfo;
class btPersistentManifold;
+typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
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();
@@ -71,6 +73,7 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
};
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp
new file mode 100644
index 00000000000..fade71179e6
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp
@@ -0,0 +1,1320 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#include "btDbvt.h"
+
+//
+typedef btAlignedObjectArray<btDbvtNode*> tNodeArray;
+typedef btAlignedObjectArray<const btDbvtNode*> tConstNodeArray;
+
+//
+struct btDbvtNodeEnumerator : btDbvt::ICollide
+{
+tConstNodeArray nodes;
+void Process(const btDbvtNode* n) { nodes.push_back(n); }
+};
+
+//
+static DBVT_INLINE int indexof(const btDbvtNode* node)
+{
+return(node->parent->childs[1]==node);
+}
+
+//
+static DBVT_INLINE btDbvtVolume merge( const btDbvtVolume& a,
+ const btDbvtVolume& b)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+DBVT_ALIGN char locals[sizeof(btDbvtAabbMm)];
+btDbvtVolume& res=*(btDbvtVolume*)locals;
+#else
+btDbvtVolume res;
+#endif
+Merge(a,b,res);
+return(res);
+}
+
+// volume+edge lengths
+static DBVT_INLINE btScalar size(const btDbvtVolume& a)
+{
+const btVector3 edges=a.Lengths();
+return( edges.x()*edges.y()*edges.z()+
+ edges.x()+edges.y()+edges.z());
+}
+
+//
+static void getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth)
+{
+if(node->isinternal())
+ {
+ getmaxdepth(node->childs[0],depth+1,maxdepth);
+ getmaxdepth(node->childs[0],depth+1,maxdepth);
+ } else maxdepth=btMax(maxdepth,depth);
+}
+
+//
+static DBVT_INLINE void deletenode( btDbvt* pdbvt,
+ btDbvtNode* node)
+{
+btAlignedFree(pdbvt->m_free);
+pdbvt->m_free=node;
+}
+
+//
+static void recursedeletenode( btDbvt* pdbvt,
+ btDbvtNode* node)
+{
+if(!node->isleaf())
+ {
+ recursedeletenode(pdbvt,node->childs[0]);
+ recursedeletenode(pdbvt,node->childs[1]);
+ }
+if(node==pdbvt->m_root) pdbvt->m_root=0;
+deletenode(pdbvt,node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ void* data)
+{
+btDbvtNode* node;
+if(pdbvt->m_free)
+ { node=pdbvt->m_free;pdbvt->m_free=0; }
+ else
+ { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); }
+node->parent = parent;
+node->data = data;
+node->childs[1] = 0;
+return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ const btDbvtVolume& volume,
+ void* data)
+{
+btDbvtNode* node=createnode(pdbvt,parent,data);
+node->volume=volume;
+return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ const btDbvtVolume& volume0,
+ const btDbvtVolume& volume1,
+ void* data)
+{
+btDbvtNode* node=createnode(pdbvt,parent,data);
+Merge(volume0,volume1,node->volume);
+return(node);
+}
+
+//
+static void insertleaf( btDbvt* pdbvt,
+ btDbvtNode* root,
+ btDbvtNode* leaf)
+{
+if(!pdbvt->m_root)
+ {
+ pdbvt->m_root = leaf;
+ leaf->parent = 0;
+ }
+ else
+ {
+ if(!root->isleaf())
+ {
+ do {
+ root=root->childs[Select( leaf->volume,
+ root->childs[0]->volume,
+ root->childs[1]->volume)];
+ } while(!root->isleaf());
+ }
+ btDbvtNode* prev=root->parent;
+ btDbvtNode* node=createnode(pdbvt,prev,leaf->volume,root->volume,0);
+ if(prev)
+ {
+ prev->childs[indexof(root)] = node;
+ node->childs[0] = root;root->parent=node;
+ node->childs[1] = leaf;leaf->parent=node;
+ do {
+ if(!prev->volume.Contain(node->volume))
+ Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ else
+ break;
+ node=prev;
+ } while(0!=(prev=node->parent));
+ }
+ else
+ {
+ node->childs[0] = root;root->parent=node;
+ node->childs[1] = leaf;leaf->parent=node;
+ pdbvt->m_root = node;
+ }
+ }
+}
+
+//
+static btDbvtNode* removeleaf( btDbvt* pdbvt,
+ btDbvtNode* leaf)
+{
+if(leaf==pdbvt->m_root)
+ {
+ pdbvt->m_root=0;
+ return(0);
+ }
+ else
+ {
+ btDbvtNode* parent=leaf->parent;
+ btDbvtNode* prev=parent->parent;
+ btDbvtNode* sibling=parent->childs[1-indexof(leaf)];
+ if(prev)
+ {
+ prev->childs[indexof(parent)]=sibling;
+ sibling->parent=prev;
+ deletenode(pdbvt,parent);
+ while(prev)
+ {
+ const btDbvtVolume pb=prev->volume;
+ Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ if(NotEqual(pb,prev->volume))
+ {
+ prev=prev->parent;
+ } else break;
+ }
+ return(prev?prev:pdbvt->m_root);
+ }
+ else
+ {
+ pdbvt->m_root=sibling;
+ sibling->parent=0;
+ deletenode(pdbvt,parent);
+ return(pdbvt->m_root);
+ }
+ }
+}
+
+//
+static void fetchleaves(btDbvt* pdbvt,
+ btDbvtNode* root,
+ tNodeArray& leaves,
+ int depth=-1)
+{
+if(root->isinternal()&&depth)
+ {
+ fetchleaves(pdbvt,root->childs[0],leaves,depth-1);
+ fetchleaves(pdbvt,root->childs[1],leaves,depth-1);
+ deletenode(pdbvt,root);
+ }
+ else
+ {
+ leaves.push_back(root);
+ }
+}
+
+//
+static void split( const tNodeArray& leaves,
+ tNodeArray& left,
+ tNodeArray& right,
+ const btVector3& org,
+ const btVector3& axis)
+{
+left.resize(0);
+right.resize(0);
+for(int i=0,ni=leaves.size();i<ni;++i)
+ {
+ if(dot(axis,leaves[i]->volume.Center()-org)<0)
+ left.push_back(leaves[i]);
+ else
+ right.push_back(leaves[i]);
+ }
+}
+
+//
+static btDbvtVolume bounds( const tNodeArray& leaves)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+DBVT_ALIGN char locals[sizeof(btDbvtVolume)];
+btDbvtVolume& volume=*(btDbvtVolume*)locals;
+volume=leaves[0]->volume;
+#else
+btDbvtVolume volume=leaves[0]->volume;
+#endif
+for(int i=1,ni=leaves.size();i<ni;++i)
+ {
+ Merge(volume,leaves[i]->volume,volume);
+ }
+return(volume);
+}
+
+//
+static void bottomup( btDbvt* pdbvt,
+ tNodeArray& leaves)
+{
+while(leaves.size()>1)
+ {
+ btScalar minsize=SIMD_INFINITY;
+ int minidx[2]={-1,-1};
+ for(int i=0;i<leaves.size();++i)
+ {
+ for(int j=i+1;j<leaves.size();++j)
+ {
+ const btScalar sz=size(merge(leaves[i]->volume,leaves[j]->volume));
+ if(sz<minsize)
+ {
+ minsize = sz;
+ minidx[0] = i;
+ minidx[1] = j;
+ }
+ }
+ }
+ btDbvtNode* n[] = {leaves[minidx[0]],leaves[minidx[1]]};
+ btDbvtNode* p = createnode(pdbvt,0,n[0]->volume,n[1]->volume,0);
+ p->childs[0] = n[0];
+ p->childs[1] = n[1];
+ n[0]->parent = p;
+ n[1]->parent = p;
+ leaves[minidx[0]] = p;
+ leaves.swap(minidx[1],leaves.size()-1);
+ leaves.pop_back();
+ }
+}
+
+//
+static btDbvtNode* topdown(btDbvt* pdbvt,
+ tNodeArray& leaves,
+ int bu_treshold)
+{
+static const btVector3 axis[]={btVector3(1,0,0),
+ btVector3(0,1,0),
+ btVector3(0,0,1)};
+if(leaves.size()>1)
+ {
+ if(leaves.size()>bu_treshold)
+ {
+ const btDbvtVolume vol=bounds(leaves);
+ const btVector3 org=vol.Center();
+ tNodeArray sets[2];
+ int bestaxis=-1;
+ int bestmidp=leaves.size();
+ int splitcount[3][2]={{0,0},{0,0},{0,0}};
+ int i;
+ for( i=0;i<leaves.size();++i)
+ {
+ const btVector3 x=leaves[i]->volume.Center()-org;
+ for(int j=0;j<3;++j)
+ {
+ ++splitcount[j][dot(x,axis[j])>0?1:0];
+ }
+ }
+ for( i=0;i<3;++i)
+ {
+ if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
+ {
+ const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1]));
+ if(midp<bestmidp)
+ {
+ bestaxis=i;
+ bestmidp=midp;
+ }
+ }
+ }
+ if(bestaxis>=0)
+ {
+ sets[0].reserve(splitcount[bestaxis][0]);
+ sets[1].reserve(splitcount[bestaxis][1]);
+ split(leaves,sets[0],sets[1],org,axis[bestaxis]);
+ }
+ else
+ {
+ sets[0].reserve(leaves.size()/2+1);
+ sets[1].reserve(leaves.size()/2);
+ for(int i=0,ni=leaves.size();i<ni;++i)
+ {
+ sets[i&1].push_back(leaves[i]);
+ }
+ }
+ btDbvtNode* node=createnode(pdbvt,0,vol,0);
+ node->childs[0]=topdown(pdbvt,sets[0],bu_treshold);
+ node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
+ node->childs[0]->parent=node;
+ node->childs[1]->parent=node;
+ return(node);
+ }
+ else
+ {
+ bottomup(pdbvt,leaves);
+ return(leaves[0]);
+ }
+ }
+return(leaves[0]);
+}
+
+//
+static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r)
+{
+btDbvtNode* p=n->parent;
+btAssert(n->isinternal());
+if(p>n)
+ {
+ const int i=indexof(n);
+ const int j=1-i;
+ btDbvtNode* s=p->childs[j];
+ btDbvtNode* q=p->parent;
+ btAssert(n==p->childs[i]);
+ if(q) q->childs[indexof(p)]=n; else r=n;
+ s->parent=n;
+ p->parent=n;
+ n->parent=q;
+ p->childs[0]=n->childs[0];
+ p->childs[1]=n->childs[1];
+ n->childs[0]->parent=p;
+ n->childs[1]->parent=p;
+ n->childs[i]=p;
+ n->childs[j]=s;
+ btSwap(p->volume,n->volume);
+ return(p);
+ }
+return(n);
+}
+
+//
+static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count)
+{
+while(n&&(count--)) n=n->parent;
+return(n);
+}
+
+//
+// Api
+//
+
+//
+ btDbvt::btDbvt()
+{
+m_root = 0;
+m_free = 0;
+m_lkhd = -1;
+m_leaves = 0;
+m_opath = 0;
+}
+
+//
+ btDbvt::~btDbvt()
+{
+clear();
+}
+
+//
+void btDbvt::clear()
+{
+if(m_root) recursedeletenode(this,m_root);
+btAlignedFree(m_free);
+m_free=0;
+}
+
+//
+void btDbvt::optimizeBottomUp()
+{
+if(m_root)
+ {
+ tNodeArray leaves;
+ leaves.reserve(m_leaves);
+ fetchleaves(this,m_root,leaves);
+ bottomup(this,leaves);
+ m_root=leaves[0];
+ }
+}
+
+//
+void btDbvt::optimizeTopDown(int bu_treshold)
+{
+if(m_root)
+ {
+ tNodeArray leaves;
+ leaves.reserve(m_leaves);
+ fetchleaves(this,m_root,leaves);
+ m_root=topdown(this,leaves,bu_treshold);
+ }
+}
+
+//
+void btDbvt::optimizeIncremental(int passes)
+{
+if(passes<0) passes=m_leaves;
+if(m_root&&(passes>0))
+ {
+ do {
+ btDbvtNode* node=m_root;
+ unsigned bit=0;
+ while(node->isinternal())
+ {
+ node=sort(node,m_root)->childs[(m_opath>>bit)&1];
+ bit=(bit+1)&(sizeof(unsigned)*8-1);
+ }
+ update(node);
+ ++m_opath;
+ } while(--passes);
+ }
+}
+
+//
+btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data)
+{
+btDbvtNode* leaf=createnode(this,0,volume,data);
+insertleaf(this,m_root,leaf);
+++m_leaves;
+return(leaf);
+}
+
+//
+void btDbvt::update(btDbvtNode* leaf,int lookahead)
+{
+btDbvtNode* root=removeleaf(this,leaf);
+if(root)
+ {
+ if(lookahead>=0)
+ {
+ for(int i=0;(i<lookahead)&&root->parent;++i)
+ {
+ root=root->parent;
+ }
+ } else root=m_root;
+ }
+insertleaf(this,root,leaf);
+}
+
+//
+void btDbvt::update(btDbvtNode* leaf,const btDbvtVolume& volume)
+{
+btDbvtNode* root=removeleaf(this,leaf);
+if(root)
+ {
+ if(m_lkhd>=0)
+ {
+ for(int i=0;(i<m_lkhd)&&root->parent;++i)
+ {
+ root=root->parent;
+ }
+ } else root=m_root;
+ }
+leaf->volume=volume;
+insertleaf(this,root,leaf);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin)
+{
+if(leaf->volume.Contain(volume)) return(false);
+volume.Expand(btVector3(margin,margin,margin));
+volume.SignedExpand(velocity);
+update(leaf,volume);
+return(true);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity)
+{
+if(leaf->volume.Contain(volume)) return(false);
+volume.SignedExpand(velocity);
+update(leaf,volume);
+return(true);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin)
+{
+if(leaf->volume.Contain(volume)) return(false);
+volume.Expand(btVector3(margin,margin,margin));
+update(leaf,volume);
+return(true);
+}
+
+//
+void btDbvt::remove(btDbvtNode* leaf)
+{
+removeleaf(this,leaf);
+deletenode(this,leaf);
+--m_leaves;
+}
+
+//
+void btDbvt::write(IWriter* iwriter) const
+{
+btDbvtNodeEnumerator nodes;
+nodes.nodes.reserve(m_leaves*2);
+enumNodes(m_root,nodes);
+iwriter->Prepare(m_root,nodes.nodes.size());
+for(int i=0;i<nodes.nodes.size();++i)
+ {
+ const btDbvtNode* n=nodes.nodes[i];
+ int p=-1;
+ if(n->parent) p=nodes.nodes.findLinearSearch(n->parent);
+ if(n->isinternal())
+ {
+ const int c0=nodes.nodes.findLinearSearch(n->childs[0]);
+ const int c1=nodes.nodes.findLinearSearch(n->childs[1]);
+ iwriter->WriteNode(n,i,p,c0,c1);
+ }
+ else
+ {
+ iwriter->WriteLeaf(n,i,p);
+ }
+ }
+}
+
+//
+void btDbvt::clone(btDbvt& dest,IClone* iclone) const
+{
+dest.clear();
+if(m_root!=0)
+ {
+ btAlignedObjectArray<sStkCLN> stack;
+ stack.reserve(m_leaves);
+ stack.push_back(sStkCLN(m_root,0));
+ do {
+ const int i=stack.size()-1;
+ const sStkCLN e=stack[i];
+ btDbvtNode* n=createnode(&dest,e.parent,e.node->volume,e.node->data);
+ stack.pop_back();
+ if(e.parent!=0)
+ e.parent->childs[i&1]=n;
+ else
+ dest.m_root=n;
+ if(e.node->isinternal())
+ {
+ stack.push_back(sStkCLN(e.node->childs[0],n));
+ stack.push_back(sStkCLN(e.node->childs[1],n));
+ }
+ else
+ {
+ iclone->CloneLeaf(n);
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+int btDbvt::maxdepth(const btDbvtNode* node)
+{
+int depth=0;
+if(node) getmaxdepth(node,1,depth);
+return(depth);
+}
+
+//
+int btDbvt::countLeaves(const btDbvtNode* node)
+{
+if(node->isinternal())
+ return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
+ else
+ return(1);
+}
+
+//
+void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves)
+{
+if(node->isinternal())
+ {
+ extractLeaves(node->childs[0],leaves);
+ extractLeaves(node->childs[1],leaves);
+ }
+ else
+ {
+ leaves.push_back(node);
+ }
+}
+
+//
+#if DBVT_ENABLE_BENCHMARK
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "LinearMath/btQuickProf.h"
+
+/*
+q6600,2.4ghz
+
+/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
+/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
+/Fo"..\..\out\release8\build\libbulletcollision\\"
+/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
+/W3 /nologo /c /Wp64 /Zi /errorReport:prompt
+
+Benchmarking dbvt...
+ World scale: 100.000000
+ Extents base: 1.000000
+ Extents range: 4.000000
+ Leaves: 8192
+ sizeof(btDbvtVolume): 32 bytes
+ sizeof(btDbvtNode): 44 bytes
+[1] btDbvtVolume intersections: 3537 ms (0%)
+[2] btDbvtVolume merges: 1945 ms (0%)
+[3] btDbvt::collideTT: 6646 ms (0%)
+[4] btDbvt::collideTT self: 3389 ms (0%)
+[5] btDbvt::collideTT xform: 7505 ms (0%)
+[6] btDbvt::collideTT xform,self: 7480 ms (0%)
+[7] btDbvt::collideRAY: 6307 ms (0%),(332511 r/s)
+[8] insert/remove: 2105 ms (-3%),(996271 ir/s)
+[9] updates (teleport): 1943 ms (0%),(1079337 u/s)
+[10] updates (jitter): 1301 ms (0%),(1611953 u/s)
+[11] optimize (incremental): 2510 ms (0%),(1671000 o/s)
+[12] btDbvtVolume notequal: 3677 ms (0%)
+[13] culling(OCL+fullsort): 2231 ms (0%),(458 t/s)
+[14] culling(OCL+qsort): 3500 ms (0%),(2340 t/s)
+[15] culling(KDOP+qsort): 1151 ms (0%),(7117 t/s)
+[16] insert/remove batch(256): 5138 ms (0%),(816330 bir/s)
+[17] btDbvtVolume proximity: 2842 ms (0%)
+[18] btDbvtVolume select: 3390 ms (0%)
+*/
+
+struct btDbvtBenchmark
+{
+struct NilPolicy : btDbvt::ICollide
+ {
+ NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {}
+ void Process(const btDbvtNode*,const btDbvtNode*) { ++m_pcount; }
+ void Process(const btDbvtNode*) { ++m_pcount; }
+ void Process(const btDbvtNode*,btScalar depth)
+ {
+ ++m_pcount;
+ if(m_checksort)
+ { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
+ }
+ int m_pcount;
+ btScalar m_depth;
+ bool m_checksort;
+ };
+struct P14 : btDbvt::ICollide
+ {
+ struct Node
+ {
+ const btDbvtNode* leaf;
+ btScalar depth;
+ };
+ void Process(const btDbvtNode* leaf,btScalar depth)
+ {
+ Node n;
+ n.leaf = leaf;
+ n.depth = depth;
+ }
+ static int sortfnc(const Node& a,const Node& b)
+ {
+ if(a.depth<b.depth) return(+1);
+ if(a.depth>b.depth) return(-1);
+ return(0);
+ }
+ btAlignedObjectArray<Node> m_nodes;
+ };
+struct P15 : btDbvt::ICollide
+ {
+ struct Node
+ {
+ const btDbvtNode* leaf;
+ btScalar depth;
+ };
+ void Process(const btDbvtNode* leaf)
+ {
+ Node n;
+ n.leaf = leaf;
+ n.depth = dot(leaf->volume.Center(),m_axis);
+ }
+ static int sortfnc(const Node& a,const Node& b)
+ {
+ if(a.depth<b.depth) return(+1);
+ if(a.depth>b.depth) return(-1);
+ return(0);
+ }
+ btAlignedObjectArray<Node> m_nodes;
+ btVector3 m_axis;
+ };
+static btScalar RandUnit()
+ {
+ return(rand()/(btScalar)RAND_MAX);
+ }
+static btVector3 RandVector3()
+ {
+ return(btVector3(RandUnit(),RandUnit(),RandUnit()));
+ }
+static btVector3 RandVector3(btScalar cs)
+ {
+ return(RandVector3()*cs-btVector3(cs,cs,cs)/2);
+ }
+static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es)
+ {
+ return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es));
+ }
+static btTransform RandTransform(btScalar cs)
+ {
+ btTransform t;
+ t.setOrigin(RandVector3(cs));
+ t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized());
+ return(t);
+ }
+static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt)
+ {
+ dbvt.clear();
+ for(int i=0;i<leaves;++i)
+ {
+ dbvt.insert(RandVolume(cs,eb,es),0);
+ }
+ }
+};
+
+void btDbvt::benchmark()
+{
+static const btScalar cfgVolumeCenterScale = 100;
+static const btScalar cfgVolumeExentsBase = 1;
+static const btScalar cfgVolumeExentsScale = 4;
+static const int cfgLeaves = 8192;
+static const bool cfgEnable = true;
+
+//[1] btDbvtVolume intersections
+bool cfgBenchmark1_Enable = cfgEnable;
+static const int cfgBenchmark1_Iterations = 8;
+static const int cfgBenchmark1_Reference = 3537;
+//[2] btDbvtVolume merges
+bool cfgBenchmark2_Enable = cfgEnable;
+static const int cfgBenchmark2_Iterations = 4;
+static const int cfgBenchmark2_Reference = 1945;
+//[3] btDbvt::collideTT
+bool cfgBenchmark3_Enable = cfgEnable;
+static const int cfgBenchmark3_Iterations = 512;
+static const int cfgBenchmark3_Reference = 6646;
+//[4] btDbvt::collideTT self
+bool cfgBenchmark4_Enable = cfgEnable;
+static const int cfgBenchmark4_Iterations = 512;
+static const int cfgBenchmark4_Reference = 3389;
+//[5] btDbvt::collideTT xform
+bool cfgBenchmark5_Enable = cfgEnable;
+static const int cfgBenchmark5_Iterations = 512;
+static const btScalar cfgBenchmark5_OffsetScale = 2;
+static const int cfgBenchmark5_Reference = 7505;
+//[6] btDbvt::collideTT xform,self
+bool cfgBenchmark6_Enable = cfgEnable;
+static const int cfgBenchmark6_Iterations = 512;
+static const btScalar cfgBenchmark6_OffsetScale = 2;
+static const int cfgBenchmark6_Reference = 7480;
+//[7] btDbvt::collideRAY
+bool cfgBenchmark7_Enable = cfgEnable;
+static const int cfgBenchmark7_Passes = 32;
+static const int cfgBenchmark7_Iterations = 65536;
+static const int cfgBenchmark7_Reference = 6307;
+//[8] insert/remove
+bool cfgBenchmark8_Enable = cfgEnable;
+static const int cfgBenchmark8_Passes = 32;
+static const int cfgBenchmark8_Iterations = 65536;
+static const int cfgBenchmark8_Reference = 2105;
+//[9] updates (teleport)
+bool cfgBenchmark9_Enable = cfgEnable;
+static const int cfgBenchmark9_Passes = 32;
+static const int cfgBenchmark9_Iterations = 65536;
+static const int cfgBenchmark9_Reference = 1943;
+//[10] updates (jitter)
+bool cfgBenchmark10_Enable = cfgEnable;
+static const btScalar cfgBenchmark10_Scale = cfgVolumeCenterScale/10000;
+static const int cfgBenchmark10_Passes = 32;
+static const int cfgBenchmark10_Iterations = 65536;
+static const int cfgBenchmark10_Reference = 1301;
+//[11] optimize (incremental)
+bool cfgBenchmark11_Enable = cfgEnable;
+static const int cfgBenchmark11_Passes = 64;
+static const int cfgBenchmark11_Iterations = 65536;
+static const int cfgBenchmark11_Reference = 2510;
+//[12] btDbvtVolume notequal
+bool cfgBenchmark12_Enable = cfgEnable;
+static const int cfgBenchmark12_Iterations = 32;
+static const int cfgBenchmark12_Reference = 3677;
+//[13] culling(OCL+fullsort)
+bool cfgBenchmark13_Enable = cfgEnable;
+static const int cfgBenchmark13_Iterations = 1024;
+static const int cfgBenchmark13_Reference = 2231;
+//[14] culling(OCL+qsort)
+bool cfgBenchmark14_Enable = cfgEnable;
+static const int cfgBenchmark14_Iterations = 8192;
+static const int cfgBenchmark14_Reference = 3500;
+//[15] culling(KDOP+qsort)
+bool cfgBenchmark15_Enable = cfgEnable;
+static const int cfgBenchmark15_Iterations = 8192;
+static const int cfgBenchmark15_Reference = 1151;
+//[16] insert/remove batch
+bool cfgBenchmark16_Enable = cfgEnable;
+static const int cfgBenchmark16_BatchCount = 256;
+static const int cfgBenchmark16_Passes = 16384;
+static const int cfgBenchmark16_Reference = 5138;
+//[17] proximity
+bool cfgBenchmark17_Enable = cfgEnable;
+static const int cfgBenchmark17_Iterations = 8;
+static const int cfgBenchmark17_Reference = 2842;
+//[18] select
+bool cfgBenchmark18_Enable = cfgEnable;
+static const int cfgBenchmark18_Iterations = 4;
+static const int cfgBenchmark18_Reference = 3390;
+
+btClock wallclock;
+printf("Benchmarking dbvt...\r\n");
+printf("\tWorld scale: %f\r\n",cfgVolumeCenterScale);
+printf("\tExtents base: %f\r\n",cfgVolumeExentsBase);
+printf("\tExtents range: %f\r\n",cfgVolumeExentsScale);
+printf("\tLeaves: %u\r\n",cfgLeaves);
+printf("\tsizeof(btDbvtVolume): %u bytes\r\n",sizeof(btDbvtVolume));
+printf("\tsizeof(btDbvtNode): %u bytes\r\n",sizeof(btDbvtNode));
+if(cfgBenchmark1_Enable)
+ {// Benchmark 1
+ srand(380843);
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<bool> results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ printf("[1] btDbvtVolume intersections: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark1_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ results[k]=Intersect(volumes[j],volumes[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark1_Reference)*100/time);
+ }
+if(cfgBenchmark2_Enable)
+ {// Benchmark 2
+ srand(380843);
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<btDbvtVolume> results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ printf("[2] btDbvtVolume merges: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark2_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ Merge(volumes[j],volumes[k],results[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark2_Reference)*100/time);
+ }
+if(cfgBenchmark3_Enable)
+ {// Benchmark 3
+ srand(380843);
+ btDbvt dbvt[2];
+ btDbvtBenchmark::NilPolicy policy;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+ dbvt[0].optimizeTopDown();
+ dbvt[1].optimizeTopDown();
+ printf("[3] btDbvt::collideTT: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark3_Iterations;++i)
+ {
+ btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark3_Reference)*100/time);
+ }
+if(cfgBenchmark4_Enable)
+ {// Benchmark 4
+ srand(380843);
+ btDbvt dbvt;
+ btDbvtBenchmark::NilPolicy policy;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[4] btDbvt::collideTT self: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark4_Iterations;++i)
+ {
+ btDbvt::collideTT(dbvt.m_root,dbvt.m_root,policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark4_Reference)*100/time);
+ }
+if(cfgBenchmark5_Enable)
+ {// Benchmark 5
+ srand(380843);
+ btDbvt dbvt[2];
+ btAlignedObjectArray<btTransform> transforms;
+ btDbvtBenchmark::NilPolicy policy;
+ transforms.resize(cfgBenchmark5_Iterations);
+ for(int i=0;i<transforms.size();++i)
+ {
+ transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark5_OffsetScale);
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+ dbvt[0].optimizeTopDown();
+ dbvt[1].optimizeTopDown();
+ printf("[5] btDbvt::collideTT xform: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark5_Iterations;++i)
+ {
+ btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,transforms[i],policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark5_Reference)*100/time);
+ }
+if(cfgBenchmark6_Enable)
+ {// Benchmark 6
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btTransform> transforms;
+ btDbvtBenchmark::NilPolicy policy;
+ transforms.resize(cfgBenchmark6_Iterations);
+ for(int i=0;i<transforms.size();++i)
+ {
+ transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark6_OffsetScale);
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[6] btDbvt::collideTT xform,self: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark6_Iterations;++i)
+ {
+ btDbvt::collideTT(dbvt.m_root,dbvt.m_root,transforms[i],policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark6_Reference)*100/time);
+ }
+if(cfgBenchmark7_Enable)
+ {// Benchmark 7
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> rayorg;
+ btAlignedObjectArray<btVector3> raydir;
+ btDbvtBenchmark::NilPolicy policy;
+ rayorg.resize(cfgBenchmark7_Iterations);
+ raydir.resize(cfgBenchmark7_Iterations);
+ for(int i=0;i<rayorg.size();++i)
+ {
+ rayorg[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+ raydir[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[7] btDbvt::collideRAY: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark7_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark7_Iterations;++j)
+ {
+ btDbvt::collideRAY(dbvt.m_root,rayorg[j],raydir[j],policy);
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ unsigned rays=cfgBenchmark7_Passes*cfgBenchmark7_Iterations;
+ printf("%u ms (%i%%),(%u r/s)\r\n",time,(time-cfgBenchmark7_Reference)*100/time,(rays*1000)/time);
+ }
+if(cfgBenchmark8_Enable)
+ {// Benchmark 8
+ srand(380843);
+ btDbvt dbvt;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[8] insert/remove: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark8_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark8_Iterations;++j)
+ {
+ dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int ir=cfgBenchmark8_Passes*cfgBenchmark8_Iterations;
+ printf("%u ms (%i%%),(%u ir/s)\r\n",time,(time-cfgBenchmark8_Reference)*100/time,ir*1000/time);
+ }
+if(cfgBenchmark9_Enable)
+ {// Benchmark 9
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<const btDbvtNode*> leaves;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ dbvt.extractLeaves(dbvt.m_root,leaves);
+ printf("[9] updates (teleport): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark9_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark9_Iterations;++j)
+ {
+ dbvt.update(const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]),
+ btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
+ }
+if(cfgBenchmark10_Enable)
+ {// Benchmark 10
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<const btDbvtNode*> leaves;
+ btAlignedObjectArray<btVector3> vectors;
+ vectors.resize(cfgBenchmark10_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1))*cfgBenchmark10_Scale;
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ dbvt.extractLeaves(dbvt.m_root,leaves);
+ printf("[10] updates (jitter): ");
+ wallclock.reset();
+
+ for(int i=0;i<cfgBenchmark10_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark10_Iterations;++j)
+ {
+ const btVector3& d=vectors[j];
+ btDbvtNode* l=const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]);
+ btDbvtVolume v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
+ dbvt.update(l,v);
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
+ }
+if(cfgBenchmark11_Enable)
+ {// Benchmark 11
+ srand(380843);
+ btDbvt dbvt;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[11] optimize (incremental): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark11_Passes;++i)
+ {
+ dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int op=cfgBenchmark11_Passes*cfgBenchmark11_Iterations;
+ printf("%u ms (%i%%),(%u o/s)\r\n",time,(time-cfgBenchmark11_Reference)*100/time,op/time*1000);
+ }
+if(cfgBenchmark12_Enable)
+ {// Benchmark 12
+ srand(380843);
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<bool> results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ printf("[12] btDbvtVolume notequal: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark12_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ results[k]=NotEqual(volumes[j],volumes[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark12_Reference)*100/time);
+ }
+if(cfgBenchmark13_Enable)
+ {// Benchmark 13
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> vectors;
+ btDbvtBenchmark::NilPolicy policy;
+ vectors.resize(cfgBenchmark13_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[13] culling(OCL+fullsort): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark13_Iterations;++i)
+ {
+ static const btScalar offset=0;
+ policy.m_depth=-SIMD_INFINITY;
+ dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int t=cfgBenchmark13_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark13_Reference)*100/time,(t*1000)/time);
+ }
+if(cfgBenchmark14_Enable)
+ {// Benchmark 14
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> vectors;
+ btDbvtBenchmark::P14 policy;
+ vectors.resize(cfgBenchmark14_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ policy.m_nodes.reserve(cfgLeaves);
+ printf("[14] culling(OCL+qsort): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark14_Iterations;++i)
+ {
+ static const btScalar offset=0;
+ policy.m_nodes.resize(0);
+ dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy,false);
+ policy.m_nodes.quickSort(btDbvtBenchmark::P14::sortfnc);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int t=cfgBenchmark14_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark14_Reference)*100/time,(t*1000)/time);
+ }
+if(cfgBenchmark15_Enable)
+ {// Benchmark 15
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btVector3> vectors;
+ btDbvtBenchmark::P15 policy;
+ vectors.resize(cfgBenchmark15_Iterations);
+ for(int i=0;i<vectors.size();++i)
+ {
+ vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+ }
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ policy.m_nodes.reserve(cfgLeaves);
+ printf("[15] culling(KDOP+qsort): ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark15_Iterations;++i)
+ {
+ static const btScalar offset=0;
+ policy.m_nodes.resize(0);
+ policy.m_axis=vectors[i];
+ dbvt.collideKDOP(dbvt.m_root,&vectors[i],&offset,1,policy);
+ policy.m_nodes.quickSort(btDbvtBenchmark::P15::sortfnc);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int t=cfgBenchmark15_Iterations;
+ printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark15_Reference)*100/time,(t*1000)/time);
+ }
+if(cfgBenchmark16_Enable)
+ {// Benchmark 16
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray<btDbvtNode*> batch;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ batch.reserve(cfgBenchmark16_BatchCount);
+ printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark16_Passes;++i)
+ {
+ for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+ {
+ batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+ }
+ for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+ {
+ dbvt.remove(batch[j]);
+ }
+ batch.resize(0);
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int ir=cfgBenchmark16_Passes*cfgBenchmark16_BatchCount;
+ printf("%u ms (%i%%),(%u bir/s)\r\n",time,(time-cfgBenchmark16_Reference)*100/time,int(ir*1000.0/time));
+ }
+if(cfgBenchmark17_Enable)
+ {// Benchmark 17
+ srand(380843);
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<btScalar> results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ printf("[17] btDbvtVolume proximity: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark17_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ results[k]=Proximity(volumes[j],volumes[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark17_Reference)*100/time);
+ }
+if(cfgBenchmark18_Enable)
+ {// Benchmark 18
+ srand(380843);
+ btAlignedObjectArray<btDbvtVolume> volumes;
+ btAlignedObjectArray<int> results;
+ btAlignedObjectArray<int> indices;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ indices.resize(cfgLeaves);
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ indices[i]=i;
+ volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+ }
+ for(int i=0;i<cfgLeaves;++i)
+ {
+ btSwap(indices[i],indices[rand()%cfgLeaves]);
+ }
+ printf("[18] btDbvtVolume select: ");
+ wallclock.reset();
+ for(int i=0;i<cfgBenchmark18_Iterations;++i)
+ {
+ for(int j=0;j<cfgLeaves;++j)
+ {
+ for(int k=0;k<cfgLeaves;++k)
+ {
+ const int idx=indices[k];
+ results[idx]=Select(volumes[idx],volumes[j],volumes[k]);
+ }
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark18_Reference)*100/time);
+ }
+printf("\r\n\r\n");
+}
+#endif
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h
new file mode 100644
index 00000000000..10f94627c37
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h
@@ -0,0 +1,1101 @@
+/*
+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.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#ifndef BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
+#define BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+
+//
+// Compile time configuration
+//
+
+
+// Implementation profiles
+#define DBVT_IMPL_GENERIC 0 // Generic implementation
+#define DBVT_IMPL_SSE 1 // SSE
+
+// Template implementation of ICollide
+#ifdef WIN32_AVOID_WHEN_EMBEDDED_INSIDE_BLENDER
+ #if (defined (_MSC_VER) && _MSC_VER >= 1400)
+ #define DBVT_USE_TEMPLATE 1
+ #else
+ #define DBVT_USE_TEMPLATE 0
+#endif
+#else
+#define DBVT_USE_TEMPLATE 0
+#endif
+
+// Using memmov for collideOCL
+#define DBVT_USE_MEMMOVE 1
+
+// Enable benchmarking code
+#define DBVT_ENABLE_BENCHMARK 0
+
+// Inlining
+#define DBVT_INLINE SIMD_FORCE_INLINE
+// Align
+#ifdef WIN32
+#define DBVT_ALIGN __declspec(align(16))
+#else
+#define DBVT_ALIGN
+#endif
+
+// Specific methods implementation
+#ifdef WIN32_AVOID_WHEN_EMBEDDED_INSIDE_BLENDER
+#define DBVT_PROXIMITY_IMPL DBVT_IMPL_SSE
+#define DBVT_SELECT_IMPL DBVT_IMPL_SSE
+#define DBVT_MERGE_IMPL DBVT_IMPL_SSE
+#else
+#define DBVT_PROXIMITY_IMPL DBVT_IMPL_GENERIC
+#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC
+#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC
+#endif
+
+//
+// Auto config and checks
+//
+
+#if DBVT_USE_TEMPLATE
+#define DBVT_VIRTUAL
+#define DBVT_VIRTUAL_DTOR(a)
+#define DBVT_PREFIX template <typename T>
+#define DBVT_IPOLICY T& policy
+#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)0;
+#else
+#define DBVT_VIRTUAL_DTOR(a) virtual ~a() {}
+#define DBVT_VIRTUAL virtual
+#define DBVT_PREFIX
+#define DBVT_IPOLICY ICollide& policy
+#define DBVT_CHECKTYPE
+#endif
+
+#if DBVT_USE_MEMMOVE
+#ifndef __CELLOS_LV2__
+#include <memory.h>
+#endif
+#include <string.h>
+#endif
+
+#ifndef DBVT_USE_TEMPLATE
+#error "DBVT_USE_TEMPLATE undefined"
+#endif
+
+#ifndef DBVT_USE_MEMMOVE
+#error "DBVT_USE_MEMMOVE undefined"
+#endif
+
+#ifndef DBVT_ENABLE_BENCHMARK
+#error "DBVT_ENABLE_BENCHMARK undefined"
+#endif
+
+#ifndef DBVT_PROXIMITY_IMPL
+#error "DBVT_PROXIMITY_IMPL undefined"
+#endif
+
+#ifndef DBVT_SELECT_IMPL
+#error "DBVT_SELECT_IMPL undefined"
+#endif
+
+#ifndef DBVT_MERGE_IMPL
+#error "DBVT_MERGE_IMPL undefined"
+#endif
+
+//
+// Defaults volumes
+//
+
+/* btDbvtAabbMm */
+struct btDbvtAabbMm
+{
+DBVT_INLINE btVector3 Center() const { return((mi+mx)/2); }
+DBVT_INLINE btVector3 Lengths() const { return(mx-mi); }
+DBVT_INLINE btVector3 Extents() const { return((mx-mi)/2); }
+DBVT_INLINE const btVector3& Mins() const { return(mi); }
+DBVT_INLINE const btVector3& Maxs() const { return(mx); }
+static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e);
+static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r);
+static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx);
+static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n);
+static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n);
+DBVT_INLINE void Expand(const btVector3 e);
+DBVT_INLINE void SignedExpand(const btVector3 e);
+DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const;
+DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const;
+DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const;
+DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ const btTransform& xform);
+DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& b);
+DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& org,
+ const btVector3& invdir,
+ const unsigned* signs);
+DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+DBVT_INLINE friend int Select( const btDbvtAabbMm& o,
+ const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+DBVT_INLINE friend void Merge( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ btDbvtAabbMm& r);
+DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+private:
+DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const;
+private:
+btVector3 mi,mx;
+};
+
+// Types
+typedef btDbvtAabbMm btDbvtVolume;
+
+/* btDbvtNode */
+struct btDbvtNode
+{
+ btDbvtVolume volume;
+ btDbvtNode* parent;
+ bool isleaf() const { return(childs[1]==0); }
+ bool isinternal() const { return(!isleaf()); }
+ union {
+ btDbvtNode* childs[2];
+ void* data;
+ };
+};
+
+///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
+///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes.
+///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
+struct btDbvt
+ {
+
+
+ /* Stack element */
+ struct sStkNN
+ {
+ const btDbvtNode* a;
+ const btDbvtNode* b;
+ sStkNN() {}
+ sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {}
+ };
+ struct sStkNP
+ {
+ const btDbvtNode* node;
+ int mask;
+ sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {}
+ };
+ struct sStkNPS
+ {
+ const btDbvtNode* node;
+ int mask;
+ btScalar value;
+ sStkNPS() {}
+ sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {}
+ };
+ struct sStkCLN
+ {
+ const btDbvtNode* node;
+ btDbvtNode* parent;
+ sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {}
+ };
+ // Policies/Interfaces
+
+ /* ICollide */
+ struct ICollide
+ {
+ DBVT_VIRTUAL_DTOR(ICollide)
+ DBVT_VIRTUAL void Process(const btDbvtNode*,const btDbvtNode*) {}
+ DBVT_VIRTUAL void Process(const btDbvtNode*) {}
+ DBVT_VIRTUAL void Process(const btDbvtNode* n,btScalar) { Process(n); }
+ DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return(true); }
+ DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return(true); }
+ };
+ /* IWriter */
+ struct IWriter
+ {
+ virtual ~IWriter() {}
+ virtual void Prepare(const btDbvtNode* root,int numnodes)=0;
+ virtual void WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0;
+ virtual void WriteLeaf(const btDbvtNode*,int index,int parent)=0;
+ };
+ /* IClone */
+ struct IClone
+ {
+ virtual ~IClone() {}
+ virtual void CloneLeaf(btDbvtNode*) {}
+ };
+
+ // Constants
+ enum {
+ SIMPLE_STACKSIZE = 64,
+ DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2
+ };
+
+ // Fields
+ btDbvtNode* m_root;
+ btDbvtNode* m_free;
+ int m_lkhd;
+ int m_leaves;
+ unsigned m_opath;
+ // Methods
+ btDbvt();
+ ~btDbvt();
+ void clear();
+ bool empty() const { return(0==m_root); }
+ void optimizeBottomUp();
+ void optimizeTopDown(int bu_treshold=128);
+ void optimizeIncremental(int passes);
+ btDbvtNode* insert(const btDbvtVolume& box,void* data);
+ void update(btDbvtNode* leaf,int lookahead=-1);
+ void update(btDbvtNode* leaf,const btDbvtVolume& volume);
+ bool update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin);
+ bool update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity);
+ bool update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin);
+ void remove(btDbvtNode* leaf);
+ void write(IWriter* iwriter) const;
+ void clone(btDbvt& dest,IClone* iclone=0) const;
+ static int maxdepth(const btDbvtNode* node);
+ static int countLeaves(const btDbvtNode* node);
+ static void extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves);
+ #if DBVT_ENABLE_BENCHMARK
+ static void benchmark();
+ #else
+ static void benchmark(){}
+ #endif
+ // DBVT_IPOLICY must support ICollide policy/interface
+ DBVT_PREFIX
+ static void enumNodes( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void enumLeaves( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ const btTransform& xform,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideTT( const btDbvtNode* root0,
+ const btTransform& xform0,
+ const btDbvtNode* root1,
+ const btTransform& xform1,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideTV( const btDbvtNode* root,
+ const btDbvtVolume& volume,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideRAY( const btDbvtNode* root,
+ const btVector3& origin,
+ const btVector3& direction,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideKDOP(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ int count,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideOCL( const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ const btVector3& sortaxis,
+ int count,
+ DBVT_IPOLICY,
+ bool fullsort=true);
+ DBVT_PREFIX
+ static void collideTU( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ // Helpers
+ static DBVT_INLINE int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h)
+ {
+ int m=0;
+ while(l<h)
+ {
+ m=(l+h)>>1;
+ if(a[i[m]].value>=v) l=m+1; else h=m;
+ }
+ return(h);
+ }
+ static DBVT_INLINE int allocate( btAlignedObjectArray<int>& ifree,
+ btAlignedObjectArray<sStkNPS>& stock,
+ const sStkNPS& value)
+ {
+ int i;
+ if(ifree.size()>0)
+ { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; }
+ else
+ { i=stock.size();stock.push_back(value); }
+ return(i);
+ }
+ //
+ private:
+ btDbvt(const btDbvt&) {}
+ };
+
+//
+// Inline's
+//
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e)
+{
+btDbvtAabbMm box;
+box.mi=c-e;box.mx=c+e;
+return(box);
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r)
+{
+return(FromCE(c,btVector3(r,r,r)));
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx)
+{
+btDbvtAabbMm box;
+box.mi=mi;box.mx=mx;
+return(box);
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n)
+{
+btDbvtAabbMm box;
+box.mi=box.mx=pts[0];
+for(int i=1;i<n;++i)
+ {
+ box.mi.setMin(pts[i]);
+ box.mx.setMax(pts[i]);
+ }
+return(box);
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3** ppts,int n)
+{
+btDbvtAabbMm box;
+box.mi=box.mx=*ppts[0];
+for(int i=1;i<n;++i)
+ {
+ box.mi.setMin(*ppts[i]);
+ box.mx.setMax(*ppts[i]);
+ }
+return(box);
+}
+
+//
+DBVT_INLINE void btDbvtAabbMm::Expand(const btVector3 e)
+{
+mi-=e;mx+=e;
+}
+
+//
+DBVT_INLINE void btDbvtAabbMm::SignedExpand(const btVector3 e)
+{
+if(e.x()>0) mx.setX(mx.x()+e.x()); else mi.setX(mi.x()+e.x());
+if(e.y()>0) mx.setY(mx.y()+e.y()); else mi.setY(mi.y()+e.y());
+if(e.z()>0) mx.setZ(mx.z()+e.z()); else mi.setZ(mi.z()+e.z());
+}
+
+//
+DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
+{
+return( (mi.x()<=a.mi.x())&&
+ (mi.y()<=a.mi.y())&&
+ (mi.z()<=a.mi.z())&&
+ (mx.x()>=a.mx.x())&&
+ (mx.y()>=a.mx.y())&&
+ (mx.z()>=a.mx.z()));
+}
+
+//
+DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const
+{
+btVector3 pi,px;
+switch(s)
+ {
+ case (0+0+0): px=btVector3(mi.x(),mi.y(),mi.z());
+ pi=btVector3(mx.x(),mx.y(),mx.z());break;
+ case (1+0+0): px=btVector3(mx.x(),mi.y(),mi.z());
+ pi=btVector3(mi.x(),mx.y(),mx.z());break;
+ case (0+2+0): px=btVector3(mi.x(),mx.y(),mi.z());
+ pi=btVector3(mx.x(),mi.y(),mx.z());break;
+ case (1+2+0): px=btVector3(mx.x(),mx.y(),mi.z());
+ pi=btVector3(mi.x(),mi.y(),mx.z());break;
+ case (0+0+4): px=btVector3(mi.x(),mi.y(),mx.z());
+ pi=btVector3(mx.x(),mx.y(),mi.z());break;
+ case (1+0+4): px=btVector3(mx.x(),mi.y(),mx.z());
+ pi=btVector3(mi.x(),mx.y(),mi.z());break;
+ case (0+2+4): px=btVector3(mi.x(),mx.y(),mx.z());
+ pi=btVector3(mx.x(),mi.y(),mi.z());break;
+ case (1+2+4): px=btVector3(mx.x(),mx.y(),mx.z());
+ pi=btVector3(mi.x(),mi.y(),mi.z());break;
+ }
+if((dot(n,px)+o)<0) return(-1);
+if((dot(n,pi)+o)>=0) return(+1);
+return(0);
+}
+
+//
+DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const
+{
+const btVector3* b[]={&mx,&mi};
+const btVector3 p( b[(signs>>0)&1]->x(),
+ b[(signs>>1)&1]->y(),
+ b[(signs>>2)&1]->z());
+return(dot(p,v));
+}
+
+//
+DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const
+{
+for(int i=0;i<3;++i)
+ {
+ if(d[i]<0)
+ { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; }
+ else
+ { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; }
+ }
+}
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+return( (a.mi.x()<=b.mx.x())&&
+ (a.mx.x()>=b.mi.x())&&
+ (a.mi.y()<=b.mx.y())&&
+ (a.mx.y()>=b.mi.y())&&
+ (a.mi.z()<=b.mx.z())&&
+ (a.mx.z()>=b.mi.z()));
+}
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ const btTransform& xform)
+{
+const btVector3 d0=xform*b.Center()-a.Center();
+const btVector3 d1=d0*xform.getBasis();
+btScalar s0[2]={0,0};
+btScalar s1[2]={dot(xform.getOrigin(),d0),s1[0]};
+a.AddSpan(d0,s0[0],s0[1]);
+b.AddSpan(d1,s1[0],s1[1]);
+if(s0[0]>(s1[1])) return(false);
+if(s0[1]<(s1[0])) return(false);
+return(true);
+}
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& b)
+{
+return( (b.x()>=a.mi.x())&&
+ (b.y()>=a.mi.y())&&
+ (b.z()>=a.mi.z())&&
+ (b.x()<=a.mx.x())&&
+ (b.y()<=a.mx.y())&&
+ (b.z()<=a.mx.z()));
+}
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& org,
+ const btVector3& invdir,
+ const unsigned* signs)
+{
+#if 0
+const btVector3 b0((a.mi-org)*invdir);
+const btVector3 b1((a.mx-org)*invdir);
+const btVector3 tmin(btMin(b0[0],b1[0]),btMin(b0[1],b1[1]),btMin(b0[2],b1[2]));
+const btVector3 tmax(btMax(b0[0],b1[0]),btMax(b0[1],b1[1]),btMax(b0[2],b1[2]));
+const btScalar tin=btMax(tmin[0],btMax(tmin[1],tmin[2]));
+const btScalar tout=btMin(tmax[0],btMin(tmax[1],tmax[2]));
+return(tin<tout);
+#else
+const btVector3* bounds[2]={&a.mi,&a.mx};
+btScalar txmin=(bounds[ signs[0]]->x()-org[0])*invdir[0];
+btScalar txmax=(bounds[1-signs[0]]->x()-org[0])*invdir[0];
+const btScalar tymin=(bounds[ signs[1]]->y()-org[1])*invdir[1];
+const btScalar tymax=(bounds[1-signs[1]]->y()-org[1])*invdir[1];
+if((txmin>tymax)||(tymin>txmax)) return(false);
+if(tymin>txmin) txmin=tymin;
+if(tymax<txmax) txmax=tymax;
+const btScalar tzmin=(bounds[ signs[2]]->z()-org[2])*invdir[2];
+const btScalar tzmax=(bounds[1-signs[2]]->z()-org[2])*invdir[2];
+if((txmin>tzmax)||(tzmin>txmax)) return(false);
+if(tzmin>txmin) txmin=tzmin;
+if(tzmax<txmax) txmax=tzmax;
+return(txmax>0);
+#endif
+}
+
+//
+DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+#if DBVT_PROXIMITY_IMPL == DBVT_IMPL_SSE
+DBVT_ALIGN btScalar r[1];
+static DBVT_ALIGN const unsigned __int32 mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+__asm
+ {
+ mov eax,a
+ mov ecx,b
+ movaps xmm0,[eax]
+ movaps xmm2,[ecx]
+ movaps xmm1,[eax+16]
+ movaps xmm3,[ecx+16]
+ addps xmm0,xmm1
+ addps xmm2,xmm3
+ subps xmm0,xmm2
+ andps xmm0,mask
+ movhlps xmm1,xmm0
+ addps xmm0,xmm1
+ pshufd xmm1,xmm0,1
+ addss xmm0,xmm1
+ movss r,xmm0
+ }
+return(r[0]);
+#else
+const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx);
+return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z()));
+#endif
+}
+
+//
+DBVT_INLINE int Select( const btDbvtAabbMm& o,
+ const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE
+DBVT_ALIGN __int32 r[1];
+static DBVT_ALIGN const unsigned __int32 mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+__asm
+ {
+ mov eax,o
+ mov ecx,a
+ mov edx,b
+ movaps xmm0,[eax]
+ movaps xmm5,mask
+ addps xmm0,[eax+16]
+ movaps xmm1,[ecx]
+ movaps xmm2,[edx]
+ addps xmm1,[ecx+16]
+ addps xmm2,[edx+16]
+ subps xmm1,xmm0
+ subps xmm2,xmm0
+ andps xmm1,xmm5
+ andps xmm2,xmm5
+ movhlps xmm3,xmm1
+ movhlps xmm4,xmm2
+ addps xmm1,xmm3
+ addps xmm2,xmm4
+ pshufd xmm3,xmm1,1
+ pshufd xmm4,xmm2,1
+ addss xmm1,xmm3
+ addss xmm2,xmm4
+ cmpless xmm2,xmm1
+ movss r,xmm2
+ }
+return(r[0]&1);
+#else
+return(Proximity(o,a)<Proximity(o,b)?0:1);
+#endif
+}
+
+//
+DBVT_INLINE void Merge( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ btDbvtAabbMm& r)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+__asm
+ {
+ mov eax,a
+ mov edx,b
+ mov ecx,r
+ movaps xmm0,[eax+0]
+ movaps xmm1,[edx+0]
+ movaps xmm2,[eax+16]
+ movaps xmm3,[edx+16]
+ minps xmm0,xmm1
+ maxps xmm2,xmm3
+ movaps [ecx+0],xmm0
+ movaps [ecx+16],xmm2
+ }
+#else
+for(int i=0;i<3;++i)
+ {
+ if(a.mi[i]<b.mi[i]) r.mi[i]=a.mi[i]; else r.mi[i]=b.mi[i];
+ if(a.mx[i]>b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i];
+ }
+#endif
+}
+
+//
+DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+return( (a.mi.x()!=b.mi.x())||
+ (a.mi.y()!=b.mi.y())||
+ (a.mi.z()!=b.mi.z())||
+ (a.mx.x()!=b.mx.x())||
+ (a.mx.y()!=b.mx.y())||
+ (a.mx.z()!=b.mx.z()));
+}
+
+//
+// Inline's
+//
+
+//
+DBVT_PREFIX
+inline void btDbvt::enumNodes( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+policy.Process(root);
+if(root->isinternal())
+ {
+ enumNodes(root->childs[0],policy);
+ enumNodes(root->childs[1],policy);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::enumLeaves( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root->isinternal())
+ {
+ enumLeaves(root->childs[0],policy);
+ enumLeaves(root->childs[1],policy);
+ }
+ else
+ {
+ policy.Process(root);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root0&&root1)
+ {
+ btAlignedObjectArray<sStkNN> stack;
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-4;
+ stack.resize(DOUBLE_STACKSIZE);
+ stack[0]=sStkNN(root0,root1);
+ do {
+ sStkNN p=stack[--depth];
+ if(depth>treshold)
+ {
+ stack.resize(stack.size()*2);
+ treshold=stack.size()-4;
+ }
+ if(p.a==p.b)
+ {
+ if(p.a->isinternal())
+ {
+ stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
+ stack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
+ stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+ }
+ }
+ else if(Intersect(p.a->volume,p.b->volume))
+ {
+ if(p.a->isinternal())
+ {
+ if(p.b->isinternal())
+ {
+ stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+ }
+ else
+ {
+ stack[depth++]=sStkNN(p.a->childs[0],p.b);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b);
+ }
+ }
+ else
+ {
+ if(p.b->isinternal())
+ {
+ stack[depth++]=sStkNN(p.a,p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a,p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a,p.b);
+ }
+ }
+ }
+ } while(depth);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ const btTransform& xform,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root0&&root1)
+ {
+ btAlignedObjectArray<sStkNN> stack;
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-4;
+ stack.resize(DOUBLE_STACKSIZE);
+ stack[0]=sStkNN(root0,root1);
+ do {
+ sStkNN p=stack[--depth];
+ if(Intersect(p.a->volume,p.b->volume,xform))
+ {
+ if(depth>treshold)
+ {
+ stack.resize(stack.size()*2);
+ treshold=stack.size()-4;
+ }
+ if(p.a->isinternal())
+ {
+ if(p.b->isinternal())
+ {
+ stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+ }
+ else
+ {
+ stack[depth++]=sStkNN(p.a->childs[0],p.b);
+ stack[depth++]=sStkNN(p.a->childs[1],p.b);
+ }
+ }
+ else
+ {
+ if(p.b->isinternal())
+ {
+ stack[depth++]=sStkNN(p.a,p.b->childs[0]);
+ stack[depth++]=sStkNN(p.a,p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a,p.b);
+ }
+ }
+ }
+ } while(depth);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTT( const btDbvtNode* root0,
+ const btTransform& xform0,
+ const btDbvtNode* root1,
+ const btTransform& xform1,
+ DBVT_IPOLICY)
+{
+const btTransform xform=xform0.inverse()*xform1;
+collideTT(root0,root1,xform,policy);
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTV( const btDbvtNode* root,
+ const btDbvtVolume& volume,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+ {
+ btAlignedObjectArray<const btDbvtNode*> stack;
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const btDbvtNode* n=stack[stack.size()-1];
+ stack.pop_back();
+ if(Intersect(n->volume,volume))
+ {
+ if(n->isinternal())
+ {
+ stack.push_back(n->childs[0]);
+ stack.push_back(n->childs[1]);
+ }
+ else
+ {
+ policy.Process(n);
+ }
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideRAY( const btDbvtNode* root,
+ const btVector3& origin,
+ const btVector3& direction,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+ {
+ const btVector3 normal=direction.normalized();
+ const btVector3 invdir( 1/normal.x(),
+ 1/normal.y(),
+ 1/normal.z());
+ const unsigned signs[]={ direction.x()<0,
+ direction.y()<0,
+ direction.z()<0};
+ btAlignedObjectArray<const btDbvtNode*> stack;
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const btDbvtNode* node=stack[stack.size()-1];
+ stack.pop_back();
+ if(Intersect(node->volume,origin,invdir,signs))
+ {
+ if(node->isinternal())
+ {
+ stack.push_back(node->childs[0]);
+ stack.push_back(node->childs[1]);
+ }
+ else
+ {
+ policy.Process(node);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideKDOP(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ int count,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+ {
+ const int inside=(1<<count)-1;
+ btAlignedObjectArray<sStkNP> stack;
+ int signs[sizeof(unsigned)*8];
+ btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
+ for(int i=0;i<count;++i)
+ {
+ signs[i]= ((normals[i].x()>=0)?1:0)+
+ ((normals[i].y()>=0)?2:0)+
+ ((normals[i].z()>=0)?4:0);
+ }
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(sStkNP(root,0));
+ do {
+ sStkNP se=stack[stack.size()-1];
+ bool out=false;
+ stack.pop_back();
+ for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+ {
+ if(0==(se.mask&j))
+ {
+ const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+ switch(side)
+ {
+ case -1: out=true;break;
+ case +1: se.mask|=j;break;
+ }
+ }
+ }
+ if(!out)
+ {
+ if((se.mask!=inside)&&(se.node->isinternal()))
+ {
+ stack.push_back(sStkNP(se.node->childs[0],se.mask));
+ stack.push_back(sStkNP(se.node->childs[1],se.mask));
+ }
+ else
+ {
+ if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideOCL( const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ const btVector3& sortaxis,
+ int count,
+ DBVT_IPOLICY,
+ bool fsort)
+{
+DBVT_CHECKTYPE
+if(root)
+ {
+ const unsigned srtsgns=(sortaxis[0]>=0?1:0)+
+ (sortaxis[1]>=0?2:0)+
+ (sortaxis[2]>=0?4:0);
+ const int inside=(1<<count)-1;
+ btAlignedObjectArray<sStkNPS> stock;
+ btAlignedObjectArray<int> ifree;
+ btAlignedObjectArray<int> stack;
+ int signs[sizeof(unsigned)*8];
+ btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
+ for(int i=0;i<count;++i)
+ {
+ signs[i]= ((normals[i].x()>=0)?1:0)+
+ ((normals[i].y()>=0)?2:0)+
+ ((normals[i].z()>=0)?4:0);
+ }
+ stock.reserve(SIMPLE_STACKSIZE);
+ stack.reserve(SIMPLE_STACKSIZE);
+ ifree.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns))));
+ do {
+ const int id=stack[stack.size()-1];
+ sStkNPS se=stock[id];
+ stack.pop_back();ifree.push_back(id);
+ if(se.mask!=inside)
+ {
+ bool out=false;
+ for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+ {
+ if(0==(se.mask&j))
+ {
+ const int side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+ switch(side)
+ {
+ case -1: out=true;break;
+ case +1: se.mask|=j;break;
+ }
+ }
+ }
+ if(out) continue;
+ }
+ if(policy.Descent(se.node))
+ {
+ if(se.node->isinternal())
+ {
+ const btDbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]};
+ sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)),
+ sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))};
+ const int q=nes[0].value<nes[1].value?1:0;
+ int j=stack.size();
+ if(fsort&&(j>0))
+ {
+ /* Insert 0 */
+ j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size());
+ stack.push_back(0);
+ #if DBVT_USE_MEMMOVE
+ memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+ #else
+ for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+ #endif
+ stack[j]=allocate(ifree,stock,nes[q]);
+ /* Insert 1 */
+ j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size());
+ stack.push_back(0);
+ #if DBVT_USE_MEMMOVE
+ memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+ #else
+ for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+ #endif
+ stack[j]=allocate(ifree,stock,nes[1-q]);
+ }
+ else
+ {
+ stack.push_back(allocate(ifree,stock,nes[q]));
+ stack.push_back(allocate(ifree,stock,nes[1-q]));
+ }
+ }
+ else
+ {
+ policy.Process(se.node,se.value);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTU( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+DBVT_CHECKTYPE
+if(root)
+ {
+ btAlignedObjectArray<const btDbvtNode*> stack;
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const btDbvtNode* n=stack[stack.size()-1];
+ stack.pop_back();
+ if(policy.Descent(n))
+ {
+ if(n->isinternal())
+ { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
+ else
+ { policy.Process(n); }
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+// PP Cleanup
+//
+
+#undef DBVT_USE_MEMMOVE
+#undef DBVT_USE_TEMPLATE
+#undef DBVT_VIRTUAL_DTOR
+#undef DBVT_VIRTUAL
+#undef DBVT_PREFIX
+#undef DBVT_IPOLICY
+#undef DBVT_CHECKTYPE
+#undef DBVT_IMPL_GENERIC
+#undef DBVT_IMPL_FPU0x86
+#undef DBVT_IMPL_SSE
+
+#endif
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
new file mode 100644
index 00000000000..c6086f28f19
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
@@ -0,0 +1,344 @@
+/*
+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.
+*/
+///btDbvtBroadphase implementation by Nathanael Presson
+
+#include "btDbvtBroadphase.h"
+
+//
+// Profiling
+//
+
+#if DBVT_BP_PROFILE
+#include <stdio.h>
+struct ProfileScope
+ {
+ ProfileScope(btClock& clock,unsigned long& value)
+ {
+ m_clock=&clock;
+ m_value=&value;
+ m_base=clock.getTimeMicroseconds();
+ }
+ ~ProfileScope()
+ {
+ (*m_value)+=m_clock->getTimeMicroseconds()-m_base;
+ }
+ btClock* m_clock;
+ unsigned long* m_value;
+ unsigned long m_base;
+ };
+#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_)
+#else
+#define SPC(_value_)
+#endif
+
+//
+// Helpers
+//
+
+//
+template <typename T>
+static inline void listappend(T* item,T*& list)
+{
+item->links[0]=0;
+item->links[1]=list;
+if(list) list->links[0]=item;
+list=item;
+}
+
+//
+template <typename T>
+static inline void listremove(T* item,T*& list)
+{
+if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
+if(item->links[1]) item->links[1]->links[0]=item->links[0];
+}
+
+//
+template <typename T>
+static inline int listcount(T* root)
+{
+int n=0;
+while(root) { ++n;root=root->links[1]; }
+return(n);
+}
+
+//
+template <typename T>
+static inline void clear(T& value)
+{
+static const struct ZeroDummy : T {} zerodummy;
+value=zerodummy;
+}
+
+//
+// Colliders
+//
+
+/* Tree collider */
+struct btDbvtTreeCollider : btDbvt::ICollide
+{
+btDbvtBroadphase* pbp;
+ btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
+void Process(const btDbvtNode* na,const btDbvtNode* nb)
+ {
+ btDbvtProxy* pa=(btDbvtProxy*)na->data;
+ btDbvtProxy* pb=(btDbvtProxy*)nb->data;
+ #if DBVT_BP_DISCRETPAIRS
+ if(Intersect(pa->aabb,pb->aabb))
+ #endif
+ {
+ if(pa>pb) btSwap(pa,pb);
+ pbp->m_paircache->addOverlappingPair(pa,pb);
+ }
+ }
+};
+
+//
+// btDbvtBroadphase
+//
+
+//
+btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
+{
+m_releasepaircache = (paircache!=0)?false:true;
+m_predictedframes = 2;
+m_stageCurrent = 0;
+m_fupdates = 1;
+m_dupdates = 1;
+m_paircache = paircache?
+ paircache :
+ new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
+m_gid = 0;
+m_pid = 0;
+for(int i=0;i<=STAGECOUNT;++i)
+ {
+ m_stageRoots[i]=0;
+ }
+#if DBVT_BP_PROFILE
+clear(m_profiling);
+#endif
+}
+
+//
+btDbvtBroadphase::~btDbvtBroadphase()
+{
+if(m_releasepaircache)
+{
+ m_paircache->~btOverlappingPairCache();
+ btAlignedFree(m_paircache);
+}
+}
+
+//
+btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ int /*shapeType*/,
+ void* userPtr,
+ short int collisionFilterGroup,
+ short int collisionFilterMask,
+ btDispatcher* /*dispatcher*/,
+ void* /*multiSapProxy*/)
+{
+btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( userPtr,
+ collisionFilterGroup,
+ collisionFilterMask);
+proxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
+proxy->leaf = m_sets[0].insert(proxy->aabb,proxy);
+proxy->stage = m_stageCurrent;
+proxy->m_uniqueId = ++m_gid;
+listappend(proxy,m_stageRoots[m_stageCurrent]);
+return(proxy);
+}
+
+//
+void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy,
+ btDispatcher* dispatcher)
+{
+btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+if(proxy->stage==STAGECOUNT)
+ m_sets[1].remove(proxy->leaf);
+ else
+ m_sets[0].remove(proxy->leaf);
+listremove(proxy,m_stageRoots[proxy->stage]);
+m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher);
+btAlignedFree(proxy);
+}
+
+//
+void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btDispatcher* /*dispatcher*/)
+{
+btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+btDbvtVolume aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
+if(NotEqual(aabb,proxy->leaf->volume))
+ {
+ if(proxy->stage==STAGECOUNT)
+ {/* fixed -> dynamic set */
+ m_sets[1].remove(proxy->leaf);
+ proxy->leaf=m_sets[0].insert(aabb,proxy);
+ }
+ else
+ {/* dynamic set */
+ if(Intersect(proxy->leaf->volume,aabb))
+ {/* Moving */
+ const btVector3 delta=(aabbMin+aabbMax)/2-proxy->aabb.Center();
+ #ifdef DBVT_BP_MARGIN
+ m_sets[0].update(proxy->leaf,aabb,delta*m_predictedframes,DBVT_BP_MARGIN);
+ #else
+ m_sets[0].update(proxy->leaf,aabb,delta*m_predictedframes);
+ #endif
+ }
+ else
+ {/* Teleporting */
+ m_sets[0].update(proxy->leaf,aabb);
+ }
+ }
+ listremove(proxy,m_stageRoots[proxy->stage]);
+ proxy->aabb = aabb;
+ proxy->stage = m_stageCurrent;
+ listappend(proxy,m_stageRoots[m_stageCurrent]);
+ }
+}
+
+//
+void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+collide(dispatcher);
+#if DBVT_BP_PROFILE
+if(0==(m_pid%DBVT_BP_PROFILING_RATE))
+ {
+ printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
+ unsigned int total=m_profiling.m_total;
+ if(total<=0) total=1;
+ printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE);
+ printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE);
+ printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE);
+ printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE);
+ const unsigned long sum=m_profiling.m_ddcollide+
+ m_profiling.m_fdcollide+
+ m_profiling.m_cleanup;
+ printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE);
+ printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE));
+ clear(m_profiling);
+ m_clock.reset();
+ }
+#endif
+}
+
+//
+void btDbvtBroadphase::collide(btDispatcher* dispatcher)
+{
+SPC(m_profiling.m_total);
+/* optimize */
+m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
+m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
+/* dynamic -> fixed set */
+m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
+btDbvtProxy* current=m_stageRoots[m_stageCurrent];
+if(current)
+ {
+ btDbvtTreeCollider collider(this);
+ do {
+ btDbvtProxy* next=current->links[1];
+ listremove(current,m_stageRoots[current->stage]);
+ listappend(current,m_stageRoots[STAGECOUNT]);
+ btDbvt::collideTT(m_sets[1].m_root,current->leaf,collider);
+ m_sets[0].remove(current->leaf);
+ current->leaf = m_sets[1].insert(current->aabb,current);
+ current->stage = STAGECOUNT;
+ current = next;
+ } while(current);
+ }
+/* collide dynamics */
+ {
+ btDbvtTreeCollider collider(this);
+ {
+ SPC(m_profiling.m_fdcollide);
+ btDbvt::collideTT(m_sets[0].m_root,m_sets[1].m_root,collider);
+ }
+ {
+ SPC(m_profiling.m_ddcollide);
+ btDbvt::collideTT(m_sets[0].m_root,m_sets[0].m_root,collider);
+ }
+ }
+/* clean up */
+ {
+ SPC(m_profiling.m_cleanup);
+ btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
+ if(pairs.size()>0)
+ {
+ for(int i=0,ni=pairs.size();i<ni;++i)
+ {
+ btBroadphasePair& p=pairs[i];
+ btDbvtProxy* pa=(btDbvtProxy*)p.m_pProxy0;
+ btDbvtProxy* pb=(btDbvtProxy*)p.m_pProxy1;
+ if(!Intersect(pa->aabb,pb->aabb))
+ {
+ if(pa>pb) btSwap(pa,pb);
+ m_paircache->removeOverlappingPair(pa,pb,dispatcher);
+ --ni;--i;
+ }
+ }
+ }
+ }
+++m_pid;
+}
+
+//
+void btDbvtBroadphase::optimize()
+{
+m_sets[0].optimizeTopDown();
+m_sets[1].optimizeTopDown();
+}
+
+//
+btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
+{
+return(m_paircache);
+}
+
+//
+const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
+{
+return(m_paircache);
+}
+
+//
+void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+{
+
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds;
+
+if(!m_sets[0].empty())
+ if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume,
+ m_sets[1].m_root->volume,bounds);
+ else
+ bounds=m_sets[0].m_root->volume;
+else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume;
+ else
+ bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0);
+aabbMin=bounds.Mins();
+aabbMax=bounds.Maxs();
+}
+
+//
+void btDbvtBroadphase::printStats()
+{}
+
+#if DBVT_BP_PROFILE
+#undef SPC
+#endif
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
new file mode 100644
index 00000000000..3f19075552b
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
@@ -0,0 +1,103 @@
+/*
+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.
+*/
+///btDbvtBroadphase implementation by Nathanael Presson
+#ifndef BT_DBVT_BROADPHASE_H
+#define BT_DBVT_BROADPHASE_H
+
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+
+//
+// Compile time config
+//
+
+#define DBVT_BP_PROFILE 0
+#define DBVT_BP_DISCRETPAIRS 1
+#define DBVT_BP_MARGIN (btScalar)0.05
+
+#if DBVT_BP_PROFILE
+ #define DBVT_BP_PROFILING_RATE 256
+ #include "LinearMath/btQuickprof.h"
+#endif
+
+//
+// btDbvtProxy
+//
+struct btDbvtProxy : btBroadphaseProxy
+{
+/* Fields */
+btDbvtAabbMm aabb;
+btDbvtNode* leaf;
+btDbvtProxy* links[2];
+int stage;
+/* ctor */
+btDbvtProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
+ btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask)
+ {
+ links[0]=links[1]=0;
+ }
+};
+
+typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
+
+///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
+///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
+///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
+struct btDbvtBroadphase : btBroadphaseInterface
+{
+/* Config */
+enum {
+ DYNAMIC_SET = 0, /* Dynamic set index */
+ FIXED_SET = 1, /* Fixed set index */
+ STAGECOUNT = 2 /* Number of stages */
+ };
+/* Fields */
+btDbvt m_sets[2]; // Dbvt sets
+btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
+btOverlappingPairCache* m_paircache; // Pair cache
+btScalar m_predictedframes; // Frames predicted
+int m_stageCurrent; // Current stage
+int m_fupdates; // % of fixed updates per frame
+int m_dupdates; // % of dynamic updates per frame
+int m_pid; // Parse id
+int m_gid; // Gen id
+bool m_releasepaircache; // Release pair cache on delete
+#if DBVT_BP_PROFILE
+btClock m_clock;
+struct {
+ unsigned long m_total;
+ unsigned long m_ddcollide;
+ unsigned long m_fdcollide;
+ unsigned long m_cleanup;
+ unsigned long m_jobcount;
+ } m_profiling;
+#endif
+/* Methods */
+btDbvtBroadphase(btOverlappingPairCache* paircache=0);
+~btDbvtBroadphase();
+void collide(btDispatcher* dispatcher);
+void optimize();
+/* btBroadphaseInterface Implementation */
+btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+void calculateOverlappingPairs(btDispatcher* dispatcher);
+btOverlappingPairCache* getOverlappingPairCache();
+const btOverlappingPairCache* getOverlappingPairCache() const;
+void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
+void printStats();
+};
+
+#endif
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h
index 3d958cc8fef..6db71a0170e 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;
@@ -43,7 +43,9 @@ struct btDispatcherInfo
m_useContinuous(false),
m_debugDraw(0),
m_enableSatConvex(false),
- m_enableSPU(false),
+ m_enableSPU(true),
+ m_useEpa(true),
+ m_allowedCcdPenetration(btScalar(0.04)),
m_stackAllocator(0)
{
@@ -51,17 +53,19 @@ struct btDispatcherInfo
btScalar m_timeStep;
int m_stepCount;
int m_dispatchFunc;
- btScalar m_timeOfImpact;
+ mutable btScalar m_timeOfImpact;
bool m_useContinuous;
class btIDebugDraw* m_debugDraw;
bool m_enableSatConvex;
bool m_enableSPU;
+ bool m_useEpa;
+ btScalar m_allowedCcdPenetration;
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).
+///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs.
+///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic).
class btDispatcher
{
@@ -81,12 +85,18 @@ public:
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0;
- virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)=0;
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const 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..3f866ab7c5f
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
@@ -0,0 +1,466 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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"
+#include "btQuantizedBvh.h"
+
+/// btSapBroadphaseArray m_sapBroadphases;
+
+/// btOverlappingPairCache* m_overlappingPairs;
+extern int gOverlappingPairs;
+
+/*
+class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
+{
+public:
+
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+ {
+ return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
+ }
+};
+
+*/
+
+btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
+:m_overlappingPairs(pairCache),
+m_optimizedAabbTree(0),
+m_ownsPairCache(false),
+m_invalidPair(0)
+{
+ if (!m_overlappingPairs)
+ {
+ m_ownsPairCache = true;
+ void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
+ m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
+ }
+
+ struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
+ {
+ virtual ~btMultiSapOverlapFilterCallback()
+ {}
+ // return true when pairs need collision
+ virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
+ {
+ btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
+ btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
+
+ bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
+ collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->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)
+ {
+ m_overlappingPairs->~btOverlappingPairCache();
+ btAlignedFree(m_overlappingPairs);
+ }
+}
+
+
+void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
+{
+ m_optimizedAabbTree = new btQuantizedBvh();
+ m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
+ QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray();
+ for (int i=0;i<m_sapBroadphases.size();i++)
+ {
+ btQuantizedBvhNode node;
+ btVector3 aabbMin,aabbMax;
+ m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax);
+ m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
+ m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+ int partId = 0;
+ node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
+ nodes.push_back(node);
+ }
+ m_optimizedAabbTree->buildInternal();
+}
+
+btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
+{
+ //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
+
+ void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
+ btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
+ m_multiSapProxies.push_back(proxy);
+
+ ///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::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase)
+{
+ void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
+ btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
+ bridgeProxyRef->m_childProxy = childProxy;
+ bridgeProxyRef->m_childBroadphase = childBroadphase;
+ parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
+}
+
+
+bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
+bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
+{
+return
+amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
+amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
+amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
+}
+
+
+
+
+
+
+//#include <stdio.h>
+
+void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
+{
+ btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
+ multiProxy->m_aabbMin = aabbMin;
+ multiProxy->m_aabbMax = aabbMax;
+
+
+// bool fullyContained = false;
+// bool alreadyInSimple = false;
+
+
+
+
+ struct MyNodeOverlapCallback : public btNodeOverlapCallback
+ {
+ btMultiSapBroadphase* m_multiSap;
+ btMultiSapProxy* m_multiProxy;
+ btDispatcher* m_dispatcher;
+
+ MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
+ :m_multiSap(multiSap),
+ m_multiProxy(multiProxy),
+ m_dispatcher(dispatcher)
+ {
+
+ }
+
+ virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
+ {
+ btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
+
+ int containingBroadphaseIndex = -1;
+ //already found?
+ for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
+ {
+
+ if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
+ {
+ containingBroadphaseIndex = i;
+ break;
+ }
+ }
+ if (containingBroadphaseIndex<0)
+ {
+ //add it
+ btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
+ m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
+
+ }
+ }
+ };
+
+ MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher);
+
+
+
+
+ m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
+ int i;
+
+ for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
+ {
+ btVector3 worldAabbMin,worldAabbMax;
+ multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
+ bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+ if (!overlapsBroadphase)
+ {
+ //remove it now
+ btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
+
+ btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
+ bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
+
+ multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
+ multiProxy->m_bridgeProxies.pop_back();
+
+ }
+ }
+
+
+ /*
+
+ if (1)
+ {
+
+ //find broadphase that contain this multiProxy
+ int numChildBroadphases = getBroadphaseArray().size();
+ for (int i=0;i<numChildBroadphases;i++)
+ {
+ btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
+ btVector3 worldAabbMin,worldAabbMax;
+ childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
+ bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+
+ // fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+ int containingBroadphaseIndex = -1;
+
+ //if already contains this
+
+ for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
+ {
+ if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
+ {
+ containingBroadphaseIndex = i;
+ }
+ alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
+ }
+
+ if (overlapsBroadphase)
+ {
+ if (containingBroadphaseIndex<0)
+ {
+ btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+ childProxy->m_multiSapParentProxy = multiProxy;
+ addToChildBroadphase(multiProxy,childProxy,childBroadphase);
+ }
+ } else
+ {
+ if (containingBroadphaseIndex>=0)
+ {
+ //remove
+ btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
+
+ btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
+ bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
+
+ multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
+ multiProxy->m_bridgeProxies.pop_back();
+ }
+ }
+ }
+
+
+ ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
+ ///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
+ if (0)//!multiProxy->m_bridgeProxies.size())
+ {
+ ///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* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+ childProxy->m_multiSapParentProxy = multiProxy;
+ addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
+ }
+ }
+
+ if (!multiProxy->m_bridgeProxies.size())
+ {
+ ///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* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+ childProxy->m_multiSapParentProxy = multiProxy;
+ addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
+ }
+*/
+
+
+ //update
+ for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
+ {
+ btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
+ bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
+ }
+
+}
+bool stopUpdating=false;
+
+
+
+class btMultiSapBroadphasePairSortPredicate
+{
+ public:
+
+ bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 )
+ {
+ btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
+ btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
+ btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
+ btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
+
+ return aProxy0 > bProxy0 ||
+ (aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
+ (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm);
+ }
+};
+
+
+ ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+
+// m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
+
+ if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
+ {
+
+ btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
+
+ // quicksort(overlappingPairArray,0,overlappingPairArray.size());
+
+ overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ // overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
+
+ 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;i<overlappingPairArray.size();i++)
+ {
+
+ btBroadphasePair& pair = overlappingPairArray[i];
+
+ btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
+ btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
+ btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
+ btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
+
+ bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
+
+ previousPair = pair;
+
+ bool needsRemoval = false;
+
+ if (!isDuplicate)
+ {
+ bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+ if (hasOverlap)
+ {
+ needsRemoval = false;//callback->processOverlap(pair);
+ } else
+ {
+ needsRemoval = true;
+ }
+ } else
+ {
+ //remove duplicate
+ needsRemoval = true;
+ //should have no algorithm
+ btAssert(!pair.m_algorithm);
+ }
+
+ if (needsRemoval)
+ {
+ getOverlappingPairCache()->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(btMultiSapBroadphasePairSortPredicate());
+ overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+ #endif//CLEAN_INVALID_PAIRS
+
+ //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+ }
+
+
+}
+
+
+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);
+
+}
+
+
+void btMultiSapBroadphase::printStats()
+{
+/* printf("---------------------------------\n");
+
+ printf("btMultiSapBroadphase.h\n");
+ printf("numHandles = %d\n",m_multiSapProxies.size());
+ //find broadphase that contain this multiProxy
+ int numChildBroadphases = getBroadphaseArray().size();
+ for (int i=0;i<numChildBroadphases;i++)
+ {
+
+ btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
+ childBroadphase->printStats();
+
+ }
+ */
+
+}
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
new file mode 100644
index 00000000000..a0c002de856
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
@@ -0,0 +1,144 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 btBroadphaseInterface;
+class btSimpleBroadphase;
+
+
+typedef btAlignedObjectArray<btBroadphaseInterface*> btSapBroadphaseArray;
+
+///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases.
+///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time.
+///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy.
+///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;
+
+ class btQuantizedBvh* m_optimizedAabbTree;
+
+
+ bool m_ownsPairCache;
+
+ btOverlapFilterCallback* m_filterCallback;
+
+ int m_invalidPair;
+
+ struct btBridgeProxy
+ {
+ btBroadphaseProxy* m_childProxy;
+ btBroadphaseInterface* m_childBroadphase;
+ };
+
+
+public:
+
+ struct btMultiSapProxy : public btBroadphaseProxy
+ {
+
+ ///array with all the entries that this proxy belongs to
+ btAlignedObjectArray<btBridgeProxy*> m_bridgeProxies;
+ 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)
+ :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask),
+ m_aabbMin(aabbMin),
+ m_aabbMax(aabbMax),
+ m_shapeType(shapeType)
+ {
+ m_multiSapParentProxy =this;
+ }
+
+
+ };
+
+protected:
+
+
+ btAlignedObjectArray<btMultiSapProxy*> 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,void* multiSapProxy);
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
+
+ void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase);
+
+ ///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;
+ }
+
+ ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+ ///will add some transform later
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ aabbMin.setValue(-1e30f,-1e30f,-1e30f);
+ aabbMax.setValue(1e30f,1e30f,1e30f);
+ }
+
+ void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
+
+ virtual void printStats();
+
+ void quicksort (btBroadphasePairArray& a, int lo, int hi);
+
+};
+
+#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..ff65cdde79f 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
@@ -1,4 +1,3 @@
-
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
@@ -21,66 +20,415 @@ subject to the following restrictions:
#include "btDispatcher.h"
#include "btCollisionAlgorithm.h"
+#include <stdio.h>
+
int gOverlappingPairs = 0;
-btOverlappingPairCache::btOverlappingPairCache():
-m_blockedForChanges(false),
-m_overlapFilterCallback(0)
-//m_NumOverlapBroadphasePair(0)
+int gRemovePairs =0;
+int gAddedPairs =0;
+int gFindPairs =0;
+
+
+
+
+btHashedOverlappingPairCache::btHashedOverlappingPairCache():
+ m_overlapFilterCallback(0),
+ m_blockedForChanges(false)
{
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+ growTables();
}
-btOverlappingPairCache::~btOverlappingPairCache()
+
+
+btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
{
//todo/test: show we erase/delete data, or is it automatic
}
-void btOverlappingPairCache::removeOverlappingPair(btBroadphasePair& findPair)
+
+void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
{
-
- int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
- if (findIndex < m_overlappingPairArray.size())
+ if (pair.m_algorithm)
+ {
+ {
+ pair.m_algorithm->~btCollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+ pair.m_algorithm=0;
+ }
+ }
+}
+
+
+
+
+void btHashedOverlappingPairCache::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 btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+ class RemovePairCallback : public btOverlapCallback
{
- gOverlappingPairs--;
- btBroadphasePair& pair = m_overlappingPairArray[findIndex];
- cleanOverlappingPair(pair);
+ 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));
+ }
- m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.size()-1);
+ };
+
+
+ RemovePairCallback removeCallback(proxy);
+
+ processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+
+
+
+
+btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+ gFindPairs++;
+ if(proxy0>proxy1) btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+ if (hash >= m_hashTable.size())
+ {
+ return NULL;
+ }
+
+ 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 <stdio.h>
+
+void btHashedOverlappingPairCache::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;i<curHashtableSize;i++)
+ {
+
+ const btBroadphasePair& pair = m_overlappingPairArray[i];
+ int proxyId1 = pair.m_pProxy0->getUid();
+ int proxyId2 = pair.m_pProxy1->getUid();
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+ int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+ m_next[i] = m_hashTable[hashValue];
+ m_hashTable[hashValue] = i;
+ }
+
+
+ }
+}
+
+btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+ if(proxy0>proxy1) btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+
+
+ btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+ if (pair != NULL)
+ {
+ return pair;
+ }
+ /*for(int i=0;i<m_overlappingPairArray.size();++i)
+ {
+ if( (m_overlappingPairArray[i].m_pProxy0==proxy0)&&
+ (m_overlappingPairArray[i].m_pProxy1==proxy1))
+ {
+ printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2);
+ internalFindPair(proxy0, proxy1, hash);
+ }
+ }*/
+ 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 = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(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* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+{
+ gRemovePairs++;
+ if(proxy0>proxy1) btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(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];
+ /* missing swap here too, Nat. */
+ int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(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 <stdio.h>
+
+void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+
+ int i;
+
+// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
+ for (i=0;i<m_overlappingPairArray.size();)
+ {
+
+ btBroadphasePair* pair = &m_overlappingPairArray[i];
+ if (callback->processOverlap(*pair))
+ {
+ removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
+
+ gOverlappingPairs--;
+ } else
+ {
+ i++;
+ }
}
}
-void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair)
+
+void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
{
- if (pair.m_algorithm)
+ if (!hasDeferredRemoval())
{
+ btBroadphasePair findPair(*proxy0,*proxy1);
+
+ int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
+ if (findIndex < m_overlappingPairArray.size())
{
- delete pair.m_algorithm;;
- pair.m_algorithm=0;
+ 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;
}
}
+
+ return 0;
}
-void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+
+
+
+btBroadphasePair* btSortedOverlappingPairCache::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++;
+ gAddedPairs++;
+ return pair;
}
@@ -88,7 +436,7 @@ void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroa
///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)
+ btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
{
if (!needsBroadphaseCollision(proxy0,proxy1))
return 0;
@@ -109,18 +457,81 @@ void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroa
-void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy)
+
+
+
+
+
+//#include <stdio.h>
+
+void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+
+ int i;
+
+ for (i=0;i<m_overlappingPairArray.size();)
+ {
+
+ btBroadphasePair* pair = &m_overlappingPairArray[i];
+ if (callback->processOverlap(*pair))
+ {
+ cleanOverlappingPair(*pair,dispatcher);
+
+ m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1);
+ m_overlappingPairArray.pop_back();
+ gOverlappingPairs--;
+ } else
+ {
+ i++;
+ }
+ }
+}
+
+
+
+
+btSortedOverlappingPairCache::btSortedOverlappingPairCache():
+ m_blockedForChanges(false),
+ m_hasDeferredRemoval(true),
+ m_overlapFilterCallback(0)
+{
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+}
+
+btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
+{
+ //todo/test: show we erase/delete data, or is it automatic
+}
+
+void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+{
+ if (pair.m_algorithm)
+ {
+ {
+ pair.m_algorithm->~btCollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+ pair.m_algorithm=0;
+ gRemovePairs--;
+ }
+ }
+}
+
+
+void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class CleanPairCallback : public btOverlapCallback
{
btBroadphaseProxy* m_cleanProxy;
btOverlappingPairCache* m_pairCache;
+ btDispatcher* m_dispatcher;
public:
- CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache)
+ CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
:m_cleanProxy(cleanProxy),
- m_pairCache(pairCache)
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
{
}
virtual bool processOverlap(btBroadphasePair& pair)
@@ -128,22 +539,21 @@ void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy)
if ((pair.m_pProxy0 == m_cleanProxy) ||
(pair.m_pProxy1 == m_cleanProxy))
{
- m_pairCache->cleanOverlappingPair(pair);
+ m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
}
return false;
}
};
- CleanPairCallback cleanPairs(proxy,this);
+ CleanPairCallback cleanPairs(proxy,this,dispatcher);
- processAllOverlappingPairs(&cleanPairs);
+ processAllOverlappingPairs(&cleanPairs,dispatcher);
}
-
-void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy)
+void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
{
class RemovePairCallback : public btOverlapCallback
@@ -163,34 +573,7 @@ void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseP
};
-
RemovePairCallback removeCallback(proxy);
- processAllOverlappingPairs(&removeCallback);
-}
-
-
-
-void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback)
-{
-
- int i;
-
- for (i=0;i<m_overlappingPairArray.size();)
- {
-
- btBroadphasePair* pair = &m_overlappingPairArray[i];
- if (callback->processOverlap(*pair))
- {
- cleanOverlappingPair(*pair);
-
- m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
- m_overlappingPairArray.pop_back();
- gOverlappingPairs--;
- } else
- {
- i++;
- }
- }
+ processAllOverlappingPairs(&removeCallback,dispatcher);
}
-
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
index a81fe3264df..66679bd218a 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
@@ -1,4 +1,3 @@
-
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
@@ -20,9 +19,13 @@ subject to the following restrictions:
#include "btBroadphaseInterface.h"
#include "btBroadphaseProxy.h"
-#include "../../LinearMath/btPoint3.h"
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "btOverlappingPairCallback.h"
+
+#include "LinearMath/btPoint3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+class btDispatcher;
+typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
struct btOverlapCallback
{
@@ -30,6 +33,7 @@ struct btOverlapCallback
{}
//return true for deletion of the pair
virtual bool processOverlap(btBroadphasePair& pair) = 0;
+
};
struct btOverlapFilterCallback
@@ -40,38 +44,261 @@ struct btOverlapFilterCallback
virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
};
-///btOverlappingPairCache maintains the objects with overlapping AABB
+
+
+
+
+
+
+extern int gRemovePairs;
+extern int gAddedPairs;
+extern int gFindPairs;
+
+const int BT_NULL_PAIR=0xffffffff;
+
+///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
+///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
+class btOverlappingPairCache : public btOverlappingPairCallback
+{
+public:
+ virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
+
+ virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
+
+ virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
+
+ virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
+
+ virtual int getNumOverlappingPairs() const = 0;
+
+ virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
+
+ virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
+
+ virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
+
+ virtual bool hasDeferredRemoval() = 0;
+
+};
+
+/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
+class btHashedOverlappingPairCache : public btOverlappingPairCache
+{
+ btBroadphasePairArray m_overlappingPairArray;
+ btOverlapFilterCallback* m_overlapFilterCallback;
+ bool m_blockedForChanges;
+
+
+public:
+ btHashedOverlappingPairCache();
+ virtual ~btHashedOverlappingPairCache();
+
+
+ void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+ virtual 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.
+ virtual 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);
+
+ virtual 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 = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
+ // Thomas Wang's hash
+
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return static_cast<unsigned int>(key);
+ }
+
+
+
+
+
+ SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
+ {
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+ #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
+ if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);
+ #endif
+
+ 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];
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return false;
+ }
+
+public:
+
+ btAlignedObjectArray<int> m_hashTable;
+ btAlignedObjectArray<int> m_next;
+
+};
+
+
+
+
+///btSortedOverlappingPairCache maintains the objects with overlapping AABB
///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
-class btOverlappingPairCache : public btBroadphaseInterface
+class btSortedOverlappingPairCache : public btOverlappingPairCache
{
protected:
//avoid brute-force finding all the time
- btAlignedObjectArray<btBroadphasePair> m_overlappingPairArray;
-
+ btBroadphasePairArray m_overlappingPairArray;
+
//during the dispatch, check that user doesn't destroy/create proxy
bool m_blockedForChanges;
+
+ ///by default, do the removal during the pair traversal
+ bool m_hasDeferredRemoval;
//if set, use the callback instead of the built in filter in needBroadphaseCollision
btOverlapFilterCallback* m_overlapFilterCallback;
+
public:
- btOverlappingPairCache();
- virtual ~btOverlappingPairCache();
+ btSortedOverlappingPairCache();
+ virtual ~btSortedOverlappingPairCache();
- 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 +311,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()
{
@@ -114,7 +350,88 @@ class btOverlappingPairCache : public btBroadphaseInterface
m_overlapFilterCallback = callback;
}
+ virtual bool hasDeferredRemoval()
+ {
+ return m_hasDeferredRemoval;
+ }
+
+
+};
+
+
+
+///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and testing.
+class btNullPairCache : public btOverlappingPairCache
+{
+
+ btBroadphasePairArray m_overlappingPairArray;
+
+public:
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
+ {
+
+ }
+
+ virtual int getNumOverlappingPairs() const
+ {
+ return 0;
+ }
+
+ virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
+ {
+
+ }
+
+ virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
+ {
+ }
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
+ {
+ }
+
+ virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
+ {
+ return 0;
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return true;
+ }
+
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
+ {
+ return 0;
+ }
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
+ {
+ return 0;
+ }
+
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
+ {
+ }
+
+
};
+
+
#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..9c7b6f81367
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.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 OVERLAPPING_PAIR_CALLBACK_H
+#define OVERLAPPING_PAIR_CALLBACK_H
+
+class btDispatcher;
+struct btBroadphasePair;
+
+///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+class btOverlappingPairCallback
+{
+public:
+ virtual ~btOverlappingPairCallback()
+ {
+
+ }
+
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
+
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
+
+};
+
+#endif //OVERLAPPING_PAIR_CALLBACK_H
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
new file mode 100644
index 00000000000..a30bd1fd9e1
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
@@ -0,0 +1,1025 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btQuantizedBvh.h"
+
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btIDebugDraw.h"
+
+
+btQuantizedBvh::btQuantizedBvh() : 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 btQuantizedBvh::buildInternal()
+{
+ ///assumes that caller filled in the m_quantizedLeafNodes
+ m_useQuantization = true;
+ int numLeafNodes = 0;
+
+ if (m_useQuantization)
+ {
+ //now we have an array of leafnodes in m_leafNodes
+ numLeafNodes = m_quantizedLeafNodes.size();
+
+ m_quantizedContiguousNodes.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();
+}
+
+
+
+///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 btQuantizedBvh::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(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+ m_useQuantization = true;
+}
+
+
+
+
+btQuantizedBvh::~btQuantizedBvh()
+{
+}
+
+#ifdef DEBUG_TREE_BUILDING
+int gStackDepth = 0;
+int gMaxStackDepth = 0;
+#endif //DEBUG_TREE_BUILDING
+
+void btQuantizedBvh::buildTree (int startIndex,int endIndex)
+{
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth++;
+ if (gStackDepth > 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,m_bvhAabbMin);
+ setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ mergeInternalNodeAabb(m_curNodeIndex,getAabbMin(i),getAabbMax(i));
+ }
+
+ m_curNodeIndex++;
+
+
+ //internalNode->m_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 btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex)
+{
+ btAssert(m_useQuantization);
+
+ btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
+ int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
+ int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
+
+ btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
+ int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
+ int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast<int>(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 btQuantizedBvh::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<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ means+=center;
+ }
+ means *= (btScalar(1.)/(btScalar)numIndices);
+
+ splitValue = means[splitAxis];
+
+ //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ if (center[splitAxis] > 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));
+ (void)unbal;
+ btAssert(!unbal);
+
+ return splitIndex;
+}
+
+
+int btQuantizedBvh::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;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ means+=center;
+ }
+ means *= (btScalar(1.)/(btScalar)numIndices);
+
+ for (i=startIndex;i<endIndex;i++)
+ {
+ btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+ btVector3 diff2 = center-means;
+ diff2 = diff2 * diff2;
+ variance += diff2;
+ }
+ variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
+
+ return variance.maxAxis();
+}
+
+
+
+void btQuantizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ //either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
+
+ if (m_useQuantization)
+ {
+ ///quantize query AABB
+ unsigned short int quantizedQueryAabbMin[3];
+ unsigned short int quantizedQueryAabbMax[3];
+ quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
+ quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
+
+ switch (m_traversalMode)
+ {
+ case TRAVERSAL_STACKLESS:
+ walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,0,m_curNodeIndex);
+ break;
+ case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
+ walkStacklessQuantizedTreeCacheFriendly(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ break;
+ case TRAVERSAL_RECURSIVE:
+ {
+ const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
+ walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+ }
+ break;
+ default:
+ //unsupported
+ btAssert(0);
+ }
+ } else
+ {
+ walkStacklessTree(nodeCallback,aabbMin,aabbMax);
+ }
+}
+
+
+int maxIterations = 0;
+
+void btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ btAssert(!m_useQuantization);
+
+ const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
+ int escapeIndex, curIndex = 0;
+ int walkIterations = 0;
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned aabbOverlap;
+
+ while (curIndex < m_curNodeIndex)
+ {
+ //catch bugs in tree data
+ assert (walkIterations < m_curNodeIndex);
+
+ walkIterations++;
+ aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_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 btQuantizedBvh::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 btQuantizedBvh::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(currentNode->getPartId(),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 btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+{
+ btAssert(m_useQuantization);
+
+ int curIndex = startNodeIndex;
+ int walkIterations = 0;
+ int subTreeSize = endNodeIndex - startNodeIndex;
+ (void)subTreeSize;
+
+ const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+ int escapeIndex;
+
+ bool isLeafNode;
+ //PCK: unsigned instead of bool
+ unsigned boxBoxOverlap = 0;
+ unsigned rayBoxOverlap = 0;
+
+ btScalar lambda_max = 1.0;
+#define RAYAABB2
+#ifdef RAYAABB2
+ btVector3 rayFrom = raySource;
+ btVector3 rayDirection = (rayTarget-raySource);
+ rayDirection.normalize ();
+ lambda_max = rayDirection.dot(rayTarget-raySource);
+ ///what about division by zero? --> just set rayDirection[i] to 1.0
+ rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[0];
+ rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[1];
+ rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[2];
+ unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
+#endif
+
+ /* Quick pruning by quantized box */
+ btVector3 rayAabbMin = raySource;
+ btVector3 rayAabbMax = raySource;
+ rayAabbMin.setMin(rayTarget);
+ rayAabbMax.setMax(rayTarget);
+
+ /* Add box cast extents to bounding box */
+ rayAabbMin += aabbMin;
+ rayAabbMax += aabbMax;
+
+ unsigned short int quantizedQueryAabbMin[3];
+ unsigned short int quantizedQueryAabbMax[3];
+ quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0);
+ quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1);
+
+ 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
+ // only interested if this is closer than any previous hit
+ btScalar param = 1.0;
+ rayBoxOverlap = 0;
+ boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+ isLeafNode = rootNode->isLeafNode();
+ if (boxBoxOverlap)
+ {
+ btVector3 bounds[2];
+ bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
+ bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
+ /* Add box cast extents */
+ bounds[0] += aabbMin;
+ bounds[1] += aabbMax;
+ btVector3 normal;
+#if 0
+ bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
+ bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
+ if (ra2 != ra)
+ {
+ printf("functions don't match\n");
+ }
+#endif
+#ifdef RAYAABB2
+ ///careful with this check: need to check division by zero (above) and fix the unQuantize method
+ ///thanks Joerg/hiker for the reproduction case!
+ ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+
+ rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
+#else
+ rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
+#endif
+ }
+
+ if (isLeafNode && rayBoxOverlap)
+ {
+ nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+ }
+
+ //PCK: unsigned instead of bool
+ if ((rayBoxOverlap != 0) || isLeafNode)
+ {
+ rootNode++;
+ curIndex++;
+ } else
+ {
+ escapeIndex = rootNode->getEscapeIndex();
+ rootNode += escapeIndex;
+ curIndex += escapeIndex;
+ }
+ }
+ if (maxIterations < walkIterations)
+ maxIterations = walkIterations;
+
+}
+
+void btQuantizedBvh::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;
+ (void)subTreeSize;
+
+ 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(rootNode->getPartId(),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 btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+ btAssert(m_useQuantization);
+
+ int i;
+
+
+ for (i=0;i<this->m_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 btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
+{
+ bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS;
+ if (fast_path)
+ {
+ walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, btVector3(0, 0, 0), btVector3(0, 0, 0), 0, m_curNodeIndex);
+ } else {
+ /* Otherwise fallback to AABB overlap test */
+ btVector3 aabbMin = raySource;
+ btVector3 aabbMax = raySource;
+ aabbMin.setMin(rayTarget);
+ aabbMax.setMax(rayTarget);
+ reportAabbOverlappingNodex(nodeCallback,aabbMin,aabbMax);
+ }
+}
+
+
+void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+ bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS;
+ if (fast_path)
+ {
+ walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+ } else {
+ /* Slow path:
+ Construct the bounding box for the entire box cast and send that down the tree */
+ btVector3 qaabbMin = raySource;
+ btVector3 qaabbMax = raySource;
+ qaabbMin.setMin(rayTarget);
+ qaabbMax.setMax(rayTarget);
+ qaabbMin += aabbMin;
+ qaabbMax += aabbMax;
+ reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
+ }
+}
+
+
+void btQuantizedBvh::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 btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex)
+{
+ if (m_useQuantization)
+ {
+ m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
+ } else
+ {
+ m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
+ }
+}
+
+//PCK: include
+#include <new>
+
+//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 btQuantizedBvh::getAlignmentSerializationPadding()
+{
+ return BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
+}
+
+unsigned btQuantizedBvh::calculateSerializeBufferSize()
+{
+ unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding();
+ baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+ if (m_useQuantization)
+ {
+ return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode);
+ }
+ return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode);
+}
+
+bool btQuantizedBvh::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;
+ }
+*/
+
+ btQuantizedBvh *targetBvh = (btQuantizedBvh *)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) btQuantizedBvh;
+
+ if (i_swapEndian)
+ {
+ targetBvh->m_curNodeIndex = static_cast<int>(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 = static_cast<int>(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(btQuantizedBvh);
+
+ 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 = static_cast<int>(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 = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
+ targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
+ targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(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 = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
+ targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(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;
+}
+
+btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+
+ if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+ {
+ return NULL;
+ }
+ btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer;
+
+ if (i_swapEndian)
+ {
+ bvh->m_curNodeIndex = static_cast<int>(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 = static_cast<int>(btSwapEndian(bvh->m_subtreeHeaderCount));
+ }
+
+ unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
+ btAssert(calculatedBufSize <= i_dataBufferSize);
+
+ if (calculatedBufSize > i_dataBufferSize)
+ {
+ return NULL;
+ }
+
+ unsigned char *nodeData = (unsigned char *)bvh;
+ nodeData += sizeof(btQuantizedBvh);
+
+ 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) btQuantizedBvh(*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 = static_cast<int>(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 = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
+ bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
+ bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(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 = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
+ bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
+ }
+ }
+
+ return bvh;
+}
+
+// Constructor that prevents btVector3's default constructor from being called
+btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &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/BroadphaseCollision/btQuantizedBvh.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
new file mode 100644
index 00000000000..8a149b533fa
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
@@ -0,0 +1,486 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 QUANTIZED_BVH_H
+#define QUANTIZED_BVH_H
+
+//#define DEBUG_CHECK_DEQUANTIZATION 1
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+#ifdef __SPU__
+#define printf spu_printf
+#endif //__SPU__
+
+#include <stdio.h>
+#include <stdlib.h>
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+
+//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
+
+
+//Note: currently we have 16 bytes per quantized node
+#define MAX_SUBTREE_SIZE_IN_BYTES 2048
+
+// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
+// actually) triangles each (since the sign bit is reserved
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///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());
+ // Get only the lower bits where the triangle index is stored
+ return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
+ }
+ int getPartId() const
+ {
+ btAssert(isLeafNode());
+ // Get only the highest bits where the part index is stored
+ return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
+ }
+}
+;
+
+/// 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<btOptimizedBvhNode> NodeArray;
+typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
+typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
+
+
+///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
+///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase.
+///It is recommended to use quantization for better performance and lower memory requirements.
+ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
+{
+protected:
+
+ 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)
+ {
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
+ } else
+ {
+ m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
+
+ }
+ }
+ void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
+ {
+ if (m_useQuantization)
+ {
+ quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
+ } 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 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];
+ quantize(quantizedAabbMin,newAabbMin,0);
+ quantize(quantizedAabbMax,newAabbMax,1);
+ 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 walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) 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 static_cast<unsigned int>(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:
+ btQuantizedBvh();
+
+ virtual ~btQuantizedBvh();
+
+
+ ///***************************************** expert/internal use only *************************
+ void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
+ QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
+ ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
+ void buildInternal();
+ ///***************************************** expert/internal use only *************************
+
+ void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
+ void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+ SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
+ {
+
+ btAssert(m_useQuantization);
+
+ btAssert(point.getX() <= m_bvhAabbMax.getX());
+ btAssert(point.getY() <= m_bvhAabbMax.getY());
+ btAssert(point.getZ() <= m_bvhAabbMax.getZ());
+
+ btAssert(point.getX() >= m_bvhAabbMin.getX());
+ btAssert(point.getY() >= m_bvhAabbMin.getY());
+ btAssert(point.getZ() >= m_bvhAabbMin.getZ());
+
+ btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
+ ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
+ ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
+ ///todo: double-check this
+ if (isMax)
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
+ out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
+ out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
+ } else
+ {
+ out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
+ out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
+ out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
+ }
+
+
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+ btVector3 newPoint = unQuantize(out);
+ if (isMax)
+ {
+ if (newPoint.getX() < point.getX())
+ {
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ }
+ if (newPoint.getY() < point.getY())
+ {
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ }
+ if (newPoint.getZ() < point.getZ())
+ {
+
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ }
+ } else
+ {
+ if (newPoint.getX() > point.getX())
+ {
+ printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+ }
+ if (newPoint.getY() > point.getY())
+ {
+ printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+ }
+ if (newPoint.getZ() > point.getZ())
+ {
+ printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+ }
+ }
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+ }
+
+
+ SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
+ {
+
+ btAssert(m_useQuantization);
+
+ btVector3 clampedPoint(point2);
+ clampedPoint.setMax(m_bvhAabbMin);
+ clampedPoint.setMin(m_bvhAabbMax);
+
+ quantize(out,clampedPoint,isMax);
+
+ }
+
+ SIMD_FORCE_INLINE btVector3 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;
+ }
+
+ ///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;
+ }
+
+
+ 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
+ virtual 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 btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int 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)
+ btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
+
+}
+;
+
+
+#endif //QUANTIZED_BVH_H
diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
index 30bcbe0c5f1..2d27f22567f 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
@@ -14,83 +14,86 @@ subject to the following restrictions:
*/
#include "btSimpleBroadphase.h"
-#include <BulletCollision/BroadphaseCollision/btDispatcher.h>
-#include <BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h>
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btMatrix3x3.h"
#include <new>
+extern int gOverlappingPairs;
void btSimpleBroadphase::validate()
{
- for (int i=0;i<m_numProxies;i++)
+ for (int i=0;i<m_numHandles;i++)
{
- for (int j=i+1;j<m_numProxies;j++)
+ for (int j=i+1;j<m_numHandles;j++)
{
- assert(m_pProxies[i] != m_pProxies[j]);
+ btAssert(&m_pHandles[i] != &m_pHandles[j]);
}
}
}
-btSimpleBroadphase::btSimpleBroadphase(int maxProxies)
- :btOverlappingPairCache(),
- m_firstFreeProxy(0),
- m_numProxies(0),
- m_maxProxies(maxProxies)
+btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
+ :m_pairCache(overlappingPairCache),
+ m_ownsPairCache(false),
+ m_invalidPair(0)
{
- m_proxies = new btSimpleBroadphaseProxy[maxProxies];
- m_freeProxies = new int[maxProxies];
- m_pProxies = new btSimpleBroadphaseProxy*[maxProxies];
-
+ if (!overlappingPairCache)
+ {
+ void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
+ m_pairCache = new (mem)btHashedOverlappingPairCache();
+ m_ownsPairCache = true;
+ }
+
+ // allocate handles buffer and put all handles on free list
+ m_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy)*maxProxies,16);
+ m_pHandles = new(m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies];
+ m_maxHandles = maxProxies;
+ m_numHandles = 0;
+ m_firstFreeHandle = 0;
+ m_firstAllocatedHandle = -1;
- int i;
- for (i=0;i<m_maxProxies;i++)
{
- m_freeProxies[i] = i;
+ for (int i = m_firstFreeHandle; i < maxProxies; i++)
+ {
+ m_pHandles[i].SetNextFree(i + 1);
+ m_pHandles[i].m_uniqueId = i+2;//any UID will do, we just avoid too trivial values (0,1) for debugging purposes
+ m_pHandles[i].SetNextAllocated(-1);
+ }
+ m_pHandles[maxProxies - 1].SetNextFree(0);
+ m_pHandles[maxProxies - 1].SetNextAllocated(-1);
+
}
+
}
btSimpleBroadphase::~btSimpleBroadphase()
{
- delete[] m_proxies;
- delete []m_freeProxies;
- delete [] m_pProxies;
+ btAlignedFree(m_pHandlesRawPtr);
- /*int i;
- for (i=m_numProxies-1;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*/,void* multiSapProxy)
{
- 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]);
-
- 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);
+ assert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
- m_pProxies[m_numProxies] = proxy;
- m_numProxies++;
- //validate();
+ int newHandleIndex = allocHandle();
+ btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy);
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<btSimpleBroadphaseProxy*>(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;i<m_numProxies;i++)
- {
- if (m_pProxies[i] == proxyOrg)
- {
- m_pProxies[i] = m_pProxies[m_numProxies-1];
- break;
- }
- }
- m_numProxies--;
//validate();
}
-void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)
+void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
{
btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
sbp->m_min = aabbMin;
@@ -186,37 +174,137 @@ public:
}
};
-void btSimpleBroadphase::refreshOverlappingPairs()
+void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
{
//first check for new overlapping pairs
int i,j;
- for (i=0;i<m_numProxies;i++)
+ if (m_firstAllocatedHandle >= 0)
{
- btBroadphaseProxy* proxy0 = m_pProxies[i];
- for (j=i+1;j<m_numProxies;j++)
+
+ btSimpleBroadphaseProxy* proxy0 = &m_pHandles[m_firstAllocatedHandle];
+
+ for (i=0;i<m_numHandles;i++)
{
- btBroadphaseProxy* proxy1 = m_pProxies[j];
- btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
- btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+ btSimpleBroadphaseProxy* proxy1 = &m_pHandles[m_firstAllocatedHandle];
- if (aabbOverlap(p0,p1))
+ for (j=0;j<m_numHandles;j++)
{
- if ( !findPair(proxy0,proxy1))
+
+ if (proxy0 != proxy1)
{
- addOverlappingPair(proxy0,proxy1);
+ btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
+ btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+
+ if (aabbOverlap(p0,p1))
+ {
+ if ( !m_pairCache->findPair(proxy0,proxy1))
+ {
+ m_pairCache->addOverlappingPair(proxy0,proxy1);
+ }
+ } else
+ {
+ if (!m_pairCache->hasDeferredRemoval())
+ {
+ if ( m_pairCache->findPair(proxy0,proxy1))
+ {
+ m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
+ }
+ }
+
+ }
}
+ proxy1 = &m_pHandles[proxy1->GetNextAllocated()];
+
}
+ proxy0 = &m_pHandles[proxy0->GetNextAllocated()];
}
- }
+ if (m_ownsPairCache && m_pairCache->hasDeferredRemoval())
+ {
+
+ btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(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;i<overlappingPairArray.size();i++)
+ {
+
+ btBroadphasePair& pair = overlappingPairArray[i];
- CheckOverlapCallback checkOverlap;
+ bool isDuplicate = (pair == previousPair);
- processAllOverlappingPairs(&checkOverlap);
+ previousPair = pair;
+ bool needsRemoval = false;
+ if (!isDuplicate)
+ {
+ bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+ if (hasOverlap)
+ {
+ needsRemoval = false;//callback->processOverlap(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.quickSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+ #endif//CLEAN_INVALID_PAIRS
+
+ }
+ }
}
+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..49dfeb84900 100644
--- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
+++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
@@ -24,35 +24,78 @@ 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),
+ btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy)
+ :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy),
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
-class btSimpleBroadphase : public btOverlappingPairCache
+///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead.
+///It is a brute force aabb culling broadphase based on O(n^2) aabb checks
+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
+ void* m_pHandlesRawPtr;
+ 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,26 +110,48 @@ 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,void* multiSapProxy);
+ 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);
+ ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+ ///will add some transform later
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ aabbMin.setValue(-1e30f,-1e30f,-1e30f);
+ aabbMax.setValue(1e30f,1e30f,1e30f);
+ }
+ virtual void printStats()
+ {
+// printf("btSimpleBroadphase.h\n");
+// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+ }
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
index 81133670f0c..f6c1e32ac7c 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
@@ -26,7 +26,7 @@ m_triangle(triangle)
}
-void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
+void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
{
(void)debugDraw;
@@ -42,7 +42,16 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res
if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact))
{
- output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
+ if (swapResults)
+ {
+ btVector3 normalOnB = transformB.getBasis()*normal;
+ btVector3 normalOnA = -normalOnB;
+ btVector3 pointOnA = transformB*point+normalOnB*depth;
+ output.addContactPoint(normalOnA,pointOnA,depth);
+ } else
+ {
+ output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
+ }
}
}
@@ -53,6 +62,8 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res
// 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);
+
btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
btVector3 diff = p - from;
btVector3 v = to - from;
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
index b32806a6846..26dabaa480e 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;
@@ -28,7 +28,7 @@ class btTriangleShape;
/// sphere-triangle to match the btDiscreteCollisionDetectorInterface
struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface
{
- virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw);
+ virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle);
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
new file mode 100644
index 00000000000..cd0c028012c
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.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 "btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "btBoxBoxDetector.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
+: btCollisionAlgorithm(ci),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
+ {
+ m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
+ m_ownManifold = true;
+ }
+}
+
+btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
+{
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+}
+
+void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ if (!m_manifoldPtr)
+ return;
+
+ btCollisionObject* col0 = body0;
+ btCollisionObject* col1 = body1;
+ btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
+ btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();
+
+
+
+ /// report a contact. internally this will be kept persistent, and contact reduction is done
+ resultOut->setPersistentManifold(m_manifoldPtr);
+#ifndef USE_PERSISTENT_CONTACTS
+ m_manifoldPtr->clearManifold();
+#endif //USE_PERSISTENT_CONTACTS
+
+ btDiscreteCollisionDetectorInterface::ClosestPointInput input;
+ input.m_maximumDistanceSquared = 1e30f;
+ input.m_transformA = body0->getWorldTransform();
+ input.m_transformB = body1->getWorldTransform();
+
+ btBoxBoxDetector detector(box0,box1);
+ detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+#ifdef USE_PERSISTENT_CONTACTS
+ // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
+ if (m_ownManifold)
+ {
+ resultOut->refreshContactPoints();
+ }
+#endif //USE_PERSISTENT_CONTACTS
+
+}
+
+btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+ //not yet
+ return 1.f;
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
new file mode 100644
index 00000000000..35afaf175a1
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 BOX_BOX__COLLISION_ALGORITHM_H
+#define BOX_BOX__COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+
+///box-box collision detection
+class btBoxBoxCollisionAlgorithm : public btCollisionAlgorithm
+{
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+
+public:
+ btBoxBoxCollisionAlgorithm(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);
+
+ btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+ virtual ~btBoxBoxCollisionAlgorithm();
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
+
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ {
+ int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
+ void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+ return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1);
+ }
+ };
+
+};
+
+#endif //BOX_BOX__COLLISION_ALGORITHM_H
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
new file mode 100644
index 00000000000..e55604632c0
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
@@ -0,0 +1,683 @@
+
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved. Email: russ@q12.org Web: www.q12.org
+ Bullet Continuous Collision Detection and Physics Library
+ Bullet is Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///ODE box-box collision detection is adapted to work with Bullet
+
+#include "btBoxBoxDetector.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+
+#include <float.h>
+#include <string.h>
+
+btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2)
+: m_box1(box1),
+m_box2(box2)
+{
+
+}
+
+
+// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and
+// generate contact points. this returns 0 if there is no contact otherwise
+// it returns the number of contacts generated.
+// `normal' returns the contact normal.
+// `depth' returns the maximum penetration depth along that normal.
+// `return_code' returns a number indicating the type of contact that was
+// detected:
+// 1,2,3 = box 2 intersects with a face of box 1
+// 4,5,6 = box 1 intersects with a face of box 2
+// 7..15 = edge-edge contact
+// `maxc' is the maximum number of contacts allowed to be generated, i.e.
+// the size of the `contact' array.
+// `contact' and `skip' are the contact array information provided to the
+// collision functions. this function only fills in the position and depth
+// fields.
+struct dContactGeom;
+#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
+#define dInfinity FLT_MAX
+
+
+/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); }
+PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); }
+PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); }
+*/
+static btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); }
+static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); }
+static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); }
+#define dMULTIPLYOP1_331(A,op,B,C) \
+{\
+ (A)[0] op dDOT41((B),(C)); \
+ (A)[1] op dDOT41((B+1),(C)); \
+ (A)[2] op dDOT41((B+2),(C)); \
+}
+
+#define dMULTIPLYOP0_331(A,op,B,C) \
+{ \
+ (A)[0] op dDOT((B),(C)); \
+ (A)[1] op dDOT((B+4),(C)); \
+ (A)[2] op dDOT((B+8),(C)); \
+}
+
+#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
+#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
+
+typedef btScalar dMatrix3[4*3];
+
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+ const btVector3& pb, const btVector3& ub,
+ btScalar *alpha, btScalar *beta);
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+ const btVector3& pb, const btVector3& ub,
+ btScalar *alpha, btScalar *beta)
+{
+ btVector3 p;
+ p[0] = pb[0] - pa[0];
+ p[1] = pb[1] - pa[1];
+ p[2] = pb[2] - pa[2];
+ btScalar uaub = dDOT(ua,ub);
+ btScalar q1 = dDOT(ua,p);
+ btScalar q2 = -dDOT(ub,p);
+ btScalar d = 1-uaub*uaub;
+ if (d <= btScalar(0.0001f)) {
+ // @@@ this needs to be made more robust
+ *alpha = 0;
+ *beta = 0;
+ }
+ else {
+ d = 1.f/d;
+ *alpha = (q1 + uaub*q2)*d;
+ *beta = (uaub*q1 + q2)*d;
+ }
+}
+
+
+
+// find all the intersection points between the 2D rectangle with vertices
+// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
+// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
+//
+// the intersection points are returned as x,y pairs in the 'ret' array.
+// the number of intersection points is returned by the function (this will
+// be in the range 0 to 8).
+
+static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16])
+{
+ // q (and r) contain nq (and nr) coordinate points for the current (and
+ // chopped) polygons
+ int nq=4,nr=0;
+ btScalar buffer[16];
+ btScalar *q = p;
+ btScalar *r = ret;
+ for (int dir=0; dir <= 1; dir++) {
+ // direction notation: xy[0] = x axis, xy[1] = y axis
+ for (int sign=-1; sign <= 1; sign += 2) {
+ // chop q along the line xy[dir] = sign*h[dir]
+ btScalar *pq = q;
+ btScalar *pr = r;
+ nr = 0;
+ for (int i=nq; i > 0; i--) {
+ // go through all points in q and all lines between adjacent points
+ if (sign*pq[dir] < h[dir]) {
+ // this point is inside the chopping line
+ pr[0] = pq[0];
+ pr[1] = pq[1];
+ pr += 2;
+ nr++;
+ if (nr & 8) {
+ q = r;
+ goto done;
+ }
+ }
+ btScalar *nextq = (i > 1) ? pq+2 : q;
+ if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) {
+ // this line crosses the chopping line
+ pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
+ (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
+ pr[dir] = sign*h[dir];
+ pr += 2;
+ nr++;
+ if (nr & 8) {
+ q = r;
+ goto done;
+ }
+ }
+ pq += 2;
+ }
+ q = r;
+ r = (q==ret) ? buffer : ret;
+ nq = nr;
+ }
+ }
+ done:
+ if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar));
+ return nr;
+}
+
+
+#define M__PI 3.14159265f
+
+// given n points in the plane (array p, of size 2*n), generate m points that
+// best represent the whole set. the definition of 'best' here is not
+// predetermined - the idea is to select points that give good box-box
+// collision detection behavior. the chosen point indexes are returned in the
+// array iret (of size m). 'i0' is always the first entry in the array.
+// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
+// in the range [0..n-1].
+
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]);
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[])
+{
+ // compute the centroid of the polygon in cx,cy
+ int i,j;
+ btScalar a,cx,cy,q;
+ if (n==1) {
+ cx = p[0];
+ cy = p[1];
+ }
+ else if (n==2) {
+ cx = btScalar(0.5)*(p[0] + p[2]);
+ cy = btScalar(0.5)*(p[1] + p[3]);
+ }
+ else {
+ a = 0;
+ cx = 0;
+ cy = 0;
+ for (i=0; i<(n-1); i++) {
+ q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
+ a += q;
+ cx += q*(p[i*2]+p[i*2+2]);
+ cy += q*(p[i*2+1]+p[i*2+3]);
+ }
+ q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
+ a = 1.f/(btScalar(3.0)*(a+q));
+ cx = a*(cx + q*(p[n*2-2]+p[0]));
+ cy = a*(cy + q*(p[n*2-1]+p[1]));
+ }
+
+ // compute the angle of each point w.r.t. the centroid
+ btScalar A[8];
+ for (i=0; i<n; i++) A[i] = btAtan2(p[i*2+1]-cy,p[i*2]-cx);
+
+ // search for points that have angles closest to A[i0] + i*(2*pi/m).
+ int avail[8];
+ for (i=0; i<n; i++) avail[i] = 1;
+ avail[i0] = 0;
+ iret[0] = i0;
+ iret++;
+ for (j=1; j<m; j++) {
+ a = btScalar(j)*(2*M__PI/m) + A[i0];
+ if (a > M__PI) a -= 2*M__PI;
+ btScalar maxdiff=1e9,diff;
+#ifndef dNODEBUG
+ *iret = i0; // iret is not allowed to keep this value
+#endif
+ for (i=0; i<n; i++) {
+ if (avail[i]) {
+ diff = btFabs (A[i]-a);
+ if (diff > M__PI) diff = 2*M__PI - diff;
+ if (diff < maxdiff) {
+ maxdiff = diff;
+ *iret = i;
+ }
+ }
+ }
+#ifndef dNODEBUG
+ btAssert (*iret != i0); // ensure iret got set
+#endif
+ avail[*iret] = 0;
+ iret++;
+ }
+}
+
+
+
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+ const btVector3& side1, const btVector3& p2,
+ const dMatrix3 R2, const btVector3& side2,
+ btVector3& normal, btScalar *depth, int *return_code,
+ int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output);
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+ const btVector3& side1, const btVector3& p2,
+ const dMatrix3 R2, const btVector3& side2,
+ btVector3& normal, btScalar *depth, int *return_code,
+ int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output)
+{
+ const btScalar fudge_factor = btScalar(1.05);
+ btVector3 p,pp,normalC;
+ const btScalar *normalR = 0;
+ btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33,
+ Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l;
+ int i,j,invert_normal,code;
+
+ // get vector from centers of box 1 to box 2, relative to box 1
+ p = p2 - p1;
+ dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1
+
+ // get side lengths / 2
+ A[0] = side1[0]*btScalar(0.5);
+ A[1] = side1[1]*btScalar(0.5);
+ A[2] = side1[2]*btScalar(0.5);
+ B[0] = side2[0]*btScalar(0.5);
+ B[1] = side2[1]*btScalar(0.5);
+ B[2] = side2[2]*btScalar(0.5);
+
+ // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
+ R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
+ R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
+ R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
+
+ Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13);
+ Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23);
+ Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33);
+
+ // for all 15 possible separating axes:
+ // * see if the axis separates the boxes. if so, return 0.
+ // * find the depth of the penetration along the separating axis (s2)
+ // * if this is the largest depth so far, record it.
+ // the normal vector will be set to the separating axis with the smallest
+ // depth. note: normalR is set to point to a column of R1 or R2 if that is
+ // the smallest depth normal so far. otherwise normalR is 0 and normalC is
+ // set to a vector relative to body 1. invert_normal is 1 if the sign of
+ // the normal should be flipped.
+
+#define TST(expr1,expr2,norm,cc) \
+ s2 = btFabs(expr1) - (expr2); \
+ if (s2 > 0) return 0; \
+ if (s2 > s) { \
+ s = s2; \
+ normalR = norm; \
+ invert_normal = ((expr1) < 0); \
+ code = (cc); \
+ }
+
+ s = -dInfinity;
+ invert_normal = 0;
+ code = 0;
+
+ // separating axis = u1,u2,u3
+ TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1);
+ TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2);
+ TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3);
+
+ // separating axis = v1,v2,v3
+ TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4);
+ TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5);
+ TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6);
+
+ // note: cross product axes need to be scaled when s is computed.
+ // normal (n1,n2,n3) is relative to box 1.
+#undef TST
+#define TST(expr1,expr2,n1,n2,n3,cc) \
+ s2 = btFabs(expr1) - (expr2); \
+ if (s2 > 0) return 0; \
+ l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
+ if (l > 0) { \
+ s2 /= l; \
+ if (s2*fudge_factor > s) { \
+ s = s2; \
+ normalR = 0; \
+ normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \
+ invert_normal = ((expr1) < 0); \
+ code = (cc); \
+ } \
+ }
+
+ // separating axis = u1 x (v1,v2,v3)
+ TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7);
+ TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8);
+ TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9);
+
+ // separating axis = u2 x (v1,v2,v3)
+ TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10);
+ TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11);
+ TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12);
+
+ // separating axis = u3 x (v1,v2,v3)
+ TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13);
+ TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14);
+ TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15);
+
+#undef TST
+
+ if (!code) return 0;
+
+ // if we get to this point, the boxes interpenetrate. compute the normal
+ // in global coordinates.
+ if (normalR) {
+ normal[0] = normalR[0];
+ normal[1] = normalR[4];
+ normal[2] = normalR[8];
+ }
+ else {
+ dMULTIPLY0_331 (normal,R1,normalC);
+ }
+ if (invert_normal) {
+ normal[0] = -normal[0];
+ normal[1] = -normal[1];
+ normal[2] = -normal[2];
+ }
+ *depth = -s;
+
+ // compute contact point(s)
+
+ if (code > 6) {
+ // an edge from box 1 touches an edge from box 2.
+ // find a point pa on the intersecting edge of box 1
+ btVector3 pa;
+ btScalar sign;
+ for (i=0; i<3; i++) pa[i] = p1[i];
+ for (j=0; j<3; j++) {
+ sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0);
+ for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j];
+ }
+
+ // find a point pb on the intersecting edge of box 2
+ btVector3 pb;
+ for (i=0; i<3; i++) pb[i] = p2[i];
+ for (j=0; j<3; j++) {
+ sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0);
+ for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
+ }
+
+ btScalar alpha,beta;
+ btVector3 ua,ub;
+ for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4];
+ for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4];
+
+ dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta);
+ for (i=0; i<3; i++) pa[i] += ua[i]*alpha;
+ for (i=0; i<3; i++) pb[i] += ub[i]*beta;
+
+ {
+
+ //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
+ //contact[0].depth = *depth;
+ btVector3 pointInWorld;
+
+#ifdef USE_CENTER_POINT
+ for (i=0; i<3; i++)
+ pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5);
+ output.addContactPoint(-normal,pointInWorld,-*depth);
+#else
+ output.addContactPoint(-normal,pb,-*depth);
+#endif //
+ *return_code = code;
+ }
+ return 1;
+ }
+
+ // okay, we have a face-something intersection (because the separating
+ // axis is perpendicular to a face). define face 'a' to be the reference
+ // face (i.e. the normal vector is perpendicular to this) and face 'b' to be
+ // the incident face (the closest face of the other box).
+
+ const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb;
+ if (code <= 3) {
+ Ra = R1;
+ Rb = R2;
+ pa = p1;
+ pb = p2;
+ Sa = A;
+ Sb = B;
+ }
+ else {
+ Ra = R2;
+ Rb = R1;
+ pa = p2;
+ pb = p1;
+ Sa = B;
+ Sb = A;
+ }
+
+ // nr = normal vector of reference face dotted with axes of incident box.
+ // anr = absolute values of nr.
+ btVector3 normal2,nr,anr;
+ if (code <= 3) {
+ normal2[0] = normal[0];
+ normal2[1] = normal[1];
+ normal2[2] = normal[2];
+ }
+ else {
+ normal2[0] = -normal[0];
+ normal2[1] = -normal[1];
+ normal2[2] = -normal[2];
+ }
+ dMULTIPLY1_331 (nr,Rb,normal2);
+ anr[0] = btFabs (nr[0]);
+ anr[1] = btFabs (nr[1]);
+ anr[2] = btFabs (nr[2]);
+
+ // find the largest compontent of anr: this corresponds to the normal
+ // for the indident face. the other axis numbers of the indicent face
+ // are stored in a1,a2.
+ int lanr,a1,a2;
+ if (anr[1] > anr[0]) {
+ if (anr[1] > anr[2]) {
+ a1 = 0;
+ lanr = 1;
+ a2 = 2;
+ }
+ else {
+ a1 = 0;
+ a2 = 1;
+ lanr = 2;
+ }
+ }
+ else {
+ if (anr[0] > anr[2]) {
+ lanr = 0;
+ a1 = 1;
+ a2 = 2;
+ }
+ else {
+ a1 = 0;
+ a2 = 1;
+ lanr = 2;
+ }
+ }
+
+ // compute center point of incident face, in reference-face coordinates
+ btVector3 center;
+ if (nr[lanr] < 0) {
+ for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr];
+ }
+ else {
+ for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr];
+ }
+
+ // find the normal and non-normal axis numbers of the reference box
+ int codeN,code1,code2;
+ if (code <= 3) codeN = code-1; else codeN = code-4;
+ if (codeN==0) {
+ code1 = 1;
+ code2 = 2;
+ }
+ else if (codeN==1) {
+ code1 = 0;
+ code2 = 2;
+ }
+ else {
+ code1 = 0;
+ code2 = 1;
+ }
+
+ // find the four corners of the incident face, in reference-face coordinates
+ btScalar quad[8]; // 2D coordinate of incident face (x,y pairs)
+ btScalar c1,c2,m11,m12,m21,m22;
+ c1 = dDOT14 (center,Ra+code1);
+ c2 = dDOT14 (center,Ra+code2);
+ // optimize this? - we have already computed this data above, but it is not
+ // stored in an easy-to-index format. for now it's quicker just to recompute
+ // the four dot products.
+ m11 = dDOT44 (Ra+code1,Rb+a1);
+ m12 = dDOT44 (Ra+code1,Rb+a2);
+ m21 = dDOT44 (Ra+code2,Rb+a1);
+ m22 = dDOT44 (Ra+code2,Rb+a2);
+ {
+ btScalar k1 = m11*Sb[a1];
+ btScalar k2 = m21*Sb[a1];
+ btScalar k3 = m12*Sb[a2];
+ btScalar k4 = m22*Sb[a2];
+ quad[0] = c1 - k1 - k3;
+ quad[1] = c2 - k2 - k4;
+ quad[2] = c1 - k1 + k3;
+ quad[3] = c2 - k2 + k4;
+ quad[4] = c1 + k1 + k3;
+ quad[5] = c2 + k2 + k4;
+ quad[6] = c1 + k1 - k3;
+ quad[7] = c2 + k2 - k4;
+ }
+
+ // find the size of the reference face
+ btScalar rect[2];
+ rect[0] = Sa[code1];
+ rect[1] = Sa[code2];
+
+ // intersect the incident and reference faces
+ btScalar ret[16];
+ int n = intersectRectQuad2 (rect,quad,ret);
+ if (n < 1) return 0; // this should never happen
+
+ // convert the intersection points into reference-face coordinates,
+ // and compute the contact position and depth for each point. only keep
+ // those points that have a positive (penetrating) depth. delete points in
+ // the 'ret' array as necessary so that 'point' and 'ret' correspond.
+ btScalar point[3*8]; // penetrating contact points
+ btScalar dep[8]; // depths for those points
+ btScalar det1 = 1.f/(m11*m22 - m12*m21);
+ m11 *= det1;
+ m12 *= det1;
+ m21 *= det1;
+ m22 *= det1;
+ int cnum = 0; // number of penetrating contact points found
+ for (j=0; j < n; j++) {
+ btScalar k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
+ btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
+ for (i=0; i<3; i++) point[cnum*3+i] =
+ center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2];
+ dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3);
+ if (dep[cnum] >= 0) {
+ ret[cnum*2] = ret[j*2];
+ ret[cnum*2+1] = ret[j*2+1];
+ cnum++;
+ }
+ }
+ if (cnum < 1) return 0; // this should never happen
+
+ // we can't generate more contacts than we actually have
+ if (maxc > cnum) maxc = cnum;
+ if (maxc < 1) maxc = 1;
+
+ if (cnum <= maxc) {
+ // we have less contacts than we need, so we use them all
+ for (j=0; j < cnum; j++) {
+
+ //AddContactPoint...
+
+ //dContactGeom *con = CONTACT(contact,skip*j);
+ //for (i=0; i<3; i++) con->pos[i] = point[j*3+i] + pa[i];
+ //con->depth = dep[j];
+
+ btVector3 pointInWorld;
+ for (i=0; i<3; i++)
+ pointInWorld[i] = point[j*3+i] + pa[i];
+ output.addContactPoint(-normal,pointInWorld,-dep[j]);
+
+ }
+ }
+ else {
+ // we have more contacts than are wanted, some of them must be culled.
+ // find the deepest point, it is always the first contact.
+ int i1 = 0;
+ btScalar maxdepth = dep[0];
+ for (i=1; i<cnum; i++) {
+ if (dep[i] > maxdepth) {
+ maxdepth = dep[i];
+ i1 = i;
+ }
+ }
+
+ int iret[8];
+ cullPoints2 (cnum,ret,maxc,i1,iret);
+
+ for (j=0; j < maxc; j++) {
+// dContactGeom *con = CONTACT(contact,skip*j);
+ // for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i];
+ // con->depth = dep[iret[j]];
+
+ btVector3 posInWorld;
+ for (i=0; i<3; i++)
+ posInWorld[i] = point[iret[j]*3+i] + pa[i];
+ output.addContactPoint(-normal,posInWorld,-dep[iret[j]]);
+ }
+ cnum = maxc;
+ }
+
+ *return_code = code;
+ return cnum;
+}
+
+void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/)
+{
+
+ const btTransform& transformA = input.m_transformA;
+ const btTransform& transformB = input.m_transformB;
+
+ int skip = 0;
+ dContactGeom *contact = 0;
+
+ dMatrix3 R1;
+ dMatrix3 R2;
+
+ for (int j=0;j<3;j++)
+ {
+ R1[0+4*j] = transformA.getBasis()[j].x();
+ R2[0+4*j] = transformB.getBasis()[j].x();
+
+ R1[1+4*j] = transformA.getBasis()[j].y();
+ R2[1+4*j] = transformB.getBasis()[j].y();
+
+
+ R1[2+4*j] = transformA.getBasis()[j].z();
+ R2[2+4*j] = transformB.getBasis()[j].z();
+
+ }
+
+
+
+ btVector3 normal;
+ btScalar depth;
+ int return_code;
+ int maxc = 4;
+
+
+ dBoxBox2 (transformA.getOrigin(),
+ R1,
+ 2.f*m_box1->getHalfExtentsWithMargin(),
+ transformB.getOrigin(),
+ R2,
+ 2.f*m_box2->getHalfExtentsWithMargin(),
+ normal, &depth, &return_code,
+ maxc, contact, skip,
+ output
+ );
+
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
new file mode 100644
index 00000000000..605294d47bd
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
@@ -0,0 +1,44 @@
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved. Email: russ@q12.org Web: www.q12.org
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 BOX_BOX_DETECTOR_H
+#define BOX_BOX_DETECTOR_H
+
+
+class btBoxShape;
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+
+/// btBoxBoxDetector wraps the ODE box-box collision detector
+/// re-distributed under the Zlib license with permission from Russell L. Smith
+struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
+{
+ btBoxShape* m_box1;
+ btBoxShape* m_box2;
+
+public:
+
+ btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2);
+
+ virtual ~btBoxBoxDetector() {};
+
+ virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+};
+
+#endif //BT_BOX_BOX_DETECTOR_H
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<class btCollisionObject*> 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..a031a9f9784 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
@@ -19,69 +19,39 @@ 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;
+#ifdef BT_DEBUG
#include <stdio.h>
+#endif
-
-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;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
- {
- for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
- {
- m_doubleDispatch[i][j] = m_emptyCreateFunc;
- }
- }
-}
-//if you want to not link with the default collision algorithms, you can
-//define BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
-//in your Bullet library build system
-#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
-
-btCollisionDispatcher::btCollisionDispatcher ():
+btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration):
m_count(0),
- m_useIslands(true)
+ m_useIslands(true),
+ m_staticWarningReported(false),
+ m_collisionConfiguration(collisionConfiguration)
{
int i;
setNearCallback(defaultNearCallback);
- //default CreationFunctions, filling the m_doubleDispatch table
- m_convexConvexCreateFunc = new btConvexConvexAlgorithm::CreateFunc;
- m_convexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::CreateFunc;
- m_swappedConvexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
- m_compoundCreateFunc = new btCompoundCollisionAlgorithm::CreateFunc;
- m_swappedCompoundCreateFunc = new btCompoundCollisionAlgorithm::SwappedCreateFunc;
- m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc;
+ m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
+
+ m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
{
for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
{
- m_doubleDispatch[i][j] = internalFindCreateFunc(i,j);
+ m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
assert(m_doubleDispatch[i][j]);
}
}
@@ -89,8 +59,6 @@ btCollisionDispatcher::btCollisionDispatcher ():
};
-#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION
-
void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
{
@@ -99,12 +67,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 +79,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 +110,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->freeMemory(manifold);
+ } else
+ {
+ btAlignedFree(manifold);
}
}
@@ -152,99 +131,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_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;
-}
+ ci.m_dispatcher1 = this;
+ ci.m_manifold = sharedManifold;
+ btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
-#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;
+ return algo;
}
-#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)
{
@@ -264,13 +163,19 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO
bool needsCollision = true;
- //broadphase filtering already deals with this
- if ((body0->isStaticObject() || body0->isKinematicObject()) &&
- (body1->isStaticObject() || body1->isKinematicObject()))
+#ifdef BT_DEBUG
+ if (!m_staticWarningReported)
{
- printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
+ //broadphase filtering already deals with this
+ if ((body0->isStaticObject() || body0->isKinematicObject()) &&
+ (body1->isStaticObject() || body1->isKinematicObject()))
+ {
+ m_staticWarningReported = true;
+ printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
+ }
}
-
+#endif //BT_DEBUG
+
if ((!body0->isActive()) && (!body1->isActive()))
needsCollision = false;
else if (!body0->checkCollideWith(body1))
@@ -286,23 +191,25 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO
///this is useful for the collision dispatcher.
class btCollisionPairCallback : public btOverlapCallback
{
- btDispatcherInfo& m_dispatchInfo;
+ const btDispatcherInfo& m_dispatchInfo;
btCollisionDispatcher* m_dispatcher;
public:
- btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
+ btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher)
:m_dispatchInfo(dispatchInfo),
m_dispatcher(dispatcher)
{
}
- btCollisionPairCallback& operator=(btCollisionPairCallback& other)
+ /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
{
m_dispatchInfo = other.m_dispatchInfo;
m_dispatcher = other.m_dispatcher;
return *this;
}
+ */
+
virtual ~btCollisionPairCallback() {}
@@ -316,13 +223,14 @@ public:
};
-void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)
+
+void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)
{
//m_blockedForChanges = true;
btCollisionPairCallback collisionCallback(dispatchInfo,this);
- pairCache->processAllOverlappingPairs(&collisionCallback);
+ pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
//m_blockedForChanges = false;
@@ -332,7 +240,7 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa
//by default, Bullet will use this near callback
-void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo)
+void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
{
btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
@@ -365,3 +273,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(static_cast<size_t>(size), 16);
+}
+
+void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
+{
+ if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
+ {
+ m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
+ } else
+ {
+ btAlignedFree(ptr);
+ }
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
index ca5aba8f01c..a9c9cd414c1 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"
@@ -34,7 +35,7 @@ class btOverlappingPairCache;
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);
+typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
@@ -46,26 +47,22 @@ class btCollisionDispatcher : public btDispatcher
btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
bool m_useIslands;
+
+ bool m_staticWarningReported;
btManifoldResult m_defaultManifoldResult;
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 +89,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 +107,7 @@ public:
virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1);
- virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo);
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
void setNearCallback(btNearCallback nearCallback)
{
@@ -127,7 +120,26 @@ public:
}
//by default, Bullet will use this near callback
- static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo);
+ static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const 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;
+ }
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
index d4c0a4e8cb3..d1641249568 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp
@@ -13,15 +13,22 @@ 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_rootCollisionShape(0),
+ m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
+ m_islandTag1(-1),
+ m_companionId(-1),
m_activationState1(1),
m_deactivationTime(btScalar(0.)),
+ m_friction(btScalar(0.5)),
+ m_restitution(btScalar(0.)),
m_userObjectPointer(0),
+ m_internalType(CO_COLLISION_OBJECT),
m_hitFraction(btScalar(1.)),
m_ccdSweptSphereRadius(btScalar(0.)),
m_ccdSquareMotionThreshold(btScalar(0.)),
@@ -55,3 +62,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..96cbd1c3eb8 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"
@@ -50,6 +51,11 @@ protected:
btVector3 m_interpolationAngularVelocity;
btBroadphaseProxy* m_broadphaseHandle;
btCollisionShape* m_collisionShape;
+
+ ///m_rootCollisionShape is temporarily used to store the original collision shape
+ ///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes
+ ///If it is NULL, the m_collisionShape is not temporarily replaced.
+ btCollisionShape* m_rootCollisionShape;
int m_collisionFlags;
@@ -65,8 +71,9 @@ protected:
///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;
+ ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody etc.
+ ///do not assign your own m_internalType unless you write a new dynamics object class.
+ int m_internalType;
///time of impact calculation
btScalar m_hitFraction;
@@ -82,13 +89,15 @@ protected:
char m_pad[7];
- virtual bool checkCollideWithOverride(btCollisionObject* co)
+ virtual bool checkCollideWithOverride(btCollisionObject* /* co */)
{
return true;
}
public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
enum CollisionFlags
{
CF_STATIC_OBJECT= 1,
@@ -97,29 +106,35 @@ public:
CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution)
};
+ enum CollisionObjectTypes
+ {
+ CO_COLLISION_OBJECT =1,
+ CO_RIGID_BODY,
+ CO_SOFT_BODY
+ };
- 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;
}
@@ -131,20 +146,35 @@ public:
void setCollisionShape(btCollisionShape* collisionShape)
{
m_collisionShape = collisionShape;
+ m_rootCollisionShape = 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;
}
-
+ SIMD_FORCE_INLINE const btCollisionShape* getRootCollisionShape() const
+ {
+ return m_rootCollisionShape;
+ }
+ SIMD_FORCE_INLINE btCollisionShape* getRootCollisionShape()
+ {
+ return m_rootCollisionShape;
+ }
+
+ ///Avoid using this internal API call
+ ///internalSetTemporaryCollisionShape is used to temporary replace the actual collision shape by a child collision shape.
+ void internalSetTemporaryCollisionShape(btCollisionShape* collisionShape)
+ {
+ m_collisionShape = collisionShape;
+ }
int getActivationState() const { return m_activationState1;}
@@ -186,14 +216,9 @@ public:
}
///reserved for Bullet internal usage
- void* getInternalOwner()
+ int getInternalType() const
{
- return m_internalOwner;
- }
-
- const void* getInternalOwner() const
- {
- return m_internalOwner;
+ return m_internalType;
}
btTransform& getWorldTransform()
@@ -331,6 +356,7 @@ public:
m_userObjectPointer = userPointer;
}
+
inline bool checkCollideWith(btCollisionObject* co)
{
if (m_checkCollideWith)
@@ -338,9 +364,6 @@ public:
return true;
}
-
-
-}
-;
+};
#endif //COLLISION_OBJECT_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
index 7dc7d8d2f68..7c2ecd6098a 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.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,59 +18,57 @@ subject to the following restrictions:
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
-
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
-#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" //for raycasting
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.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,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_debugDrawer(0)
{
- 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;
for (i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* collisionObject= m_collisionObjects[i];
-
+
btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
if (bp)
{
//
// 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,66 +103,100 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho
type,
collisionObject,
collisionFilterGroup,
- collisionFilterMask
+ collisionFilterMask,
+ m_dispatcher1,0
)) ;
-
+
}
+void btCollisionWorld::updateAabbs()
+{
+ BT_PROFILE("updateAabbs");
+
+ btTransform predictedTrans;
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+
+ //only update aabb of active objects
+ if (colObj->isActive())
+ {
+ 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(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
+ } else
+ {
+ //something went wrong, investigate
+ //this assert is unwanted in 3D modelers (danger of loosing work)
+ colObj->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");
+ }
+ }
+ }
+ }
+
+}
void btCollisionWorld::performDiscreteCollisionDetection()
{
- btDispatcherInfo& dispatchInfo = getDispatchInfo();
-
- BEGIN_PROFILE("perform Broadphase Collision Detection");
+ BT_PROFILE("performDiscreteCollisionDetection");
+ btDispatcherInfo& dispatchInfo = getDispatchInfo();
- //update aabb (of all moved objects)
+ updateAabbs();
- btVector3 aabbMin,aabbMax;
- for (int i=0;i<m_collisionObjects.size();i++)
{
- m_collisionObjects[i]->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax);
- m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax);
+ BT_PROFILE("calculateOverlappingPairs");
+ m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
}
- 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");
+ {
+ BT_PROFILE("dispatchAllCollisionPairs");
+ if (dispatcher)
+ dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
+ }
}
+
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);
+ getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
+ getBroadphase()->destroyProxy(bp,m_dispatcher1);
collisionObject->setBroadphaseHandle(0);
}
}
@@ -181,192 +213,457 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback,
- short int collisionFilterMask,
- bool faceNormal)
+ RayResultCallback& resultCallback)
{
-
btSphereShape pointShape(btScalar(0.0));
pointShape.setMargin(0.f);
+ const btConvexShape* castShape = &pointShape;
+
+ if (collisionShape->isConvex())
+ {
+ btConvexCast::CastResult castResult;
+ castResult.m_fraction = resultCallback.m_closestHitFraction;
+
+ 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())
+ {
+ if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ ///optimized version for btBvhTriangleMeshShape
+ btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)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;
+ triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal);
+ } else
+ {
+ btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape;
+
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
- objectQuerySingle(&pointShape,rayFromTrans,rayToTrans,
- collisionObject,
- collisionShape,
- colObjWorldTransform,
- resultCallback,collisionFilterMask,faceNormal);
+ 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<const btCompoundShape*>(collisionShape);
+ int i=0;
+ for (i=0;i<compoundShape->getNumChildShapes();i++)
+ {
+ btTransform childTrans = compoundShape->getChildTransform(i);
+ const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
+ btTransform childWorldTrans = colObjWorldTransform * childTrans;
+ rayTestSingle(rayFromTrans,rayToTrans,
+ collisionObject,
+ childCollisionShape,
+ childWorldTrans,
+ resultCallback);
+
+ }
+ }
+ }
+ }
}
-void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans,
+void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback,
- short int collisionFilterMask,
- bool faceNormal)
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration)
{
-
-
if (collisionShape->isConvex())
+ {
+ btConvexCast::CastResult castResult;
+ castResult.m_allowedPenetration = allowedPenetration;
+ castResult.m_fraction = btScalar(1.);//??
+
+ btConvexShape* convexShape = (btConvexShape*) collisionShape;
+ btVoronoiSimplexSolver simplexSolver;
+ btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
+
+ btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver);
+ //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
+ //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
+
+ btConvexCast* castPtr = &convexCaster1;
+
+
+
+ if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+ {
+ //add hit
+ if (castResult.m_normal.length2() > btScalar(0.0001))
{
- 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))
+ if (castResult.m_fraction < resultCallback.m_closestHitFraction)
{
- //add hit
- if (castResult.m_normal.length2() > btScalar(0.0001))
- {
- castResult.m_normal.normalize();
- if (castResult.m_fraction < resultCallback.m_closestHitFraction)
- {
-
- btCollisionWorld::LocalRayResult localRayResult
+ castResult.m_normal.normalize();
+ btCollisionWorld::LocalConvexResult localConvexResult
(
- collisionObject,
+ collisionObject,
0,
castResult.m_normal,
+ castResult.m_hitPoint,
castResult.m_fraction
);
- resultCallback.AddSingleResult(localRayResult);
+ bool normalInWorldSpace = true;
+ resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
- }
- }
}
}
- else
+ }
+ } else {
+ if (collisionShape->isConcave())
+ {
+ if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
{
-
- if (collisionShape->isConcave())
+ btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+ btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
+ btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
+ // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
+ btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
+
+ //ConvexCast::CastResult
+ struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
+ {
+ btCollisionWorld::ConvexResultCallback* m_resultCallback;
+ btCollisionObject* m_collisionObject;
+ btTriangleMeshShape* m_triangleMesh;
+
+ BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
+ btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
+ btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh)
+ {
+ }
+
+
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
{
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = partId;
+ shapeInfo.m_triangleIndex = triangleIndex;
+ if (hitFraction <= m_resultCallback->m_closestHitFraction)
+ {
- btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape;
-
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+ btCollisionWorld::LocalConvexResult convexResult
+ (m_collisionObject,
+ &shapeInfo,
+ hitNormalLocal,
+ hitPointLocal,
+ hitFraction);
- btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
- btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+ bool normalInWorldSpace = true;
- //ConvexCast::CastResult
- struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
- {
- btCollisionWorld::RayResultCallback* m_resultCallback;
- btCollisionObject* m_collisionObject;
- btTriangleMeshShape* m_triangleMesh;
-
- BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,bool faceNormal,
- btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh):
- btTriangleRaycastCallback(from,to,faceNormal),
- 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;
- shapeInfo.m_triangleShape = m_triangleMesh;
-
- btCollisionWorld::LocalRayResult rayResult
- (m_collisionObject,
- &shapeInfo,
- hitNormalLocal,
- hitFraction);
-
- return m_resultCallback->AddSingleResult(rayResult);
-
-
- }
-
- };
+ return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
+ }
+ return hitFraction;
+ }
+ };
- BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,faceNormal,&resultCallback,collisionObject,triangleMesh);
- rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+ BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
+ tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+ btVector3 boxMinLocal, boxMaxLocal;
+ castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+ triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
+ } else
+ {
+ btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+ btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+ btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
+ btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
+ // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
+ btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
+
+ //ConvexCast::CastResult
+ struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
+ {
+ btCollisionWorld::ConvexResultCallback* m_resultCallback;
+ btCollisionObject* m_collisionObject;
+ btTriangleMeshShape* m_triangleMesh;
+
+ BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
+ btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld):
+ btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
+ m_resultCallback(resultCallback),
+ m_collisionObject(collisionObject),
+ m_triangleMesh(triangleMesh)
+ {
+ }
- btVector3 rayAabbMinLocal = rayFromLocal;
- rayAabbMinLocal.setMin(rayToLocal);
- btVector3 rayAabbMaxLocal = rayFromLocal;
- rayAabbMaxLocal.setMax(rayToLocal);
- triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
-
- } else
+ virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
{
- //todo: use AABB tree or other BVH acceleration structure!
- if (collisionShape->isCompound())
+ btCollisionWorld::LocalShapeInfo shapeInfo;
+ shapeInfo.m_shapePart = partId;
+ shapeInfo.m_triangleIndex = triangleIndex;
+ if (hitFraction <= m_resultCallback->m_closestHitFraction)
{
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
- int i=0;
- for (i=0;i<compoundShape->getNumChildShapes();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, faceNormal);
- }
+ btCollisionWorld::LocalConvexResult convexResult
+ (m_collisionObject,
+ &shapeInfo,
+ hitNormalLocal,
+ hitPointLocal,
+ hitFraction);
+ bool normalInWorldSpace = false;
+ return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
}
+ return hitFraction;
}
+
+ };
+
+ BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
+ tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+ btVector3 boxMinLocal, boxMaxLocal;
+ castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+
+ btVector3 rayAabbMinLocal = convexFromLocal;
+ rayAabbMinLocal.setMin(convexToLocal);
+ btVector3 rayAabbMaxLocal = convexFromLocal;
+ rayAabbMaxLocal.setMax(convexToLocal);
+ rayAabbMinLocal += boxMinLocal;
+ rayAabbMaxLocal += boxMaxLocal;
+ triangleMesh->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
}
+ } else {
+ //todo: use AABB tree or other BVH acceleration structure!
+ if (collisionShape->isCompound())
+ {
+ const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
+ int i=0;
+ for (i=0;i<compoundShape->getNumChildShapes();i++)
+ {
+ btTransform childTrans = compoundShape->getChildTransform(i);
+ const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
+ btTransform childWorldTrans = colObjWorldTransform * childTrans;
+ objectQuerySingle(castShape, convexFromTrans,convexToTrans,
+ collisionObject,
+ childCollisionShape,
+ childWorldTrans,
+ resultCallback, allowedPenetration);
+ }
+ }
+ }
+ }
}
-void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask, bool faceNormal)
+void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
{
-
+
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;i<m_collisionObjects.size();i++)
{
+ ///terminate further ray tests, once the closestHitFraction reached zero
+ if (resultCallback.m_closestHitFraction == btScalar(0.f))
+ break;
+
btCollisionObject* collisionObject= m_collisionObjects[i];
//only perform raycast if filterMask matches
- if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) {
+ if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
//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
+ btScalar hitLambda = resultCallback.m_closestHitFraction;
btVector3 hitNormal;
if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
{
- // before testing this object, verify that it is not filtered out
- if (resultCallback.NeedRayCast(collisionObject))
- {
- rayTestSingle(rayFromTrans,rayToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- resultCallback,
- collisionFilterMask,
- faceNormal);
- }
- }
+ rayTestSingle(rayFromTrans,rayToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ resultCallback);
+ }
+ }
+
+ }
+
+}
+
+void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback) const
+{
+ btTransform convexFromTrans,convexToTrans;
+ convexFromTrans = convexFromWorld;
+ convexToTrans = convexToWorld;
+ btVector3 castShapeAabbMin, castShapeAabbMax;
+ /* Compute AABB that encompasses angular movement */
+ {
+ btVector3 linVel, angVel;
+ btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
+ btTransform R;
+ R.setIdentity ();
+ R.setRotation (convexFromTrans.getRotation());
+ castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
+ }
+
+ /// go over all objects, and if the ray intersects their aabb + cast shape aabb,
+ // do a ray-shape query using convexCaster (CCD)
+ int i;
+ for (i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* collisionObject= m_collisionObjects[i];
+ //only perform raycast if filterMask matches
+ if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+ //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+ btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+ collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+ AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
+ btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
+ btVector3 hitNormal;
+ if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
+ {
+ objectQuerySingle(castShape, convexFromTrans,convexToTrans,
+ collisionObject,
+ collisionObject->getCollisionShape(),
+ collisionObject->getWorldTransform(),
+ resultCallback,
+ getDispatchInfo().m_allowedCcdPenetration);
+ }
}
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h
index ed41232ece3..7557691a9a9 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,18 +90,22 @@ protected:
btStackAlloc* m_stackAlloc;
- btOverlappingPairCache* m_broadphasePairCache;
-
- bool m_ownsDispatcher;
- bool m_ownsBroadphasePairCache;
+ btBroadphaseInterface* m_broadphasePairCache;
+
+ btIDebugDraw* m_debugDrawer;
+
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();
+ void setBroadphase(btBroadphaseInterface* pairCache)
+ {
+ m_broadphasePairCache = pairCache;
+ }
btBroadphaseInterface* getBroadphase()
{
@@ -110,7 +114,7 @@ public:
btOverlappingPairCache* getPairCache()
{
- return m_broadphasePairCache;
+ return m_broadphasePairCache->getOverlappingPairCache();
}
@@ -119,14 +123,32 @@ public:
return m_dispatcher1;
}
+ const btDispatcher* getDispatcher() const
+ {
+ return m_dispatcher1;
+ }
+
+ virtual void updateAabbs();
+
+ virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
+ {
+ m_debugDrawer = debugDrawer;
+ }
+
+ virtual btIDebugDraw* getDebugDrawer()
+ {
+ return m_debugDrawer;
+ }
+
+
///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;
- // needed in case of compound shape
- const btCollisionShape* m_triangleShape;
+
+ //const btCollisionShape* m_shapeTemp;
//const btTransform* m_shapeLocalTransform;
};
@@ -153,32 +175,43 @@ public:
///RayResultCallback is used to report new raycast results
struct RayResultCallback
{
+ btScalar m_closestHitFraction;
+ btCollisionObject* m_collisionObject;
+ short int m_collisionFilterGroup;
+ short int m_collisionFilterMask;
+
virtual ~RayResultCallback()
{
}
- btScalar m_closestHitFraction;
- bool HasHit()
+ bool hasHit() const
{
- return (m_closestHitFraction < btScalar(1.));
+ return (m_collisionObject != 0);
}
RayResultCallback()
- :m_closestHitFraction(btScalar(1.))
+ :m_closestHitFraction(btScalar(1.)),
+ m_collisionObject(0),
+ m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+ m_collisionFilterMask(btBroadphaseProxy::AllFilter)
{
}
- virtual bool NeedRayCast(btCollisionObject* object)
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
{
- return true;
+ bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+ collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+ return collides;
}
- virtual btScalar AddSingleResult(LocalRayResult& rayResult) = 0;
+
+
+ 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)
+ m_rayToWorld(rayToWorld)
{
}
@@ -187,24 +220,121 @@ public:
btVector3 m_hitNormalWorld;
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
- assert(rayResult.m_hitFraction <= m_closestHitFraction);
+ //caller already does the filter on the m_closestHitFraction
+ btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
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;
}
};
-
+ struct LocalConvexResult
+ {
+ LocalConvexResult(btCollisionObject* hitCollisionObject,
+ LocalShapeInfo* localShapeInfo,
+ const btVector3& hitNormalLocal,
+ const btVector3& hitPointLocal,
+ btScalar hitFraction
+ )
+ :m_hitCollisionObject(hitCollisionObject),
+ m_localShapeInfo(localShapeInfo),
+ m_hitNormalLocal(hitNormalLocal),
+ m_hitPointLocal(hitPointLocal),
+ m_hitFraction(hitFraction)
+ {
+ }
+
+ btCollisionObject* m_hitCollisionObject;
+ LocalShapeInfo* m_localShapeInfo;
+ btVector3 m_hitNormalLocal;
+ btVector3 m_hitPointLocal;
+ btScalar m_hitFraction;
+ };
+
+ ///RayResultCallback is used to report new raycast results
+ struct ConvexResultCallback
+ {
+ btScalar m_closestHitFraction;
+ short int m_collisionFilterGroup;
+ short int m_collisionFilterMask;
+
+ ConvexResultCallback()
+ :m_closestHitFraction(btScalar(1.)),
+ m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+ m_collisionFilterMask(btBroadphaseProxy::AllFilter)
+ {
+ }
+
+ virtual ~ConvexResultCallback()
+ {
+ }
+
+ bool hasHit() const
+ {
+ return (m_closestHitFraction < btScalar(1.));
+ }
+
+
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+ collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+ return collides;
+ }
+
+ virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0;
+ };
+
+ struct ClosestConvexResultCallback : public ConvexResultCallback
+ {
+ ClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld)
+ :m_convexFromWorld(convexFromWorld),
+ m_convexToWorld(convexToWorld),
+ m_hitCollisionObject(0)
+ {
+ }
+
+ btVector3 m_convexFromWorld;//used to calculate hitPointWorld from hitFraction
+ btVector3 m_convexToWorld;
+
+ btVector3 m_hitNormalWorld;
+ btVector3 m_hitPointWorld;
+ btCollisionObject* m_hitCollisionObject;
+
+ virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace)
+ {
+//caller already does the filter on the m_closestHitFraction
+ btAssert(convexResult.m_hitFraction <= m_closestHitFraction);
+
+ m_closestHitFraction = convexResult.m_hitFraction;
+ m_hitCollisionObject = convexResult.m_hitCollisionObject;
+ if (normalInWorldSpace)
+ {
+ m_hitNormalWorld = convexResult.m_hitNormalLocal;
+ } else
+ {
+ ///need to transform normal into worldspace
+ m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
+ }
+ m_hitPointWorld = convexResult.m_hitPointLocal;
+ return convexResult.m_hitFraction;
+ }
+ };
int getNumCollisionObjects() const
{
@@ -213,7 +343,12 @@ public:
/// 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, bool faceNormal=false);
+ void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
+
+ // convexTest performs a swept convex cast 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 return by the callback.
+ void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback) const;
+
/// 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.
@@ -222,20 +357,16 @@ public:
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback,
- short int collisionFilterMask=-1,
- bool faceNormal=false);
+ RayResultCallback& resultCallback);
/// 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,
- bool faceNormal=false);
+ ConvexResultCallback& resultCallback, btScalar allowedPenetration);
- void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1);
+ void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter);
btCollisionObjectArray& getCollisionObjectArray()
{
@@ -257,6 +388,11 @@ public:
return m_dispatchInfo;
}
+ const btDispatcherInfo& getDispatchInfo() const
+ {
+ return m_dispatchInfo;
+ }
+
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
index 92f4c8b28a6..a29a6d624e5 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;
@@ -32,11 +33,11 @@ btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlg
m_childCollisionAlgorithms.resize(numChildren);
for (i=0;i<numChildren;i++)
{
+ btCollisionShape* tmpShape = colObj->getCollisionShape();
btCollisionShape* childShape = compoundShape->getChildShape(i);
- btCollisionShape* orgShape = colObj->getCollisionShape();
- colObj->setCollisionShape( childShape );
- m_childCollisionAlgorithms[i] = ci.m_dispatcher->findAlgorithm(colObj,otherObj);
- colObj->setCollisionShape( orgShape );
+ colObj->internalSetTemporaryCollisionShape( childShape );
+ m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj);
+ colObj->internalSetTemporaryCollisionShape( tmpShape );
}
}
@@ -47,7 +48,8 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
int i;
for (i=0;i<numChildren;i++)
{
- delete m_childCollisionAlgorithms[i];
+ m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
+ m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
}
}
@@ -75,17 +77,21 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt
//backup
btTransform orgTrans = colObj->getWorldTransform();
- btCollisionShape* orgShape = colObj->getCollisionShape();
+ btTransform orgInterpolationTrans = colObj->getInterpolationWorldTransform();
const btTransform& childTrans = compoundShape->getChildTransform(i);
- //btTransform newChildWorldTrans = orgTrans*childTrans ;
- colObj->setWorldTransform( orgTrans*childTrans );
+ btTransform newChildWorldTrans = orgTrans*childTrans ;
+ colObj->setWorldTransform( newChildWorldTrans);
+ colObj->setInterpolationWorldTransform(newChildWorldTrans);
+
//the contactpoint is still projected back using the original inverted worldtrans
- colObj->setCollisionShape( childShape );
+ btCollisionShape* tmpShape = colObj->getCollisionShape();
+ colObj->internalSetTemporaryCollisionShape( childShape );
m_childCollisionAlgorithms[i]->processCollision(colObj,otherObj,dispatchInfo,resultOut);
//revert back
- colObj->setCollisionShape( orgShape);
+ colObj->internalSetTemporaryCollisionShape( tmpShape);
colObj->setWorldTransform( orgTrans );
+ colObj->setInterpolationWorldTransform(orgInterpolationTrans);
}
}
@@ -117,20 +123,20 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject*
//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 );
+ btCollisionShape* tmpShape = colObj->getCollisionShape();
+ colObj->internalSetTemporaryCollisionShape( childShape );
btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
if (frac<hitFraction)
{
hitFraction = frac;
}
//revert back
- colObj->setCollisionShape( orgShape);
+ colObj->internalSetTemporaryCollisionShape( tmpShape);
colObj->setWorldTransform( orgTrans);
}
return hitFraction;
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
index 7091b233b46..1682c6761cd 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
@@ -43,11 +44,21 @@ public:
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ int i;
+ for (i=0;i<m_childCollisionAlgorithms.size();i++)
+ {
+ m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
+ }
+ }
+
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
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 +66,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..6d28904cb03 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)
{
}
@@ -37,6 +37,13 @@ btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
{
}
+void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
+{
+ if (m_btConvexTriangleCallback.m_manifoldPtr)
+ {
+ manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr);
+ }
+}
btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
@@ -79,7 +86,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<btCollisionObject*>(m_triBody);
@@ -109,13 +116,11 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i
{
btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
tm.setMargin(m_collisionMarginTriangle);
-
btCollisionShape* tmpShape = ob->getCollisionShape();
- ob->setCollisionShape( &tm );
+ ob->internalSetTemporaryCollisionShape( &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,12 +128,11 @@ 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;
- ob->setCollisionShape( tmpShape );
-
+ colAlgo->~btCollisionAlgorithm();
+ ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
+ ob->internalSetTemporaryCollisionShape( tmpShape);
}
-
}
@@ -188,9 +192,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..34b9a107be9 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;
}
@@ -88,13 +88,16 @@ public:
btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
+
void clearCache();
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
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 +105,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..cb830f889be 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
@@ -15,7 +15,7 @@ subject to the following restrictions:
#include "btConvexConvexAlgorithm.h"
-#include <stdio.h>
+//#include <stdio.h>
#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
@@ -33,7 +33,6 @@ subject to the following restrictions:
-#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
@@ -48,26 +47,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 +141,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..a0030e6793d 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;
@@ -46,6 +47,14 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ ///should we use m_ownManifold to avoid adding duplicates?
+ if (m_manifoldPtr && m_ownManifold)
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+
+
void setLowLevelOfDetail(bool useLowLevel);
@@ -58,15 +67,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/btConvexPlaneCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
new file mode 100644
index 00000000000..391cf6c7bc4
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
@@ -0,0 +1,108 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btConvexPlaneCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+//#include <stdio.h>
+
+btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
+: btCollisionAlgorithm(ci),
+m_ownManifold(false),
+m_manifoldPtr(mf),
+m_isSwapped(isSwapped)
+{
+ btCollisionObject* convexObj = m_isSwapped? col1 : col0;
+ btCollisionObject* planeObj = m_isSwapped? col0 : col1;
+
+ if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj))
+ {
+ m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj);
+ m_ownManifold = true;
+ }
+}
+
+
+btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
+{
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+}
+
+
+
+void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)dispatchInfo;
+ (void)resultOut;
+ if (!m_manifoldPtr)
+ return;
+
+ btCollisionObject* convexObj = m_isSwapped? body1 : body0;
+ btCollisionObject* planeObj = m_isSwapped? body0: body1;
+
+ btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
+ btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
+
+ bool hasCollision = false;
+ const btVector3& planeNormal = planeShape->getPlaneNormal();
+ const btScalar& planeConstant = planeShape->getPlaneConstant();
+ btTransform planeInConvex;
+ planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform();
+ btTransform convexInPlaneTrans;
+ convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform();
+
+ btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
+ btVector3 vtxInPlane = convexInPlaneTrans(vtx);
+ btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
+
+ btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
+ btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected;
+
+ hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
+ resultOut->setPersistentManifold(m_manifoldPtr);
+ if (hasCollision)
+ {
+ /// report a contact. internally this will be kept persistent, and contact reduction is done
+ btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal;
+ btVector3 pOnB = vtxInPlaneWorld;
+ resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
+ }
+ if (m_ownManifold)
+ {
+ if (m_manifoldPtr->getNumContacts())
+ {
+ resultOut->refreshContactPoints();
+ }
+ }
+}
+
+btScalar btConvexPlaneCollisionAlgorithm::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/btConvexPlaneCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
new file mode 100644
index 00000000000..7b258554171
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.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_PLANE_COLLISION_ALGORITHM_H
+#define CONVEX_PLANE_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 btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
+{
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+ bool m_isSwapped;
+
+public:
+
+ btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
+
+ virtual ~btConvexPlaneCollisionAlgorithm();
+
+ 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 void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
+ if (!m_swapped)
+ {
+ return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false);
+ } else
+ {
+ return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true);
+ }
+ }
+ };
+
+};
+
+#endif //CONVEX_PLANE_COLLISION_ALGORITHM_H
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
new file mode 100644
index 00000000000..3f94f4d4eac
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
@@ -0,0 +1,281 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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/btConvexPlaneCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+
+
+
+#include "LinearMath/btStackAlloc.h"
+#include "LinearMath/btPoolAllocator.h"
+
+
+
+
+
+btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
+//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
+{
+
+ void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16);
+ m_simplexSolver = new (mem)btVoronoiSimplexSolver();
+
+#define USE_EPA 1
+#ifdef USE_EPA
+ mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
+ m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
+#else
+ mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16);
+ m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver;
+#endif//USE_EPA
+
+
+ //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;
+
+ mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16);
+ m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc;
+
+ //convex versus plane
+ mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+ m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
+ mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+ m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
+ m_planeConvexCF->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 (constructionInfo.m_stackAlloc)
+ {
+ m_ownsStackAllocator = false;
+ this->m_stackAlloc = constructionInfo.m_stackAlloc;
+ } else
+ {
+ m_ownsStackAllocator = true;
+ void* mem = btAlignedAlloc(sizeof(btStackAlloc),16);
+ m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize);
+ }
+
+ if (constructionInfo.m_persistentManifoldPool)
+ {
+ m_ownsPersistentManifoldPool = false;
+ m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
+ } else
+ {
+ m_ownsPersistentManifoldPool = true;
+ void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+ m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
+ }
+
+ if (constructionInfo.m_collisionAlgorithmPool)
+ {
+ m_ownsCollisionAlgorithmPool = false;
+ m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
+ } else
+ {
+ m_ownsCollisionAlgorithmPool = true;
+ void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+ m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
+ }
+
+
+}
+
+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_boxBoxCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_boxBoxCF);
+
+ m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_convexPlaneCF);
+ m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_planeConvexCF);
+
+ m_simplexSolver->~btVoronoiSimplexSolver();
+ btAlignedFree(m_simplexSolver);
+
+ m_pdSolver->~btConvexPenetrationDepthSolver();
+
+ 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 ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
+ {
+ return m_boxBoxCF;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
+ {
+ return m_convexPlaneCF;
+ }
+
+ if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
+ {
+ return m_planeConvexCF;
+ }
+
+
+
+ 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..0b274d394af
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
@@ -0,0 +1,112 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 btConvexPenetrationDepthSolver;
+
+struct btDefaultCollisionConstructionInfo
+{
+ btStackAlloc* m_stackAlloc;
+ btPoolAllocator* m_persistentManifoldPool;
+ btPoolAllocator* m_collisionAlgorithmPool;
+ int m_defaultMaxPersistentManifoldPoolSize;
+ int m_defaultMaxCollisionAlgorithmPoolSize;
+ int m_defaultStackAllocatorSize;
+
+ btDefaultCollisionConstructionInfo()
+ :m_stackAlloc(0),
+ m_persistentManifoldPool(0),
+ m_collisionAlgorithmPool(0),
+ m_defaultMaxPersistentManifoldPoolSize(65535),
+ m_defaultMaxCollisionAlgorithmPoolSize(65535),
+ m_defaultStackAllocatorSize(5*1024*1024)
+ {
+ }
+};
+
+
+
+///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;
+ btConvexPenetrationDepthSolver* 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_boxBoxCF;
+ btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
+ btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
+ btCollisionAlgorithmCreateFunc* m_planeConvexCF;
+ btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
+
+public:
+
+
+ btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
+
+ virtual ~btDefaultCollisionConfiguration();
+
+ ///memory pools
+ virtual btPoolAllocator* getPersistentManifoldPool()
+ {
+ return m_persistentManifoldPool;
+ }
+
+ virtual btPoolAllocator* getCollisionAlgorithmPool()
+ {
+ return m_collisionAlgorithmPool;
+ }
+
+ virtual btStackAlloc* getStackAllocator()
+ {
+ return m_stackAlloc;
+ }
+
+
+ virtual 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..e54721dec21 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)
@@ -33,13 +34,18 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ }
+
struct CreateFunc :public btCollisionAlgorithmCreateFunc
{
virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
{
(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..d5b12598be2 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp
@@ -79,12 +79,30 @@ 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);
+ //BP mod, store contact triangles.
+ newPt.m_partId0 = m_partId0;
+ newPt.m_partId1 = m_partId1;
+ newPt.m_index0 = m_index0;
+ newPt.m_index1 = m_index1;
+
+ ///todo, check this for any side effects
+ if (insertIndex >= 0)
+ {
+ //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
+ m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
+ } else
+ {
+ insertIndex = m_manifoldPtr->addManifoldPoint(newPt);
+ }
+
//User can override friction and/or restitution
if (gContactAddedCallback &&
//and if either of the two bodies requires custom material
@@ -94,16 +112,8 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b
//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);
+ (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),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..1cc78f76acd 100644
--- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
@@ -1,3 +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 "LinearMath/btScalar.h"
@@ -7,7 +21,7 @@
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
-#include <stdio.h>
+//#include <stdio.h>
#include "LinearMath/btQuickprof.h"
btSimulationIslandManager::btSimulationIslandManager()
@@ -25,17 +39,17 @@ void btSimulationIslandManager::initUnionFind(int n)
}
-void btSimulationIslandManager::findUnions(btDispatcher* dispatcher)
+void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
{
{
- for (int i=0;i<dispatcher->getNumManifolds();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<const btCollisionObject*>(manifold->getBody0());
- const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
+ for (int i=0;i<colWorld->getPairCache()->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 +85,7 @@ void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld
}
// do the union find
- findUnions(dispatcher);
+ findUnions(dispatcher,colWorld);
@@ -129,30 +143,13 @@ class btPersistentManifoldSortPredicate
};
-
-
-
-//
-// todo: this is random access, it can be walked 'cache friendly'!
-//
-void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback)
+void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects)
{
+ BT_PROFILE("islandUnionFindAndQuickSort");
-
- /*if (0)
- {
- int maxNumManifolds = dispatcher->getNumManifolds();
- btCollisionDispatcher* colDis = (btCollisionDispatcher*)dispatcher;
- btPersistentManifold** manifold = colDis->getInternalManifoldPointer();
- callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, 0);
- return;
- }
- */
+ m_islandmanifold.resize(0);
-
- 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
@@ -183,7 +180,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
- printf("error in island management\n");
+// printf("error in island management\n");
}
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
@@ -210,7 +207,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
- printf("error in island management\n");
+// printf("error in island management\n");
}
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
@@ -231,7 +228,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
btCollisionObject* colObj0 = collisionObjects[i];
if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
{
- printf("error in island management\n");
+// printf("error in island management\n");
}
assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
@@ -247,11 +244,17 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
}
}
- btAlignedObjectArray<btPersistentManifold*> islandmanifold;
+
int i;
int maxNumManifolds = dispatcher->getNumManifolds();
- islandmanifold.reserve(maxNumManifolds);
+#define SPLIT_ISLANDS 1
+#ifdef SPLIT_ISLANDS
+
+
+#endif //SPLIT_ISLANDS
+
+
for (i=0;i<maxNumManifolds ;i++)
{
btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
@@ -265,29 +268,52 @@ 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());
+//
+// todo: this is random access, it can be walked 'cache friendly'!
+//
+void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback)
+{
+
+ buildIslands(dispatcher,collisionObjects);
+
+ int endIslandIndex=1;
+ int startIslandIndex;
+ int numElem = getUnionFind().getNumElements();
+
+ BT_PROFILE("processIslands");
+
+#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.quickSort(btPersistentManifoldSortPredicate());
//now process all active islands (sets of manifolds for now)
@@ -296,10 +322,9 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
//int islandId;
- END_PROFILE("islandUnionFindAndHeapSort");
-
- btAlignedObjectArray<btCollisionObject*> islandBodies;
+
+// printf("Start Islands\n");
//traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
@@ -313,7 +338,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
{
int i = getUnionFind().getElement(endIslandIndex).m_sz;
btCollisionObject* colObj0 = collisionObjects[i];
- islandBodies.push_back(colObj0);
+ m_islandBodies.push_back(colObj0);
if (!colObj0->isActive())
islandSleeping = true;
}
@@ -325,12 +350,12 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
if (startManifoldIndex<numManifolds)
{
- int curIslandId = getIslandId(islandmanifold[startManifoldIndex]);
+ int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
if (curIslandId == islandId)
{
- startManifold = &islandmanifold[startManifoldIndex];
+ startManifold = &m_islandmanifold[startManifoldIndex];
- for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(islandmanifold[endManifoldIndex]));endManifoldIndex++)
+ for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
{
}
@@ -342,7 +367,8 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
if (!islandSleeping)
{
- callback->ProcessIsland(&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 +376,9 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,
startManifoldIndex = endManifoldIndex;
}
- islandBodies.resize(0);
+ m_islandBodies.resize(0);
}
+#endif //SPLIT_ISLANDS
+
-
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
index d91ed1c20eb..5f4d54cd803 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<btPersistentManifold*> m_islandmanifold;
+ btAlignedObjectArray<btCollisionObject* > 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);
@@ -55,6 +63,8 @@ public:
void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback);
+ void buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects);
+
};
#endif //SIMULATION_ISLAND_MANAGER_H
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..158f0ffcc74 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.
@@ -40,6 +42,14 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
+
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);
@@ -48,12 +58,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..c9256473c00 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,23 +56,34 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0
btScalar radius0 = sphere0->getRadius();
btScalar radius1 = sphere1->getRadius();
+ //m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
+
///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;
+ btVector3 normalOnSurfaceB(1,0,0);
+ if (len > SIMD_EPSILON)
+ {
+ 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);
+ //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..afdc2ee7fa0 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.
@@ -39,6 +41,13 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
virtual ~btSphereSphereCollisionAlgorithm();
@@ -46,7 +55,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..46961f5d61b 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);
@@ -57,11 +60,16 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co
btDiscreteCollisionDetectorInterface::ClosestPointInput input;
input.m_maximumDistanceSquared = btScalar(1e30);//todo: tighter bounds
- input.m_transformA = col0->getWorldTransform();
- input.m_transformB = col1->getWorldTransform();
+ input.m_transformA = sphereObj->getWorldTransform();
+ input.m_transformB = triObj->getWorldTransform();
+
+ bool swapResults = m_swapped && !m_ownManifold;
- detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+ detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults);
+ 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..bbaf228c44c 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.
@@ -40,6 +41,13 @@ public:
virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ {
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+ }
virtual ~btSphereTriangleCollisionAlgorithm();
@@ -49,7 +57,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..bb01b60fa85 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();
@@ -76,8 +77,7 @@ void btUnionFind::sortIslands()
// Sort the vector using predicate and std::sort
//std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
- //perhaps use radix sort?
- m_elements.heapSort(btUnionFindElementSortPredicate());
+ m_elements.quickSort(btUnionFindElementSortPredicate());
}
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..4d4fbefea37 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h
@@ -18,11 +18,11 @@ 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
+///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
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;i<numVectors;i++)
{
const btVector3& vec = vectors[i];
- supportVerticesOut[i].setValue(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());
+ supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+ btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+ btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
}
}
@@ -79,14 +84,38 @@ public:
btBoxShape( const btVector3& boxHalfExtents)
{
- m_implicitShapeDimensions = boxHalfExtents;
+ btVector3 margin(getMargin(),getMargin(),getMargin());
+ m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
};
-
+
+ virtual void setMargin(btScalar collisionMargin)
+ {
+ //correct the m_implicitShapeDimensions for the margin
+ btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+
+ btConvexInternalShape::setMargin(collisionMargin);
+ btVector3 newMargin(getMargin(),getMargin(),getMargin());
+ m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+ }
+ virtual void setLocalScaling(const btVector3& scaling)
+ {
+ btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+ btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+ btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+ btConvexInternalShape::setLocalScaling(scaling);
+
+ m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+ }
+
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i ) const
{
@@ -116,7 +145,7 @@ public:
virtual void getVertex(int i,btVector3& vtx) const
{
- btVector3 halfExtents = getHalfExtents();
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
vtx = btVector3(
halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
@@ -127,7 +156,7 @@ public:
virtual void getPlaneEquation(btVector4& plane,int i) const
{
- btVector3 halfExtents = getHalfExtents();
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
switch (i)
{
@@ -234,7 +263,7 @@ public:
virtual bool isInside(const btPoint3& pt,btScalar tolerance) const
{
- btVector3 halfExtents = getHalfExtents();
+ btVector3 halfExtents = getHalfExtentsWithoutMargin();
//btScalar minDist = 2*tolerance;
@@ -250,7 +279,7 @@ public:
//debugging
- virtual char* getName()const
+ virtual const char* getName()const
{
return "Box";
}
@@ -291,3 +320,4 @@ public:
#endif //OBB_BOX_MINKOWSKI_H
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
index 8da554ef14d..819f6f7f97d 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
@@ -18,32 +18,56 @@ subject to the following restrictions:
#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)
+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
- m_bvh = new btOptimizedBvh();
btVector3 bvhAabbMin,bvhAabbMax;
- meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax);
- m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
+ if(meshInterface->hasPremadeAabb())
+ {
+ meshInterface->getPremadeAabb(&bvhAabbMin, &bvhAabbMax);
+ }
+ else
+ {
+ 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)
-: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
@@ -58,16 +82,140 @@ void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btV
}
-void btBvhTriangleMeshShape::refitTree()
+void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
{
- m_bvh->refit( m_meshInterface );
+ m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
recalcLocalAabb();
}
btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
{
- delete m_bvh;
+ if (m_ownsBvh)
+ {
+ m_bvh->~btOptimizedBvh();
+ btAlignedFree(m_bvh);
+ }
+}
+
+void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
+{
+ struct MyNodeOverlapCallback : public btNodeOverlapCallback
+ {
+ btStridingMeshInterface* m_meshInterface;
+ btTriangleCallback* m_callback;
+
+ MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
+ :m_meshInterface(meshInterface),
+ m_callback(callback)
+ {
+ }
+
+ virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+ {
+ btVector3 m_triangle[3];
+ 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);
+
+ unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+ btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+
+ const btVector3& meshScaling = m_meshInterface->getScaling();
+ for (int j=2;j>=0;j--)
+ {
+ int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+
+ btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
+
+ m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ }
+
+ /* Perform ray vs. triangle collision here */
+ m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+ m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+ }
+ };
+
+ MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
+
+ m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
+}
+
+void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
+{
+ struct MyNodeOverlapCallback : public btNodeOverlapCallback
+ {
+ btStridingMeshInterface* m_meshInterface;
+ btTriangleCallback* m_callback;
+
+ MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
+ :m_meshInterface(meshInterface),
+ m_callback(callback)
+ {
+ }
+
+ virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+ {
+ btVector3 m_triangle[3];
+ 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);
+
+ unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+ btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+
+ const btVector3& meshScaling = m_meshInterface->getScaling();
+ for (int j=2;j>=0;j--)
+ {
+ int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+
+ btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
+
+ m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+ }
+
+ /* Perform ray vs. triangle collision here */
+ m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+ m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+ }
+ };
+
+ MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
+
+ m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
}
//perform bvh tree traversal and report overlapping triangles to 'callback'
@@ -118,13 +266,14 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co
indicestype,
nodeSubPart);
- int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
+ unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+ btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
const btVector3& meshScaling = m_meshInterface->getScaling();
for (int j=2;j>=0;j--)
{
- int graphicsindex = gfxbase[j];
+ int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
#ifdef DEBUG_TRIANGLE_MESH
@@ -157,17 +306,37 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co
}
-
-void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+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);
+ 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);
+ m_ownsBvh = true;
+ }
+}
- }
+void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
+{
+ btAssert(!m_bvh);
+ btAssert(!m_ownsBvh);
+
+ m_bvh = bvh;
+ m_ownsBvh = false;
+ // update the scaling without rebuilding the bvh
+ if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
+ {
+ btTriangleMeshShape::setLocalScaling(scaling);
+ }
}
+
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
index 4914d9f959c..6e587340dc1 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
@@ -18,45 +18,55 @@ 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.
+
+///The btBvhTriangleMeshShape is a static-triangle mesh shape with several optimizations, such as bounding volume hierarchy and cache friendly traversal for PlayStation 3 Cell SPU. It is recommended to enable useQuantizedAabbCompression for better memory usage.
+///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method.
+///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk.
+///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example.
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();
-
- /*
+ bool getOwnsBvh () const
+ {
+ return m_ownsBvh;
+ }
+
virtual int getShapeType() const
{
return TRIANGLE_MESH_SHAPE_PROXYTYPE;
}
- */
-
-
+
+ void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget);
+ void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax);
virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
- void refitTree();
+ void refitTree(const btVector3& aabbMin,const btVector3& aabbMax);
///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 const char* getName()const {return "BVHTRIANGLEMESH";}
virtual void setLocalScaling(const btVector3& scaling);
@@ -65,6 +75,10 @@ public:
{
return m_bvh;
}
+
+
+ void setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1));
+
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..26ba276b900 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp
@@ -21,6 +21,7 @@ subject to the following restrictions:
btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
{
+ m_upAxis = 1;
m_implicitShapeDimensions.setValue(radius,0.5f*height,radius);
}
@@ -50,7 +51,9 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
{
- btVector3 pos(0,getHalfHeight(),0);
+ btVector3 pos(0,0,0);
+ pos[getUpAxis()] = getHalfHeight();
+
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
@@ -60,7 +63,9 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
}
}
{
- btVector3 pos(0,-getHalfHeight(),0);
+ btVector3 pos(0,0,0);
+ pos[getUpAxis()] = -getHalfHeight();
+
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
@@ -88,7 +93,8 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
btVector3 vtx;
btScalar newDot;
{
- btVector3 pos(0,getHalfHeight(),0);
+ btVector3 pos(0,0,0);
+ pos[getUpAxis()] = getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
@@ -98,7 +104,8 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height)
}
}
{
- btVector3 pos(0,-getHalfHeight(),0);
+ btVector3 pos(0,0,0);
+ pos[getUpAxis()] = -getHalfHeight();
vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
newDot = vec.dot(vtx);
if (newDot > maxDot)
@@ -112,7 +119,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
@@ -122,7 +129,8 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
btScalar radius = getRadius();
- btVector3 halfExtents(radius,radius+getHalfHeight(),radius);
+ btVector3 halfExtents(radius,radius,radius);
+ halfExtents[getUpAxis()]+=getHalfHeight();
btScalar margin = CONVEX_DISTANCE_MARGIN;
@@ -140,6 +148,22 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
}
+btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height)
+{
+ m_upAxis = 0;
+ m_implicitShapeDimensions.setValue(0.5f*height, radius,radius);
+}
+
+
+
+
+
+
+btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height)
+{
+ m_upAxis = 2;
+ m_implicitShapeDimensions.setValue(radius,radius,0.5f*height);
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h
index 27da8adefa5..92bcce55119 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h
@@ -16,20 +16,27 @@ 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
+///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis.
+///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres.
+class btCapsuleShape : public btConvexInternalShape
{
+protected:
+ int m_upAxis;
+
+protected:
+ ///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses.
+ btCapsuleShape() {};
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,21 +45,73 @@ public:
virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; }
- virtual char* getName()const
+ virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+ {
+ btVector3 halfExtents(getRadius(),getRadius(),getRadius());
+ halfExtents[m_upAxis] = getRadius() + getHalfHeight();
+ 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;
+ }
+
+ virtual const char* getName()const
{
return "CapsuleShape";
}
+ int getUpAxis() const
+ {
+ return m_upAxis;
+ }
+
btScalar getRadius() const
{
- return m_implicitShapeDimensions.getX();
+ int radiusAxis = (m_upAxis+2)%3;
+ return m_implicitShapeDimensions[radiusAxis];
}
btScalar getHalfHeight() const
{
- return m_implicitShapeDimensions.getY();
+ return m_implicitShapeDimensions[m_upAxis];
+ }
+
+};
+
+///btCapsuleShapeX represents a capsule around the Z axis
+///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+class btCapsuleShapeX : public btCapsuleShape
+{
+public:
+
+ btCapsuleShapeX(btScalar radius,btScalar height);
+
+ //debugging
+ virtual const char* getName()const
+ {
+ return "CapsuleX";
}
+
+
+};
+
+///btCapsuleShapeZ represents a capsule around the Z axis
+///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+class btCapsuleShapeZ : public btCapsuleShape
+{
+public:
+ btCapsuleShapeZ(btScalar radius,btScalar height);
+
+ //debugging
+ virtual const char* getName()const
+ {
+ return "CapsuleZ";
+ }
+
+
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp
index 81d82428f4c..39e621aa946 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp
@@ -21,7 +21,12 @@ subject to the following restrictions:
can be used by probes that are checking whether the
library is actually installed.
*/
-extern "C" void btBulletCollisionProbe () {}
+extern "C"
+{
+void btBulletCollisionProbe ();
+
+void btBulletCollisionProbe () {}
+}
@@ -46,7 +51,7 @@ btScalar btCollisionShape::getAngularMotionDisc() const
return disc;
}
-void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax)
+void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const
{
//start with static aabb
getAabb(curTrans,temporalAabbMin,temporalAabbMax);
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h
index 96268734a83..3a352b90777 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h
@@ -16,18 +16,21 @@ 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.
+///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects.
class btCollisionShape
{
+
+ void* m_userPointer;
+
public:
- btCollisionShape()
+ btCollisionShape() : m_userPointer(0)
{
}
virtual ~btCollisionShape()
@@ -45,30 +48,30 @@ public:
///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);
+ void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const;
#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 +79,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__
@@ -88,6 +91,18 @@ public:
virtual void setMargin(btScalar margin) = 0;
virtual btScalar getMargin() const = 0;
+
+ ///optional user data pointer
+ void setUserPointer(void* userPtr)
+ {
+ m_userPointer = userPtr;
+ }
+
+ void* getUserPointer() const
+ {
+ return m_userPointer;
+ }
+
};
#endif //COLLISION_SHAPE_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp
index a4712b3e925..740f1783630 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;
@@ -55,9 +62,53 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio
}
}
+void btCompoundShape::removeChildShape(btCollisionShape* shape)
+{
+ bool done_removing;
+
+ // Find the children containing the shape specified, and remove those children.
+ do
+ {
+ done_removing = true;
+
+ for(int i = 0; i < m_children.size(); i++)
+ {
+ if(m_children[i].m_childShape == shape)
+ {
+ m_children.remove(m_children[i]);
+ done_removing = false; // Do another iteration pass after removing from the vector
+ break;
+ }
+ }
+ }
+ while (!done_removing);
+
+ recalculateLocalAabb();
+}
-
- ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btCompoundShape::recalculateLocalAabb()
+{
+ // Recalculate the local aabb
+ // Brute force, it iterates over all the shapes left.
+ m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30));
+ m_localAabbMax = btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30));
+
+ //extend the local aabbMin/aabbMax
+ for (int j = 0; j < m_children.size(); j++)
+ {
+ btVector3 localAabbMin,localAabbMax;
+ m_children[j].m_childShape->getAabb(m_children[j].m_transform, 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);
@@ -76,7 +127,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..f77e4b59558 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h
@@ -18,58 +18,95 @@ 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;
+};
+
+SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2)
+{
+ return ( c1.m_transform == c2.m_transform &&
+ c1.m_childShape == c2.m_childShape &&
+ c1.m_childShapeType == c2.m_childShapeType &&
+ c1.m_childMargin == c2.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
+/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape.
+ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape
{
- btAlignedObjectArray<btTransform> m_childTransforms;
- btAlignedObjectArray<btCollisionShape*> m_childShapes;
+ //btAlignedObjectArray<btTransform> m_childTransforms;
+ //btAlignedObjectArray<btCollisionShape*> m_childShapes;
+ btAlignedObjectArray<btCompoundShapeChild> 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);
+ /** Remove all children shapes that contain the specified shape. */
+ virtual void removeChildShape(btCollisionShape* shape);
+
+
+
+
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;
}
- ///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;
+ btCompoundShapeChild* getChildList()
+ {
+ return &m_children[0];
+ }
+
+ ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+ /** Re-calculate the local Aabb. Is called at the end of removeChildShapes.
+ Use this yourself if you modify the children or their transforms. */
+ virtual void recalculateLocalAabb();
virtual void setLocalScaling(const btVector3& scaling)
{
@@ -80,7 +117,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 +129,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..f3f57206ab7 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h
@@ -17,12 +17,12 @@ 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"
-///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.
+///The btConcaveShape class provides an interface for non-moving (static) concave shapes.
+///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape.
class btConcaveShape : public btCollisionShape
{
protected:
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h
index 3ccda5b12c6..685369742e4 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
+///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis.
+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..c029ca19403 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h
@@ -17,18 +17,17 @@ 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.
-///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)
+///The btConvexHullShape implements an implicit convex hull of an array of vertices.
+///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex.
ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexShape
{
btAlignedObjectArray<btPoint3> 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.
@@ -43,7 +42,12 @@ public:
return &m_points[0];
}
- int getNumPoints()
+ const btPoint3* getPoints() const
+ {
+ return &m_points[0];
+ }
+
+ int getNumPoints() const
{
return m_points.size();
}
@@ -56,7 +60,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..9388ccf31f2
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h
@@ -0,0 +1,98 @@
+
+#ifndef BT_CONVEX_INTERNAL_SHAPE_H
+#define BT_CONVEX_INTERNAL_SHAPE_H
+
+#include "btConvexShape.h"
+
+///The btConvexInternalShape is an internal base class, shared by most convex shape implementations.
+class btConvexInternalShape : public btConvexShape
+{
+
+ protected:
+
+ //local scaling. collisionMargin is not scaled !
+ btVector3 m_localScaling;
+
+ btVector3 m_implicitShapeDimensions;
+
+ btScalar m_collisionMargin;
+
+ btScalar m_padding;
+
+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..e4eb7f6dbf6 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h
@@ -18,37 +18,25 @@ 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.
-/// used in combination with GJK or btConvexCast
+/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc.
+/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector.
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 +44,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 +52,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);
- }
-
-
-
- virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
-
+ void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
- virtual void setLocalScaling(const btVector3& scaling);
- virtual const btVector3& getLocalScaling() const
- {
- return m_localScaling;
- }
+ virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
- const btVector3& getLocalScalingNV() const
- {
- return m_localScaling;
- }
+ virtual void setLocalScaling(const btVector3& scaling) =0;
+ virtual const btVector3& getLocalScaling() const =0;
- virtual void setMargin(btScalar margin)
- {
- m_collisionMargin = margin;
- }
- virtual btScalar getMargin() const
- {
- return m_collisionMargin;
- }
+ virtual void setMargin(btScalar margin)=0;
- btScalar getMarginNV() const
- {
- return m_collisionMargin;
- }
+ virtual btScalar getMargin() const=0;
- virtual int getNumPreferredPenetrationDirections() const
- {
- return 0;
- }
+ virtual int getNumPreferredPenetrationDirections() const=0;
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
- {
- (void)penetrationVector;
- (void)index;
- btAssert(0);
- }
-
-
+ virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0;
-}
-;
+};
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
index 6941030b15f..f1682aaf65b 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
@@ -19,10 +19,11 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
-btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface)
+btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb)
:m_stridingMesh(meshInterface)
{
- recalcLocalAabb();
+ if ( calcAabb )
+ recalcLocalAabb();
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
index 34ee7af744c..01eecf27811 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
@@ -3,20 +3,24 @@
#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.
-/// It uses the btStridingMeshInterface instead of a point cloud. This can avoid the duplication of the triangle mesh data.
+/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape.
+/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead.
class btConvexTriangleMeshShape : public btPolyhedralConvexShape
{
class btStridingMeshInterface* m_stridingMesh;
public:
- btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface);
+ btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true);
- 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;
@@ -49,3 +53,4 @@ public:
#endif //CONVEX_TRIANGLEMESH_SHAPE_H
+
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;i<numVectors;i++)
{
- supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtents(),vectors[i]);
+ supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vectors[i]);
}
}
@@ -188,7 +188,7 @@ void btCylinderShapeZ::batchedUnitVectorGetSupportingVertexWithoutMargin(const b
{
for (int i=0;i<numVectors;i++)
{
- supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtents(),vectors[i]);
+ supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vectors[i]);
}
}
@@ -199,7 +199,7 @@ void btCylinderShapeX::batchedUnitVectorGetSupportingVertexWithoutMargin(const b
{
for (int i=0;i<numVectors;i++)
{
- supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtents(),vectors[i]);
+ supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vectors[i]);
}
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h
index c78890c887a..30938acf7c7 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.h
@@ -17,10 +17,10 @@ subject to the following restrictions:
#define CYLINDER_MINKOWSKI_H
#include "btBoxShape.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
-#include "../../LinearMath/btVector3.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btVector3.h"
-/// implements cylinder shape interface
+/// The btCylinderShape class implements a cylinder shape primitive, centered around the origin. Its central axis aligned with the Y axis. btCylinderShapeX is aligned with the X axis and btCylinderShapeZ around the Z axis.
class btCylinderShape : public btBoxShape
{
@@ -60,7 +60,7 @@ public:
//use box inertia
- // virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
+ // virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual int getShapeType() const
{
@@ -74,11 +74,11 @@ public:
virtual btScalar getRadius() const
{
- return getHalfExtents().getX();
+ return getHalfExtentsWithMargin().getX();
}
//debugging
- virtual char* getName()const
+ virtual const char* getName()const
{
return "CylinderY";
}
@@ -96,14 +96,14 @@ public:
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
//debugging
- virtual char* getName()const
+ virtual const char* getName()const
{
return "CylinderX";
}
virtual btScalar getRadius() const
{
- return getHalfExtents().getY();
+ return getHalfExtentsWithMargin().getY();
}
};
@@ -121,14 +121,14 @@ public:
return 2;
}
//debugging
- virtual char* getName()const
+ virtual const char* getName()const
{
return "CylinderZ";
}
virtual btScalar getRadius() const
{
- return getHalfExtents().getX();
+ return getHalfExtentsWithMargin().getX();
}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.cpp
index dcc486f194b..6954aad7917 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.cpp
@@ -40,7 +40,7 @@ void btEmptyShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aa
}
-void btEmptyShape::calculateLocalInertia(btScalar ,btVector3& )
+void btEmptyShape::calculateLocalInertia(btScalar ,btVector3& ) const
{
btAssert(0);
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h
index 8ec53444976..d7d78407b61 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btEmptyShape.h
@@ -18,16 +18,16 @@ subject to the following restrictions:
#include "btConcaveShape.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"
-/// btEmptyShape is a collision shape without actual collision detection.
-///It can be replaced by another shape during runtime
+/// The btEmptyShape is a collision shape without actual collision detection shape, so most users should ignore this class.
+/// It can be replaced by another shape during runtime, but the inertia tensor should be recomputed.
class btEmptyShape : public btConcaveShape
{
public:
@@ -49,12 +49,12 @@ public:
return m_localScaling;
}
- virtual void calculateLocalInertia(btScalar mass,btVector3& inertia);
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual int getShapeType() const { return EMPTY_SHAPE_PROXYTYPE;}
- virtual char* getName()const
+ virtual const char* getName()const
{
return "Empty";
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
index 94be43c88e2..9e4800a46fe 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
@@ -18,16 +18,18 @@ subject to the following restrictions:
#include "LinearMath/btTransformUtil.h"
-btHeightfieldTerrainShape::btHeightfieldTerrainShape(int width,int length,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
-:m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
-m_width(width),
-m_length(length),
-m_heightfieldDataUnknown(heightfieldData),
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
+: m_heightStickWidth(heightStickWidth),
+m_heightStickLength(heightStickLength),
m_maxHeight(maxHeight),
-m_upAxis(upAxis),
+m_width((btScalar)heightStickWidth-1),
+m_length((btScalar)heightStickLength-1),
+m_heightfieldDataUnknown(heightfieldData),
m_useFloatData(useFloatData),
m_flipQuadEdges(flipQuadEdges),
-m_useDiamondSubdivision(false)
+m_useDiamondSubdivision(false),
+m_upAxis(upAxis),
+m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
{
@@ -43,25 +45,25 @@ m_useDiamondSubdivision(false)
case 0:
{
halfExtents.setValue(
- m_maxHeight,
- m_width,
- m_length);
+ btScalar(m_maxHeight),
+ btScalar(m_width), //?? don't know if this should change
+ btScalar(m_length));
break;
}
case 1:
{
halfExtents.setValue(
- m_width,
- m_maxHeight,
- m_length);
+ btScalar(m_width),
+ btScalar(m_maxHeight),
+ btScalar(m_length));
break;
};
case 2:
{
halfExtents.setValue(
- m_width,
- m_length,
- m_maxHeight
+ btScalar(m_width),
+ btScalar(m_length),
+ btScalar(m_maxHeight)
);
break;
}
@@ -114,11 +116,11 @@ btScalar btHeightfieldTerrainShape::getHeightFieldValue(int x,int y) const
btScalar val = 0.f;
if (m_useFloatData)
{
- val = m_heightfieldDataFloat[(y*m_width)+x];
+ val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
} else
{
//assume unsigned short int
- unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_width)+x];
+ unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
val = heightFieldValue* (m_maxHeight/btScalar(65535));
}
return val;
@@ -133,8 +135,8 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
btAssert(x>=0);
btAssert(y>=0);
- btAssert(x<m_width);
- btAssert(y<m_length);
+ btAssert(x<m_heightStickWidth);
+ btAssert(y<m_heightStickLength);
btScalar height = getHeightFieldValue(x,y);
@@ -145,25 +147,25 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
{
vertex.setValue(
height,
- (-m_width/2 ) + x,
- (-m_length/2 ) + y
+ (-m_width/btScalar(2.0)) + x,
+ (-m_length/btScalar(2.0) ) + y
);
break;
}
case 1:
{
vertex.setValue(
- (-m_width/2 ) + x,
+ (-m_width/btScalar(2.0)) + x,
height,
- (-m_length/2 ) + y
+ (-m_length/btScalar(2.0)) + y
);
break;
};
case 2:
{
vertex.setValue(
- (-m_width/2 ) + x,
- (-m_length/2 ) + y,
+ (-m_width/btScalar(2.0)) + x,
+ (-m_length/btScalar(2.0)) + y,
height
);
break;
@@ -180,21 +182,20 @@ void btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
}
-void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point) const
+void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
{
-
-
btVector3 clampedPoint(point);
clampedPoint.setMax(m_localAabbMin);
clampedPoint.setMin(m_localAabbMax);
- btVector3 v = (clampedPoint );// * m_quantization;
-
- out[0] = (int)(v.getX());
- out[1] = (int)(v.getY());
- out[2] = (int)(v.getZ());
- //correct for
+ btVector3 v = (clampedPoint);// - m_bvhAabbMin) * m_bvhQuantization;
+ //TODO: optimization: check out how to removed this btFabs
+
+ out[0] = (int)(v.getX() + v.getX() / btFabs(v.getX())* btScalar(0.5) );
+ out[1] = (int)(v.getY() + v.getY() / btFabs(v.getY())* btScalar(0.5) );
+ out[2] = (int)(v.getZ() + v.getZ() / btFabs(v.getZ())* btScalar(0.5) );
+
}
@@ -212,24 +213,24 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
btVector3 localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
btVector3 localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
- quantizeWithClamp(quantizedAabbMin, localAabbMin);
- quantizeWithClamp(quantizedAabbMax, localAabbMax);
+ quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
+ quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
int startX=0;
- int endX=m_width-1;
+ int endX=m_heightStickWidth-1;
int startJ=0;
- int endJ=m_length-1;
+ int endJ=m_heightStickLength-1;
switch (m_upAxis)
{
case 0:
{
- quantizedAabbMin[1]+=m_width/2-1;
- quantizedAabbMax[1]+=m_width/2+1;
- quantizedAabbMin[2]+=m_length/2-1;
- quantizedAabbMax[2]+=m_length/2+1;
+ quantizedAabbMin[1]+=m_heightStickWidth/2-1;
+ quantizedAabbMax[1]+=m_heightStickWidth/2+1;
+ quantizedAabbMin[2]+=m_heightStickLength/2-1;
+ quantizedAabbMax[2]+=m_heightStickLength/2+1;
if (quantizedAabbMin[1]>startX)
startX = quantizedAabbMin[1];
@@ -243,10 +244,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
}
case 1:
{
- quantizedAabbMin[0]+=m_width/2-1;
- quantizedAabbMax[0]+=m_width/2+1;
- quantizedAabbMin[2]+=m_length/2-1;
- quantizedAabbMax[2]+=m_length/2+1;
+ quantizedAabbMin[0]+=m_heightStickWidth/2-1;
+ quantizedAabbMax[0]+=m_heightStickWidth/2+1;
+ quantizedAabbMin[2]+=m_heightStickLength/2-1;
+ quantizedAabbMax[2]+=m_heightStickLength/2+1;
if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0];
@@ -260,10 +261,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
};
case 2:
{
- quantizedAabbMin[0]+=m_width/2-1;
- quantizedAabbMax[0]+=m_width/2+1;
- quantizedAabbMin[1]+=m_length/2-1;
- quantizedAabbMax[1]+=m_length/2+1;
+ quantizedAabbMin[0]+=m_heightStickWidth/2-1;
+ quantizedAabbMax[0]+=m_heightStickWidth/2+1;
+ quantizedAabbMin[1]+=m_heightStickLength/2-1;
+ quantizedAabbMax[1]+=m_heightStickLength/2+1;
if (quantizedAabbMin[0]>startX)
startX = quantizedAabbMin[0];
@@ -290,7 +291,7 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
for(int x=startX; x<endX; x++)
{
btVector3 vertices[3];
- if (m_flipQuadEdges || (m_useDiamondSubdivision && ((j+x) & 1)))
+ if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
{
//first triangle
getVertex(x,j,vertices[0]);
@@ -322,7 +323,7 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback
}
-void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia)
+void btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
{
//moving concave objects not supported
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
index 49f3e106733..d6890fe6b97 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
@@ -18,7 +18,8 @@ subject to the following restrictions:
#include "btConcaveShape.h"
-///btHeightfieldTerrainShape simulates a 2D heightfield terrain
+///The btHeightfieldTerrainShape simulates a 2D heightfield terrain collision shape. You can also use the more general btBvhTriangleMeshShape instead.
+///An example implementation of btHeightfieldTerrainShape is provided in Demos/VehicleDemo/VehicleDemo.cpp
class btHeightfieldTerrainShape : public btConcaveShape
{
protected:
@@ -26,9 +27,11 @@ protected:
btVector3 m_localAabbMax;
///terrain data
- int m_width;
- int m_length;
+ int m_heightStickWidth;
+ int m_heightStickLength;
btScalar m_maxHeight;
+ btScalar m_width;
+ btScalar m_length;
union
{
unsigned char* m_heightfieldDataUnsignedChar;
@@ -45,7 +48,7 @@ protected:
btVector3 m_localScaling;
virtual btScalar getHeightFieldValue(int x,int y) const;
- void quantizeWithClamp(int* out, const btVector3& point) const;
+ void quantizeWithClamp(int* out, const btVector3& point,int isMax) const;
void getVertex(int x,int y,btVector3& vertex) const;
inline bool testQuantizedAabbAgainstQuantizedAabb(int* aabbMin1, int* aabbMax1,const int* aabbMin2,const int* aabbMax2) const
@@ -58,7 +61,7 @@ protected:
}
public:
- btHeightfieldTerrainShape(int width,int height,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
+ btHeightfieldTerrainShape(int heightStickWidth,int heightStickHeight,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
virtual ~btHeightfieldTerrainShape();
@@ -74,14 +77,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 "HEIGHTFIELD";}
+ virtual const char* getName()const {return "HEIGHTFIELD";}
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h
new file mode 100644
index 00000000000..7cb6d5ab6fe
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h
@@ -0,0 +1,34 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// This file was created by Alex Silverman
+
+#ifndef MATERIAL_H
+#define MATERIAL_H
+
+// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties
+class btMaterial
+{
+ // public members so that materials can change due to world events
+public:
+ btScalar m_friction;
+ btScalar m_restitution;
+ int pad[2];
+
+ btMaterial(){}
+ btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; }
+};
+
+#endif // MATERIAL_H \ No newline at end of file
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
index 015314bc09f..8f893ac98aa 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
@@ -26,9 +26,9 @@ m_shapeB(shapeB)
btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
{
- btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis()));
+ 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;
+ return supVertexA - supVertexB;
}
void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
@@ -49,7 +49,7 @@ btScalar btMinkowskiSumShape::getMargin() const
}
-void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
+void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
{
(void)mass;
btAssert(0);
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
index 198faaff9f9..f9c8427c2f3 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
@@ -16,11 +16,11 @@ subject to the following restrictions:
#ifndef MINKOWSKI_SUM_SHAPE_H
#define MINKOWSKI_SUM_SHAPE_H
-#include "btConvexShape.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#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 btConvexShape
+/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes.
+class btMinkowskiSumShape : public btConvexInternalShape
{
btTransform m_transA;
@@ -37,7 +37,7 @@ 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;
void setTransformA(const btTransform& transA) { m_transA = transA;}
void setTransformB(const btTransform& transB) { m_transB = transB;}
@@ -53,7 +53,7 @@ public:
const btConvexShape* getShapeA() const { return m_shapeA;}
const btConvexShape* getShapeB() const { return m_shapeB;}
- virtual char* getName()const
+ virtual const char* getName()const
{
return "MinkowskiSum";
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
index 6015a618082..c709205efc2 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
@@ -47,7 +47,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,cons
btVector3 vec = vec0;
btScalar lenSqr = vec.length2();
- if (lenSqr < btScalar(0.0001))
+ if (lenSqr < (SIMD_EPSILON*SIMD_EPSILON))
{
vec.setValue(1,0,0);
} else
@@ -116,7 +116,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,cons
-void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia)
+void btMultiSphereShape::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/btMultiSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h
index 1897b474057..45968f3947f 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h
@@ -16,13 +16,14 @@ subject to the following restrictions:
#ifndef MULTI_SPHERE_MINKOWSKI_H
#define MULTI_SPHERE_MINKOWSKI_H
-#include "btConvexShape.h"
-#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#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 btConvexShape
+///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes.
+///It is possible to animate the spheres for deformation.
+class btMultiSphereShape : public btConvexInternalShape
{
@@ -39,7 +40,7 @@ public:
btMultiSphereShape (const btVector3& inertiaHalfExtents,const btVector3* positions,const btScalar* radi,int numSpheres);
///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;
@@ -63,7 +64,7 @@ public:
virtual int getShapeType() const { return MULTI_SPHERE_SHAPE_PROXYTYPE; }
- virtual char* getName()const
+ virtual const char* getName()const
{
return "MultiSphere";
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
new file mode 100644
index 00000000000..fc47e86411d
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
@@ -0,0 +1,45 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// This file was created by Alex Silverman
+
+#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h"
+//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
+
+
+///Obtains the material for a specific triangle
+const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex)
+{
+ const unsigned char * materialBase = 0;
+ int numMaterials;
+ PHY_ScalarType materialType;
+ int materialStride;
+ const unsigned char * triangleMaterialBase = 0;
+ int numTriangles;
+ int triangleMaterialStride;
+ PHY_ScalarType triangleType;
+
+ ((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride,
+ &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID);
+
+ // return the pointer to the place with the friction for the triangle
+ // TODO: This depends on whether it's a moving mesh or not
+ // BUG IN GIMPACT
+ //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]);
+ int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)]));
+ btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride]));
+ return (matVal);
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
new file mode 100644
index 00000000000..2f108020cdf
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
@@ -0,0 +1,124 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// This file was created by Alex Silverman
+
+#ifndef BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+#define BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+
+#include "btBvhTriangleMeshShape.h"
+#include "btMaterial.h"
+
+///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution.
+ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape
+{
+ btAlignedObjectArray <btMaterial*> m_materialList;
+ int ** m_triangleMaterials;
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btMultimaterialTriangleMeshShape(): btBvhTriangleMeshShape() {}
+ btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true):
+ btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
+ {
+ btVector3 m_triangle[3];
+ const unsigned char *vertexbase;
+ int numverts;
+ PHY_ScalarType type;
+ int stride;
+ const unsigned char *indexbase;
+ int indexstride;
+ int numfaces;
+ PHY_ScalarType indicestype;
+
+ //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
+
+ for(int i = 0; i < meshInterface->getNumSubParts(); i++)
+ {
+ m_meshInterface->getLockedReadOnlyVertexIndexBase(
+ &vertexbase,
+ numverts,
+ type,
+ stride,
+ &indexbase,
+ indexstride,
+ numfaces,
+ indicestype,
+ i);
+ //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16));
+ }
+ }
+
+ ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
+ btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true):
+ btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh)
+ {
+ btVector3 m_triangle[3];
+ const unsigned char *vertexbase;
+ int numverts;
+ PHY_ScalarType type;
+ int stride;
+ const unsigned char *indexbase;
+ int indexstride;
+ int numfaces;
+ PHY_ScalarType indicestype;
+
+ //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
+
+ for(int i = 0; i < meshInterface->getNumSubParts(); i++)
+ {
+ m_meshInterface->getLockedReadOnlyVertexIndexBase(
+ &vertexbase,
+ numverts,
+ type,
+ stride,
+ &indexbase,
+ indexstride,
+ numfaces,
+ indicestype,
+ i);
+ //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16));
+ }
+ }
+
+ virtual ~btMultimaterialTriangleMeshShape()
+ {
+/*
+ for(int i = 0; i < m_meshInterface->getNumSubParts(); i++)
+ {
+ btAlignedFree(m_materialValues[i]);
+ m_materialLookup[i] = NULL;
+ }
+ btAlignedFree(m_materialValues);
+ m_materialLookup = NULL;
+*/
+ }
+ virtual int getShapeType() const
+ {
+ return MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
+ }
+
+ //debugging
+ virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";}
+
+ ///Obtains the material for a specific triangle
+ const btMaterial * getMaterialProperties(int partID, int triIndex);
+
+}
+;
+
+#endif //BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
index 44438a24455..9b78fc0f7c2 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
@@ -19,13 +19,12 @@ subject to the following restrictions:
#include "LinearMath/btIDebugDraw.h"
-
-btOptimizedBvh::btOptimizedBvh() : m_useQuantization(false),
- m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
- //m_traversalMode(TRAVERSAL_STACKLESS)
- //m_traversalMode(TRAVERSAL_RECURSIVE)
+btOptimizedBvh::btOptimizedBvh()
{
+}
+btOptimizedBvh::~btOptimizedBvh()
+{
}
@@ -80,7 +79,7 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback
{
QuantizedNodeArray& m_triangleNodes;
- const btOptimizedBvh* m_optimizedTree; // for quantization
+ const btQuantizedBvh* m_optimizedTree; // for quantization
QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
{
@@ -89,14 +88,16 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
return *this;
}
- QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btOptimizedBvh* tree)
+ QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btQuantizedBvh* tree)
:m_triangleNodes(triangleNodes),m_optimizedTree(tree)
{
}
virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
{
- btAssert(partId==0);
+ // The partId and triangle index must fit in the same (positive) integer
+ btAssert(partId < (1<<MAX_NUM_PARTS_IN_BITS));
+ btAssert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS)));
//negative indices are reserved for escapeIndex
btAssert(triangleIndex>=0);
@@ -111,10 +112,29 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized
aabbMin.setMin(triangle[2]);
aabbMax.setMax(triangle[2]);
- m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMin[0],aabbMin);
- m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMax[0],aabbMax);
+ //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);
+ }
- node.m_escapeIndexOrTriangleIndex = triangleIndex;
+ m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
+ m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+
+ node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
m_triangleNodes.push_back(node);
}
@@ -170,10 +190,45 @@ 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();
+}
+
+
+
+
+void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ if (m_useQuantization)
+ {
+
+ setQuantizationValues(aabbMin,aabbMax);
+
+ updateBvhNodes(meshInterface,0,m_curNodeIndex,0);
+
+ ///now update all subtree headers
+
+ int i;
+ for (i=0;i<m_SubtreeHeaders.size();i++)
+ {
+ btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+ subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+ }
+
+ } else
+ {
+
+ }
}
+
void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
{
//incrementally initialize quantization values
@@ -193,16 +248,17 @@ void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const b
unsigned short quantizedQueryAabbMin[3];
unsigned short quantizedQueryAabbMax[3];
- quantizeWithClamp(&quantizedQueryAabbMin[0],aabbMin);
- quantizeWithClamp(&quantizedQueryAabbMax[0],aabbMax);
+ quantize(&quantizedQueryAabbMin[0],aabbMin,0);
+ quantize(&quantizedQueryAabbMax[0],aabbMax,1);
int i;
for (i=0;i<this->m_SubtreeHeaders.size();i++)
{
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);
@@ -212,36 +268,23 @@ void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const b
}
-///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;
+ int curNodeSubPart=-1;
//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);
+ const unsigned char *vertexbase = 0;
+ int numverts = 0;
+ PHY_ScalarType type = PHY_INTEGER;
+ int stride = 0;
+ const unsigned char *indexbase = 0;
+ int indexstride = 0;
+ int numfaces = 0;
+ PHY_ScalarType indicestype = PHY_INTEGER;
btVector3 triangleVerts[3];
btVector3 aabbMin,aabbMax;
@@ -256,16 +299,24 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f
if (curNode.isLeafNode())
{
//recalc aabb from triangle data
+ int nodeSubPart = curNode.getPartId();
int nodeTriangleIndex = curNode.getTriangleIndex();
+ if (nodeSubPart != curNodeSubPart)
+ {
+ if (curNodeSubPart >= 0)
+ meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+ meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
+ btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+ }
//triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
- int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride);
+ unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
for (int j=2;j>=0;j--)
{
- int graphicsindex = gfxbase[j];
+ int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride);
#ifdef DEBUG_PATCH_COLORS
btVector3 mycolor = color[index&3];
@@ -292,8 +343,8 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f
aabbMin.setMin(triangleVerts[2]);
aabbMax.setMax(triangleVerts[2]);
- quantizeWithClamp(&curNode.m_quantizedAabbMin[0],aabbMin);
- quantizeWithClamp(&curNode.m_quantizedAabbMax[0],aabbMax);
+ quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0);
+ quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1);
} else
{
@@ -321,525 +372,17 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f
}
- meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+ if (curNodeSubPart >= 0)
+ meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
}
-void btOptimizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin)
+///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
{
- //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<m_SubtreeHeaders.size();i++)
- {
- btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
- subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
- }
-
- } else
- {
-
- }
-}
-
-
-
-btOptimizedBvh::~btOptimizedBvh()
-{
-}
-
-#ifdef DEBUG_TREE_BUILDING
-int gStackDepth = 0;
-int gMaxStackDepth = 0;
-#endif //DEBUG_TREE_BUILDING
-
-void btOptimizedBvh::buildTree (int startIndex,int endIndex)
-{
-#ifdef DEBUG_TREE_BUILDING
- gStackDepth++;
- if (gStackDepth > 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)));
+ btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
- for (i=startIndex;i<endIndex;i++)
- {
- mergeInternalNodeAabb(m_curNodeIndex,getAabbMin(i),getAabbMax(i));
- }
-
- m_curNodeIndex++;
-
-
- //internalNode->m_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<endIndex;i++)
- {
- btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
- means+=center;
- }
- means *= (btScalar(1.)/(btScalar)numIndices);
-
- splitValue = means[splitAxis];
-
- //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i=startIndex;i<endIndex;i++)
- {
- btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
- if (center[splitAxis] > 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;i<endIndex;i++)
- {
- btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
- means+=center;
- }
- means *= (btScalar(1.)/(btScalar)numIndices);
-
- for (i=startIndex;i<endIndex;i++)
- {
- btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
- btVector3 diff2 = center-means;
- diff2 = diff2 * diff2;
- variance += diff2;
- }
- variance *= (btScalar(1.)/ ((btScalar)numIndices-1) );
-
- return variance.maxAxis();
-}
-
-
-
-void btOptimizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
-{
- //either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
-
-
- if (m_useQuantization)
- {
- ///quantize query AABB
- unsigned short int quantizedQueryAabbMin[3];
- unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin,aabbMin);
- quantizeWithClamp(quantizedQueryAabbMax,aabbMax);
-
- switch (m_traversalMode)
- {
- case TRAVERSAL_STACKLESS:
- walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,0,m_curNodeIndex);
- break;
- case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
- walkStacklessQuantizedTreeCacheFriendly(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
- break;
- case TRAVERSAL_RECURSIVE:
- {
- const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
- walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
- }
- break;
- default:
- //unsupported
- btAssert(0);
- }
- } else
- {
- walkStacklessTree(nodeCallback,aabbMin,aabbMax);
- }
-}
-
-
-int maxIterations = 0;
-
-void btOptimizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
-{
- btAssert(!m_useQuantization);
-
- const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
- int escapeIndex, curIndex = 0;
- int walkIterations = 0;
- bool aabbOverlap, isLeafNode;
-
- while (curIndex < m_curNodeIndex)
- {
- //catch bugs in tree data
- assert (walkIterations < m_curNodeIndex);
-
- walkIterations++;
- aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_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;i<this->m_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];
- }
+ //we don't add additional data so just do a static upcast
+ return static_cast<btOptimizedBvh*>(bvh);
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h
index d5159586344..d7536417d7e 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h
@@ -16,315 +16,48 @@ subject to the following restrictions:
#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
-
-
+#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h"
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
+///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface.
+ATTRIBUTE_ALIGNED16(class) btOptimizedBvh : public btQuantizedBvh
{
- //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<btOptimizedBvhNode> NodeArray;
-typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
-typedef btAlignedObjectArray<btBvhSubtreeInfo> 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);
+ BT_DECLARE_ALIGNED_ALLOCATOR();
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 refit(btStridingMeshInterface* triangles,const btVector3& aabbMin,const btVector3& aabbMax);
void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax);
void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index);
+ /// Data buffer MUST be 16 byte aligned
+ virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian)
+ {
+ return btQuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
- QuantizedNodeArray& getQuantizedNodeArray()
- {
- return m_quantizedContiguousNodes;
}
- BvhSubtreeInfoArray& getSubtreeInfoArray()
- {
- return m_SubtreeHeaders;
- }
+ ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+ static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
-}
-;
+
+};
#endif //OPTIMIZED_BVH_H
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
index bbc4ba62af6..71c3af38a02 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#include <BulletCollision/CollisionShapes/btPolyhedralConvexShape.h>
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
btPolyhedralConvexShape::btPolyhedralConvexShape()
:m_localAabbMin(1,1,1),
@@ -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
@@ -128,10 +128,46 @@ void btPolyhedralConvexShape::getAabb(const btTransform& trans,btVector3& aabbMi
+void btPolyhedralConvexShape::setLocalScaling(const btVector3& scaling)
+{
+ btConvexInternalShape::setLocalScaling(scaling);
+ recalcLocalAabb();
+}
void btPolyhedralConvexShape::recalcLocalAabb()
{
m_isLocalAabbValid = true;
+
+ #if 1
+ static const btVector3 _directions[] =
+ {
+ btVector3( 1., 0., 0.),
+ btVector3( 0., 1., 0.),
+ btVector3( 0., 0., 1.),
+ btVector3( -1., 0., 0.),
+ btVector3( 0., -1., 0.),
+ btVector3( 0., 0., -1.)
+ };
+
+ btVector3 _supporting[] =
+ {
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.),
+ btVector3( 0., 0., 0.)
+ };
+
+ batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
+
+ for ( int i = 0; i < 3; ++i )
+ {
+ m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
+ m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+ }
+
+ #else
for (int i=0;i<3;i++)
{
@@ -143,6 +179,8 @@ void btPolyhedralConvexShape::recalcLocalAabb()
tmp = localGetSupportingVertex(vec);
m_localAabbMin[i] = tmp[i]-m_collisionMargin;
}
+ #endif
}
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
index c35f7512663..0d55e4fe92c 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
+///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
+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
@@ -73,6 +73,8 @@ public:
virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+ virtual void setLocalScaling(const btVector3& scaling);
+
void recalcLocalAabb();
virtual int getNumVertices() const = 0 ;
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp
new file mode 100644
index 00000000000..a87b87f1a6f
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp
@@ -0,0 +1,164 @@
+/*
+btbtShapeHull implemented by John McCutchan.
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btShapeHull.h"
+#include "LinearMath/btConvexHull.h"
+
+#define NUM_UNITSPHERE_POINTS 42
+
+static btVector3 btUnitSpherePoints[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))
+};
+
+btShapeHull::btShapeHull (const btConvexShape* shape)
+{
+ m_shape = shape;
+ m_vertices.clear ();
+ m_indices.clear();
+ m_numIndices = 0;
+}
+
+btShapeHull::~btShapeHull ()
+{
+ m_indices.clear();
+ m_vertices.clear ();
+}
+
+bool
+btShapeHull::buildHull (btScalar /*margin*/)
+{
+ int numSampleDirections = NUM_UNITSPHERE_POINTS;
+ {
+ int numPDA = m_shape->getNumPreferredPenetrationDirections();
+ if (numPDA)
+ {
+ for (int i=0;i<numPDA;i++)
+ {
+ btVector3 norm;
+ m_shape->getPreferredPenetrationDirection(i,norm);
+ btUnitSpherePoints[numSampleDirections] = norm;
+ numSampleDirections++;
+ }
+ }
+ }
+
+ btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+ int i;
+ for (i = 0; i < numSampleDirections; i++)
+ {
+ supportPoints[i] = m_shape->localGetSupportingVertex(btUnitSpherePoints[i]);
+ }
+
+ HullDesc hd;
+ hd.mFlags = QF_TRIANGLES;
+ hd.mVcount = static_cast<unsigned int>(numSampleDirections);
+
+#ifdef BT_USE_DOUBLE_PRECISION
+ hd.mVertices = &supportPoints[0];
+ hd.mVertexStride = sizeof(btVector3);
+#else
+ hd.mVertices = &supportPoints[0];
+ hd.mVertexStride = sizeof (btVector3);
+#endif
+
+ HullLibrary hl;
+ HullResult hr;
+ if (hl.CreateConvexHull (hd, hr) == QE_FAIL)
+ {
+ return false;
+ }
+
+ m_vertices.resize (static_cast<int>(hr.mNumOutputVertices));
+
+
+ for (i = 0; i < static_cast<int>(hr.mNumOutputVertices); i++)
+ {
+ m_vertices[i] = hr.m_OutputVertices[i];
+ }
+ m_numIndices = hr.mNumIndices;
+ m_indices.resize(static_cast<int>(m_numIndices));
+ for (i = 0; i < static_cast<int>(m_numIndices); i++)
+ {
+ m_indices[i] = hr.m_Indices[i];
+ }
+
+ // free temporary hull result that we just copied
+ hl.ReleaseResult (hr);
+
+ return true;
+}
+
+int
+btShapeHull::numTriangles () const
+{
+ return static_cast<int>(m_numIndices / 3);
+}
+
+int
+btShapeHull::numVertices () const
+{
+ return m_vertices.size ();
+}
+
+int
+btShapeHull::numIndices () const
+{
+ return static_cast<int>(m_numIndices);
+}
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h
new file mode 100644
index 00000000000..583c6b99eb6
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h
@@ -0,0 +1,56 @@
+/*
+btShapeHull implemented by John McCutchan.
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 _SHAPE_HULL_H
+#define _SHAPE_HULL_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+
+///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices.
+///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object.
+///It approximates the convex hull using the supporting vertex of 42 directions.
+class btShapeHull
+{
+public:
+ btShapeHull (const btConvexShape* shape);
+ ~btShapeHull ();
+
+ bool buildHull (btScalar margin);
+
+ int numTriangles () const;
+ int numVertices () const;
+ int numIndices () const;
+
+ const btVector3* getVertexPointer() const
+ {
+ return &m_vertices[0];
+ }
+ const unsigned int* getIndexPointer() const
+ {
+ return &m_indices[0];
+ }
+
+protected:
+ btAlignedObjectArray<btVector3> m_vertices;
+ btAlignedObjectArray<unsigned int> m_indices;
+ unsigned int m_numIndices;
+ const btConvexShape* m_shape;
+};
+
+#endif //_SHAPE_HULL_H
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..83421d69e0d 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
+///The btSphereShape implements an implicit sphere, centered around a local origin with radius.
+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..3c98ca08ddc 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
@@ -19,10 +19,11 @@ subject to the following restrictions:
btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant)
-:m_planeNormal(planeNormal),
+:m_planeNormal(planeNormal.normalized()),
m_planeConstant(planeConstant),
m_localScaling(btScalar(0.),btScalar(0.),btScalar(0.))
{
+ // btAssert( btFuzzyZero(m_planeNormal.length() - btScalar(1.)) );
}
@@ -86,7 +87,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..ddebca73dea 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h
@@ -19,8 +19,7 @@ subject to the following restrictions:
#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.
+///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane.
class btStaticPlaneShape : public btConcaveShape
{
protected:
@@ -46,14 +45,23 @@ 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;
+ const btVector3& getPlaneNormal() const
+ {
+ return m_planeNormal;
+ }
+
+ const btScalar& getPlaneConstant() const
+ {
+ return m_planeConstant;
+ }
//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..752a5fc1dfa 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
@@ -51,7 +51,7 @@ void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleInde
{
for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
{
- int* tri_indices= (int*)(indexbase+gfxindex*indexstride);
+ unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
graphicsbase = (btScalar*)(vertexbase+tri_indices[0]*stride);
triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
graphicsbase = (btScalar*)(vertexbase+tri_indices[1]*stride);
@@ -66,7 +66,7 @@ void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleInde
{
for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
{
- short int* tri_indices= (short int*)(indexbase+gfxindex*indexstride);
+ unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
graphicsbase = (btScalar*)(vertexbase+tri_indices[0]*stride);
triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
graphicsbase = (btScalar*)(vertexbase+tri_indices[1]*stride);
@@ -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..85020dd3f58 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.
@@ -29,7 +29,8 @@ typedef enum PHY_ScalarType {
PHY_FIXEDPOINT88
} PHY_ScalarType;
-/// btStridingMeshInterface is the interface class for high performance access to triangle meshes
+/// The btStridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with btBvhTriangleMeshShape and some other collision shapes.
+/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
class btStridingMeshInterface
{
@@ -47,7 +48,7 @@ class btStridingMeshInterface
- void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+ virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
///brute force method to calculate aabb
void calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax);
@@ -75,6 +76,10 @@ class btStridingMeshInterface
virtual void preallocateVertices(int numverts)=0;
virtual void preallocateIndices(int numindices)=0;
+ virtual bool hasPremadeAabb() const { return false; }
+ virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const {}
+ virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const {}
+
const btVector3& getScaling() const {
return m_scaling;
}
@@ -83,6 +88,7 @@ class btStridingMeshInterface
m_scaling = scaling;
}
+
};
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h
index 94bc4ec0fa5..09272d61dc2 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTetrahedronShape.h
@@ -18,10 +18,10 @@ 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).
+///The btBU_Simplex1to4 implements tetrahedron, triangle, line, vertex collision shapes. In most cases it is better to use btConvexHullShape instead.
class btBU_Simplex1to4 : public btPolyhedralConvexShape
{
protected:
@@ -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.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
index 54864c32f3a..5194219f256 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
@@ -16,14 +16,7 @@ subject to the following restrictions:
#include "btTriangleBuffer.h"
-///example usage of this class:
-// btTriangleBuffer triBuf;
-// concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax);
-// for (int i=0;i<triBuf.getNumTriangles();i++)
-// {
-// const btTriangle& tri = triBuf.getTriangle(i);
-// //do something useful here with the triangle
-// }
+
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleBuffer.h
index 3805c519d22..c739fc11e8f 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
{
@@ -29,6 +29,14 @@ struct btTriangle
};
///btTriangleBuffer can be useful to collect and store overlapping triangles between AABB and concave objects that support 'processAllTriangles'
+///Example usage of this class:
+/// btTriangleBuffer triBuf;
+/// concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax);
+/// for (int i=0;i<triBuf.getNumTriangles();i++)
+/// {
+/// const btTriangle& tri = triBuf.getTriangle(i);
+/// //do something useful here with the triangle
+/// }
class btTriangleBuffer : public btTriangleCallback
{
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h
index fbb87bc4fd8..cb760be80ca 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleCallback.h
@@ -16,9 +16,11 @@ subject to the following restrictions:
#ifndef TRIANGLE_CALLBACK_H
#define TRIANGLE_CALLBACK_H
-#include "../../LinearMath/btVector3.h"
+#include "LinearMath/btVector3.h"
+///The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
+///This callback is called by processAllTriangles for all btConcaveShape derived class, such as btBvhTriangleMeshShape, btStaticPlaneShape and btHeightfieldTerrainShape.
class btTriangleCallback
{
public:
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
index 00847861cf1..8d634a67143 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,34 +18,43 @@ 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;
(*indexbase) = (unsigned char *)mesh.m_triangleIndexBase;
indexstride = mesh.m_triangleIndexStride;
- indicestype = PHY_INTEGER;
+ indicestype = mesh.m_indexType;
}
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
@@ -54,12 +63,34 @@ 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;
(*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase;
indexstride = mesh.m_triangleIndexStride;
- indicestype = PHY_INTEGER;
+ indicestype = mesh.m_indexType;
+}
+
+bool btTriangleIndexVertexArray::hasPremadeAabb() const
+{
+ return (m_hasAabb == 1);
+}
+
+void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax )
+{
+ m_aabbMin = aabbMin;
+ m_aabbMax = aabbMax;
+ m_hasAabb = 1; // this is intentionally an int see notes in header
+}
+
+void btTriangleIndexVertexArray::getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const
+{
+ *aabbMin = m_aabbMin;
+ *aabbMax = m_aabbMax;
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
index 6ab6a762b39..e546675f802 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
@@ -17,48 +17,62 @@ 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
+
+///The btIndexedMesh indexes a single vertex and index array. Multiple btIndexedMesh objects can be passed into a btTriangleIndexVertexArray using addIndexedMesh.
+///Instead of the number of indices, we pass the number of triangles.
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];
+ // The index type is set when adding an indexed mesh to the
+ // btTriangleIndexVertexArray, do not set it manually
+ PHY_ScalarType m_indexType;
+ int pad;
}
;
typedef btAlignedObjectArray<btIndexedMesh> IndexedMeshArray;
-///TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays.
+///The btTriangleIndexVertexArray allows to access multiple triangle 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
{
+protected:
IndexedMeshArray m_indexedMeshes;
- int m_pad[3];
+ int m_pad[2];
+ int m_hasAabb; // using int instead of bool to maintain alignment
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax;
-
public:
- btTriangleIndexVertexArray()
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btTriangleIndexVertexArray() : m_hasAabb(0)
{
}
+ virtual ~btTriangleIndexVertexArray();
+
//just to be backwards compatible
- btTriangleIndexVertexArray(int numTriangleIndices,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride);
+ btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride);
- void addIndexedMesh(const btIndexedMesh& mesh)
+ void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
{
m_indexedMeshes.push_back(mesh);
+ m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType;
}
@@ -91,6 +105,10 @@ public:
virtual void preallocateVertices(int numverts){(void) numverts;}
virtual void preallocateIndices(int numindices){(void) numindices;}
+ virtual bool hasPremadeAabb() const;
+ virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax );
+ virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const;
+
}
;
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
new file mode 100644
index 00000000000..492854ff646
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
@@ -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.
+*/
+
+///This file was created by Alex Silverman
+
+#include "btTriangleIndexVertexMaterialArray.h"
+
+btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
+ int numVertices,btScalar* vertexBase,int vertexStride,
+ int numMaterials, unsigned char* materialBase, int materialStride,
+ int* triangleMaterialsBase, int materialIndexStride) :
+btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride)
+{
+ btMaterialProperties mat;
+
+ mat.m_numMaterials = numMaterials;
+ mat.m_materialBase = materialBase;
+ mat.m_materialStride = materialStride;
+#ifdef BT_USE_DOUBLE_PRECISION
+ mat.m_materialType = PHY_DOUBLE;
+#else
+ mat.m_materialType = PHY_FLOAT;
+#endif
+
+ mat.m_numTriangles = numTriangles;
+ mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase;
+ mat.m_triangleMaterialStride = materialIndexStride;
+ mat.m_triangleType = PHY_INTEGER;
+
+ addMaterialProperties(mat);
+}
+
+
+void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
+{
+ btAssert(subpart< getNumSubParts() );
+
+ btMaterialProperties& mats = m_materials[subpart];
+
+ numMaterials = mats.m_numMaterials;
+ (*materialBase) = (unsigned char *) mats.m_materialBase;
+#ifdef BT_USE_DOUBLE_PRECISION
+ materialType = PHY_DOUBLE;
+#else
+ materialType = PHY_FLOAT;
+#endif
+ materialStride = mats.m_materialStride;
+
+ numTriangles = mats.m_numTriangles;
+ (*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase;
+ triangleMaterialStride = mats.m_triangleMaterialStride;
+ triangleType = mats.m_triangleType;
+}
+
+void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
+{
+ btMaterialProperties& mats = m_materials[subpart];
+
+ numMaterials = mats.m_numMaterials;
+ (*materialBase) = (const unsigned char *) mats.m_materialBase;
+#ifdef BT_USE_DOUBLE_PRECISION
+ materialType = PHY_DOUBLE;
+#else
+ materialType = PHY_FLOAT;
+#endif
+ materialStride = mats.m_materialStride;
+
+ numTriangles = mats.m_numTriangles;
+ (*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase;
+ triangleMaterialStride = mats.m_triangleMaterialStride;
+ triangleType = mats.m_triangleType;
+}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
new file mode 100644
index 00000000000..69a2e631458
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///This file was created by Alex Silverman
+
+#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
+
+#include "btTriangleIndexVertexArray.h"
+
+
+ATTRIBUTE_ALIGNED16( struct) btMaterialProperties
+{
+ ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution
+ int m_numMaterials;
+ const unsigned char * m_materialBase;
+ int m_materialStride;
+ PHY_ScalarType m_materialType;
+ ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're
+ /// padding the structure, it can be reproduced at no real cost
+ ///m_triangleMaterials =====> 1 integer value makes up one entry
+ /// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5
+ int m_numTriangles;
+ const unsigned char * m_triangleMaterialsBase;
+ int m_triangleMaterialStride;
+ ///m_triangleType <========== Automatically set in addMaterialProperties
+ PHY_ScalarType m_triangleType;
+};
+
+typedef btAlignedObjectArray<btMaterialProperties> MaterialArray;
+
+///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray
+///The addition of a material array allows for the utilization of the partID and
+///triangleIndex that are returned in the ContactAddedCallback. As with
+///TriangleIndexVertexArray, no duplicate is made of the material data, so it
+///is the users responsibility to maintain the array during the lifetime of the
+///TriangleIndexVertexMaterialArray.
+ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray
+{
+protected:
+ MaterialArray m_materials;
+
+public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btTriangleIndexVertexMaterialArray()
+ {
+ }
+
+ btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
+ int numVertices,btScalar* vertexBase,int vertexStride,
+ int numMaterials, unsigned char* materialBase, int materialStride,
+ int* triangleMaterialsBase, int materialIndexStride);
+
+ virtual ~btTriangleIndexVertexMaterialArray() {}
+
+ void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER)
+ {
+ m_materials.push_back(mat);
+ m_materials[m_materials.size()-1].m_triangleType = triangleType;
+ }
+
+ virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0);
+
+ virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+ const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
+
+}
+;
+
+#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp
index 98c54ef45f8..bcea97052d6 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp
@@ -14,47 +14,102 @@ subject to the following restrictions:
*/
#include "btTriangleMesh.h"
-#include <assert.h>
-btTriangleMesh::btTriangleMesh ()
+
+btTriangleMesh::btTriangleMesh (bool use32bitIndices,bool use4componentVertices)
+:m_use32bitIndices(use32bitIndices),
+m_use4componentVertices(use4componentVertices)
{
+ btIndexedMesh meshIndex;
+ meshIndex.m_numTriangles = 0;
+ meshIndex.m_numVertices = 0;
+ meshIndex.m_indexType = PHY_INTEGER;
+ meshIndex.m_triangleIndexBase = 0;
+ meshIndex.m_triangleIndexStride = 3*sizeof(int);
+ meshIndex.m_vertexBase = 0;
+ meshIndex.m_vertexStride = sizeof(btVector3);
+ m_indexedMeshes.push_back(meshIndex);
-}
+ if (m_use32bitIndices)
+ {
+ m_indexedMeshes[0].m_numTriangles = m_32bitIndices.size()/3;
+ m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0];
+ m_indexedMeshes[0].m_indexType = PHY_INTEGER;
+ m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(int);
+ } else
+ {
+ m_indexedMeshes[0].m_numTriangles = m_16bitIndices.size()/3;
+ m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0];
+ m_indexedMeshes[0].m_indexType = PHY_SHORT;
+ m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(short int);
+ }
-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);
+ if (m_use4componentVertices)
+ {
+ m_indexedMeshes[0].m_numVertices = m_4componentVertices.size();
+ m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0];
+ m_indexedMeshes[0].m_vertexStride = sizeof(btVector3);
+ } else
+ {
+ m_indexedMeshes[0].m_numVertices = m_3componentVertices.size()/3;
+ m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0];
+ m_indexedMeshes[0].m_vertexStride = 3*sizeof(btScalar);
+ }
- 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 btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2)
{
- (void)subpart;
- numverts = m_vertices.size();
- *vertexbase = (unsigned char*)&m_vertices[0];
- type = PHY_FLOAT;
- stride = sizeof(btVector3);
+ m_indexedMeshes[0].m_numTriangles++;
+ m_indexedMeshes[0].m_numVertices+=3;
- numfaces = m_indices.size()/3;
- *indexbase = (unsigned char*) &m_indices[0];
- indicestype = PHY_INTEGER;
- indexstride = 3*sizeof(int);
+ if (m_use4componentVertices)
+ {
+ m_4componentVertices.push_back(vertex0);
+ m_4componentVertices.push_back(vertex1);
+ m_4componentVertices.push_back(vertex2);
+ m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0];
+ } else
+ {
+ m_3componentVertices.push_back(vertex0.getX());
+ m_3componentVertices.push_back(vertex0.getY());
+ m_3componentVertices.push_back(vertex0.getZ());
-}
+ m_3componentVertices.push_back(vertex1.getX());
+ m_3componentVertices.push_back(vertex1.getY());
+ m_3componentVertices.push_back(vertex1.getZ());
+ m_3componentVertices.push_back(vertex2.getX());
+ m_3componentVertices.push_back(vertex2.getY());
+ m_3componentVertices.push_back(vertex2.getZ());
+ m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0];
+ }
+ if (m_use32bitIndices)
+ {
+ int curIndex = m_32bitIndices.size();
+ m_32bitIndices.push_back(curIndex++);
+ m_32bitIndices.push_back(curIndex++);
+ m_32bitIndices.push_back(curIndex++);
+ m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0];
+ } else
+ {
+ short curIndex = static_cast<short>(m_16bitIndices.size());
+ m_16bitIndices.push_back(curIndex++);
+ m_16bitIndices.push_back(curIndex++);
+ m_16bitIndices.push_back(curIndex++);
+ m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0];
+ }
+}
-int btTriangleMesh::getNumSubParts() const
+int btTriangleMesh::getNumTriangles() const
{
- return 1;
+ if (m_use32bitIndices)
+ {
+ return m_32bitIndices.size() / 3;
+ }
+ return m_16bitIndices.size() / 3;
}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h
index 525f5336b48..e4d41d5ede0 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h
@@ -17,54 +17,42 @@ subject to the following restrictions:
#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
+#include "btTriangleIndexVertexArray.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+///The btTriangleMesh class is a convenience class derived from btTriangleIndexVertexArray, that provides storage for a concave triangle mesh. It can be used as data for the btBvhTriangleMeshShape.
+///It allows either 32bit or 16bit indices, and 4 (x-y-z-w) or 3 (x-y-z) component vertices.
+///If you want to share triangle/index data between graphics mesh and collision mesh (btBvhTriangleMeshShape), you can directly use btTriangleIndexVertexArray or derive your own class from btStridingMeshInterface.
+///Performance of btTriangleMesh and btTriangleIndexVertexArray used in a btBvhTriangleMeshShape is the same.
+class btTriangleMesh : public btTriangleIndexVertexArray
{
- btAlignedObjectArray<btVector3> m_vertices;
- btAlignedObjectArray<int> m_indices;
+ btAlignedObjectArray<btVector3> m_4componentVertices;
+ btAlignedObjectArray<float> m_3componentVertices;
+
+ btAlignedObjectArray<unsigned int> m_32bitIndices;
+ btAlignedObjectArray<unsigned short int> m_16bitIndices;
+ bool m_use32bitIndices;
+ bool m_use4componentVertices;
+
public:
- btTriangleMesh ();
+ btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true);
- void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2)
+ bool getUse32bitIndices() const
{
- 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++);
+ return m_use32bitIndices;
}
- int getNumTriangles() const
+ bool getUse4componentVertices() const
{
- return m_indices.size() / 3;
+ return m_use4componentVertices;
}
-
-
-//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;
+ void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2);
+ int getNumTriangles() const;
+
virtual void preallocateVertices(int numverts){(void) numverts;}
virtual void preallocateIndices(int numindices){(void) numindices;}
diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
index ed81897b515..cd0a00bbd6f 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
@@ -20,12 +20,18 @@ subject to the following restrictions:
#include "LinearMath/btAabbUtil2.h"
#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-#include "stdio.h"
btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface)
: m_meshInterface(meshInterface)
{
- recalcLocalAabb();
+ if(meshInterface->hasPremadeAabb())
+ {
+ meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax);
+ }
+ else
+ {
+ recalcLocalAabb();
+ }
}
@@ -138,6 +144,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 +181,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..9fba77cb547 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h
@@ -20,18 +20,20 @@ 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.
+///The btTriangleMeshShape is an internal 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;
-
-public:
+ ///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;
@@ -44,16 +46,11 @@ public:
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 calculateLocalInertia(btScalar mass,btVector3& inertia) const;
virtual void setLocalScaling(const btVector3& scaling);
virtual const btVector3& getLocalScaling() const;
@@ -70,7 +67,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..ba7aa0c32a0 100644
--- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h
@@ -27,7 +27,6 @@ public:
btVector3 m_vertices1[3];
-
virtual int getNumVertices() const
{
return 3;
@@ -84,14 +83,13 @@ public:
- btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2)
- {
- m_vertices1[0] = p0;
- m_vertices1[1] = p1;
- m_vertices1[2] = p2;
- }
+ btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2)
+ {
+ m_vertices1[0] = p0;
+ m_vertices1[1] = p1;
+ m_vertices1[2] = p2;
+ }
-
virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i) const
{
@@ -116,7 +114,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 +153,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;i<numVectors;i++)
+ {
+ supportVerticesOut[i] = supportVerticesOut[i] * m_uniformScalingFactor;
+ }
+}
+
+
+btVector3 btUniformScalingShape::localGetSupportingVertex(const btVector3& vec)const
+{
+ btVector3 tmpVertex;
+ tmpVertex = m_childConvexShape->localGetSupportingVertex(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..1e17fc8e198
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.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 BT_UNIFORM_SCALING_SHAPE_H
+#define BT_UNIFORM_SCALING_SHAPE_H
+
+#include "btConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way.
+///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it.
+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..6551cfb92fe 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
@@ -16,7 +16,6 @@ subject to the following restrictions:
#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"
@@ -26,7 +25,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)
@@ -35,7 +34,7 @@ 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
+#define MAX_ITERATIONS 64
bool btContinuousConvexCollision::calcTimeOfImpact(
const btTransform& fromA,
@@ -52,10 +51,18 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
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;
+ btVector3 relLinVel = (linVelB-linVelA);
+
+ btScalar relLinVelocLength = (linVelB-linVelA).length();
+
+ if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f)
+ return false;
+
btScalar radius = btScalar(0.001);
@@ -93,7 +100,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,25 +115,31 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
btScalar dist;
dist = pointCollector1.m_distance;
n = pointCollector1.m_normalOnBInWorld;
+
+ btScalar projectedLinearVelocity = relLinVel.dot(n);
//not close enough
while (dist > radius)
{
numIter++;
if (numIter > maxIter)
+ {
return false; //todo: report a failure
-
+ }
btScalar dLambda = btScalar(0.);
+ projectedLinearVelocity = relLinVel.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);
+
+
lambda = lambda + dLambda;
if (lambda > btScalar(1.))
@@ -135,9 +148,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 +181,13 @@ 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;
+ result.m_hitPoint = pointCollector.m_pointInWorld;
return true;
}
c = pointCollector.m_pointInWorld;
-
+ n = pointCollector.m_normalOnBInWorld;
dist = pointCollector.m_distance;
} else
{
@@ -177,8 +197,13 @@ bool btContinuousConvexCollision::calcTimeOfImpact(
}
+ //don't report time of impact for motion away from the contact normal (or causes minor penetration)
+ if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=result.m_allowedPenetration)//SIMD_EPSILON)
+ return false;
+
result.m_fraction = lambda;
result.m_normal = n;
+ result.m_hitPoint = c;
return true;
}
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..0edf4dcd496 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
@@ -42,19 +42,21 @@ public:
CastResult()
:m_fraction(btScalar(1e30)),
- m_debugDrawer(0)
+ m_debugDrawer(0),
+ m_allowedPenetration(btScalar(0))
{
}
virtual ~CastResult() {};
- btVector3 m_normal;
- btScalar m_fraction;
btTransform m_hitTransformA;
btTransform m_hitTransformB;
-
+ btVector3 m_normal;
+ btVector3 m_hitPoint;
+ btScalar m_fraction; //input and output
btIDebugDraw* m_debugDrawer;
+ btScalar m_allowedPenetration;
};
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..db797d5141f 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
@@ -58,7 +58,7 @@ struct 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;
+ virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false) = 0;
};
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
index 93edffeafd6..bef697a0a11 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
@@ -17,12 +17,17 @@ subject to the following restrictions:
#include "btGjkConvexCast.h"
#include "BulletCollision/CollisionShapes/btSphereShape.h"
-#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
#include "btGjkPairDetector.h"
#include "btPointCollector.h"
+#include "LinearMath/btTransformUtil.h"
+#ifdef BT_USE_DOUBLE_PRECISION
+#define MAX_ITERATIONS 64
+#else
+#define MAX_ITERATIONS 32
+#endif
-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)
@@ -38,120 +43,113 @@ bool btGjkConvexCast::calcTimeOfImpact(
{
- 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);
-
+ m_simplexSolver->reset();
+ /// compute linear velocity for this interval, to interpolate
+ //assume no rotation/angular velocity, assert here?
+ btVector3 linVelA,linVelB;
+ linVelA = toA.getOrigin()-fromA.getOrigin();
+ linVelB = toB.getOrigin()-fromB.getOrigin();
+ btScalar radius = btScalar(0.001);
+ btScalar lambda = btScalar(0.);
+ btVector3 v(1,0,0);
- btScalar radius = btScalar(0.01);
+ int maxIter = MAX_ITERATIONS;
- btScalar lambda = btScalar(0.);
- btVector3 s = rayFromLocalA.getOrigin();
- btVector3 r = rayToLocalA.getOrigin()-rayFromLocalA.getOrigin();
- btVector3 x = s;
btVector3 n;
- n.setValue(0,0,0);
+ n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
bool hasResult = false;
btVector3 c;
+ btVector3 r = (linVelA-linVelB);
btScalar lastLambda = lambda;
+ //btScalar epsilon = btScalar(0.001);
+ int numIter = 0;
//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);
- result.drawCoordSystem(sphereTr);
- {
- btPointCollector pointCollector1;
- btGjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr);
+ btPointCollector pointCollector;
- btGjkPairDetector::ClosestPointInput input;
- input.m_transformA = sphereTr;
- input.m_transformB = identityTrans;
- gjk.getClosestPoints(input,pointCollector1,0);
+
+ btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,0);//m_penetrationDepthSolver);
+ btGjkPairDetector::ClosestPointInput input;
- hasResult = pointCollector1.m_hasResult;
- c = pointCollector1.m_pointInWorld;
- n = pointCollector1.m_normalOnBInWorld;
- }
+ //we don't use margins during CCD
+ // gjk.setIgnoreMargin(true);
-
+ input.m_transformA = fromA;
+ input.m_transformB = fromB;
+ gjk.getClosestPoints(input,pointCollector,0);
+
+ hasResult = pointCollector.m_hasResult;
+ c = pointCollector.m_pointInWorld;
if (hasResult)
{
btScalar dist;
- dist = (c-x).length();
- if (dist < radius)
- {
- //penetration
- lastLambda = btScalar(1.);
- }
+ dist = pointCollector.m_distance;
+ n = pointCollector.m_normalOnBInWorld;
+
+
//not close enough
while (dist > radius)
{
+ numIter++;
+ if (numIter > maxIter)
+ {
+ return false; //todo: report a failure
+ }
+ btScalar dLambda = btScalar(0.);
+
+ btScalar projectedLinearVelocity = r.dot(n);
- n = x - c;
- btScalar nDotr = n.dot(r);
+ dLambda = dist / (projectedLinearVelocity);
+
+ lambda = lambda - dLambda;
- if (nDotr >= -(SIMD_EPSILON*SIMD_EPSILON))
+ if (lambda > btScalar(1.))
return false;
-
- lambda = lambda - n.dot(n) / nDotr;
+
+ 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;
- 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;
+ //interpolate to next lambda
+ result.DebugDraw( lambda );
+ input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
+ input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
+
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;
+ n = pointCollector.m_normalOnBInWorld;
+ result.m_normal=n;
+ result.m_hitPoint = pointCollector.m_pointInWorld;
return true;
}
- c = pointCollector.m_pointInWorld;
- dist = (c-x).length();
+ c = pointCollector.m_pointInWorld;
+ n = pointCollector.m_normalOnBInWorld;
+ dist = pointCollector.m_distance;
} else
{
//??
@@ -160,15 +158,19 @@ bool btGjkConvexCast::calcTimeOfImpact(
}
- if (lastLambda < btScalar(1.))
- {
-
- result.m_fraction = lastLambda;
- result.m_normal = n;
- return true;
- }
+ //is n normalized?
+ //don't report time of impact for motion away from the contact normal (or causes minor penetration)
+ if (n.dot(r)>=-result.m_allowedPenetration)
+ return false;
+
+ result.m_fraction = lambda;
+ result.m_normal = n;
+ result.m_hitPoint = c;
+ return true;
}
return false;
+
+
}
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..36cdeeaefdb 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp
@@ -26,7 +26,7 @@ Nov.2006
#include "btGjkEpa.h"
#include <string.h> //for memset
-#include <LinearMath/btStackAlloc.h>
+#include "LinearMath/btStackAlloc.h"
#if defined(DEBUG) || defined (_DEBUG)
#include <stdio.h> //for debug printf
@@ -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)
@@ -602,13 +602,13 @@ GJK gjk(stackAlloc,
wtrs1.getBasis(),wtrs1.getOrigin(),shape1,
radialmargin+EPA_accuracy);
const Z collide(gjk.SearchOrigin());
-results.gjk_iterations = gjk.iterations+1;
+results.gjk_iterations = static_cast<int>(gjk.iterations+1);
if(collide)
{
/* Then EPA for penetration depth */
EPA epa(&gjk);
const F pd(epa.EvaluatePD());
- results.epa_iterations = epa.iterations+1;
+ results.epa_iterations = static_cast<int>(epa.iterations+1);
if(pd>0)
{
results.status = sResults::Penetrating;
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h
index 759b30bb17f..1c256f41939 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;
@@ -35,7 +35,7 @@ struct sResults
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 */
+ EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
} status;
btVector3 witnesses[2];
btVector3 normal;
@@ -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/btGjkEpa2.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
new file mode 100644
index 00000000000..ccfc22ee673
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
@@ -0,0 +1,943 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as 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, 2008
+*/
+#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "btGjkEpa2.h"
+
+#if defined(DEBUG) || defined (_DEBUG)
+#include <stdio.h> //for debug printf
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+#endif //__SPU__
+#endif
+
+namespace gjkepa2_impl
+{
+
+// Config
+
+ /* GJK */
+#define GJK_MAX_ITERATIONS 128
+#define GJK_ACCURARY ((btScalar)0.0001)
+#define GJK_MIN_DISTANCE ((btScalar)0.0001)
+#define GJK_DUPLICATED_EPS ((btScalar)0.0001)
+#define GJK_SIMPLEX2_EPS ((btScalar)0.0)
+#define GJK_SIMPLEX3_EPS ((btScalar)0.0)
+#define GJK_SIMPLEX4_EPS ((btScalar)0.0)
+
+ /* EPA */
+#define EPA_MAX_VERTICES 64
+#define EPA_MAX_FACES (EPA_MAX_VERTICES*2)
+#define EPA_MAX_ITERATIONS 255
+#define EPA_ACCURACY ((btScalar)0.0001)
+#define EPA_FALLBACK (10*EPA_ACCURACY)
+#define EPA_PLANE_EPS ((btScalar)0.00001)
+#define EPA_INSIDE_EPS ((btScalar)0.01)
+
+
+// Shorthands
+typedef unsigned int U;
+typedef unsigned char U1;
+
+// MinkowskiDiff
+struct MinkowskiDiff
+ {
+ const btConvexShape* m_shapes[2];
+ btMatrix3x3 m_toshape1;
+ btTransform m_toshape0;
+ btVector3 (btConvexShape::*Ls)(const btVector3&) const;
+ void EnableMargin(bool enable)
+ {
+ if(enable)
+ Ls=&btConvexShape::localGetSupportingVertex;
+ else
+ Ls=&btConvexShape::localGetSupportingVertexWithoutMargin;
+ }
+ inline btVector3 Support0(const btVector3& d) const
+ {
+ return(((m_shapes[0])->*(Ls))(d));
+ }
+ inline btVector3 Support1(const btVector3& d) const
+ {
+ return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d));
+ }
+ inline btVector3 Support(const btVector3& d) const
+ {
+ return(Support0(d)-Support1(-d));
+ }
+ btVector3 Support(const btVector3& d,U index) const
+ {
+ if(index)
+ return(Support1(d));
+ else
+ return(Support0(d));
+ }
+ };
+
+typedef MinkowskiDiff tShape;
+
+
+// GJK
+struct GJK
+{
+/* Types */
+struct sSV
+ {
+ btVector3 d,w;
+ };
+struct sSimplex
+ {
+ sSV* c[4];
+ btScalar p[4];
+ U rank;
+ };
+struct eStatus { enum _ {
+ Valid,
+ Inside,
+ Failed };};
+/* Fields */
+tShape m_shape;
+btVector3 m_ray;
+btScalar m_distance;
+sSimplex m_simplices[2];
+sSV m_store[4];
+sSV* m_free[4];
+U m_nfree;
+U m_current;
+sSimplex* m_simplex;
+eStatus::_ m_status;
+/* Methods */
+ GJK()
+ {
+ Initialize();
+ }
+void Initialize()
+ {
+ m_ray = btVector3(0,0,0);
+ m_nfree = 0;
+ m_status = eStatus::Failed;
+ m_current = 0;
+ m_distance = 0;
+ }
+eStatus::_ Evaluate(const tShape& shapearg,const btVector3& guess)
+ {
+ U iterations=0;
+ btScalar sqdist=0;
+ btScalar alpha=0;
+ btVector3 lastw[4];
+ U clastw=0;
+ /* Initialize solver */
+ m_free[0] = &m_store[0];
+ m_free[1] = &m_store[1];
+ m_free[2] = &m_store[2];
+ m_free[3] = &m_store[3];
+ m_nfree = 4;
+ m_current = 0;
+ m_status = eStatus::Valid;
+ m_shape = shapearg;
+ m_distance = 0;
+ /* Initialize simplex */
+ m_simplices[0].rank = 0;
+ m_ray = guess;
+ const btScalar sqrl= m_ray.length2();
+ appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0));
+ m_simplices[0].p[0] = 1;
+ m_ray = m_simplices[0].c[0]->w;
+ sqdist = sqrl;
+ lastw[0] =
+ lastw[1] =
+ lastw[2] =
+ lastw[3] = m_ray;
+ /* Loop */
+ do {
+ const U next=1-m_current;
+ sSimplex& cs=m_simplices[m_current];
+ sSimplex& ns=m_simplices[next];
+ /* Check zero */
+ const btScalar rl=m_ray.length();
+ if(rl<GJK_MIN_DISTANCE)
+ {/* Touching or inside */
+ m_status=eStatus::Inside;
+ break;
+ }
+ /* Append new vertice in -'v' direction */
+ appendvertice(cs,-m_ray);
+ const btVector3& w=cs.c[cs.rank-1]->w;
+ bool found=false;
+ for(U i=0;i<4;++i)
+ {
+ if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
+ { found=true;break; }
+ }
+ if(found)
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ else
+ {/* Update lastw */
+ lastw[clastw=(clastw+1)&3]=w;
+ }
+ /* Check for termination */
+ const btScalar omega=dot(m_ray,w)/rl;
+ alpha=btMax(omega,alpha);
+ if(((rl-alpha)-(GJK_ACCURARY*rl))<=0)
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ /* Reduce simplex */
+ btScalar weights[4];
+ U mask=0;
+ switch(cs.rank)
+ {
+ case 2: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ weights,mask);break;
+ case 3: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ weights,mask);break;
+ case 4: sqdist=projectorigin( cs.c[0]->w,
+ cs.c[1]->w,
+ cs.c[2]->w,
+ cs.c[3]->w,
+ weights,mask);break;
+ }
+ if(sqdist>=0)
+ {/* Valid */
+ ns.rank = 0;
+ m_ray = btVector3(0,0,0);
+ m_current = next;
+ for(U i=0,ni=cs.rank;i<ni;++i)
+ {
+ if(mask&(1<<i))
+ {
+ ns.c[ns.rank] = cs.c[i];
+ ns.p[ns.rank++] = weights[i];
+ m_ray += cs.c[i]->w*weights[i];
+ }
+ else
+ {
+ m_free[m_nfree++] = cs.c[i];
+ }
+ }
+ if(mask==15) m_status=eStatus::Inside;
+ }
+ else
+ {/* Return old simplex */
+ removevertice(m_simplices[m_current]);
+ break;
+ }
+ m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eStatus::Failed;
+ } while(m_status==eStatus::Valid);
+ m_simplex=&m_simplices[m_current];
+ switch(m_status)
+ {
+ case eStatus::Valid: m_distance=m_ray.length();break;
+ case eStatus::Inside: m_distance=0;break;
+ }
+ return(m_status);
+ }
+bool EncloseOrigin()
+ {
+ switch(m_simplex->rank)
+ {
+ case 1:
+ {
+ for(U i=0;i<3;++i)
+ {
+ btVector3 axis=btVector3(0,0,0);
+ axis[i]=1;
+ appendvertice(*m_simplex, axis);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-axis);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ break;
+ case 2:
+ {
+ const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w;
+ for(U i=0;i<3;++i)
+ {
+ btVector3 axis=btVector3(0,0,0);
+ axis[i]=1;
+ const btVector3 p=cross(d,axis);
+ if(p.length2()>0)
+ {
+ appendvertice(*m_simplex, p);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-p);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ }
+ break;
+ case 3:
+ {
+ const btVector3 n=cross(m_simplex->c[1]->w-m_simplex->c[0]->w,
+ m_simplex->c[2]->w-m_simplex->c[0]->w);
+ if(n.length2()>0)
+ {
+ appendvertice(*m_simplex,n);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ appendvertice(*m_simplex,-n);
+ if(EncloseOrigin()) return(true);
+ removevertice(*m_simplex);
+ }
+ }
+ break;
+ case 4:
+ {
+ if(btFabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w,
+ m_simplex->c[1]->w-m_simplex->c[3]->w,
+ m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
+ return(true);
+ }
+ break;
+ }
+ return(false);
+ }
+/* Internals */
+void getsupport(const btVector3& d,sSV& sv) const
+ {
+ sv.d = d/d.length();
+ sv.w = m_shape.Support(sv.d);
+ }
+void removevertice(sSimplex& simplex)
+ {
+ m_free[m_nfree++]=simplex.c[--simplex.rank];
+ }
+void appendvertice(sSimplex& simplex,const btVector3& v)
+ {
+ simplex.p[simplex.rank]=0;
+ simplex.c[simplex.rank]=m_free[--m_nfree];
+ getsupport(v,*simplex.c[simplex.rank++]);
+ }
+static btScalar det(const btVector3& a,const btVector3& b,const btVector3& c)
+ {
+ return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()-
+ a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+
+ a.x()*b.y()*c.z()-a.z()*b.y()*c.x());
+ }
+static btScalar projectorigin( const btVector3& a,
+ const btVector3& b,
+ btScalar* w,U& m)
+ {
+ const btVector3 d=b-a;
+ const btScalar l=d.length2();
+ if(l>GJK_SIMPLEX2_EPS)
+ {
+ const btScalar t(l>0?-dot(a,d)/l:0);
+ if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); }
+ else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); }
+ else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
+ }
+ return(-1);
+ }
+static btScalar projectorigin( const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btScalar* w,U& m)
+ {
+ static const U imd3[]={1,2,0};
+ const btVector3* vt[]={&a,&b,&c};
+ const btVector3 dl[]={a-b,b-c,c-a};
+ const btVector3 n=cross(dl[0],dl[1]);
+ const btScalar l=n.length2();
+ if(l>GJK_SIMPLEX3_EPS)
+ {
+ btScalar mindist=-1;
+ btScalar subw[2];
+ U subm;
+ for(U i=0;i<3;++i)
+ {
+ if(dot(*vt[i],cross(dl[i],n))>0)
+ {
+ const U j=imd3[i];
+ const btScalar subd(projectorigin(*vt[i],*vt[j],subw,subm));
+ if((mindist<0)||(subd<mindist))
+ {
+ mindist = subd;
+ m = static_cast<U>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ }
+ }
+ }
+ if(mindist<0)
+ {
+ const btScalar d=dot(a,n);
+ const btScalar s=btSqrt(l);
+ const btVector3 p=n*(d/l);
+ mindist = p.length2();
+ m = 7;
+ w[0] = (cross(dl[1],b-p)).length()/s;
+ w[1] = (cross(dl[2],c-p)).length()/s;
+ w[2] = 1-(w[0]+w[1]);
+ }
+ return(mindist);
+ }
+ return(-1);
+ }
+static btScalar projectorigin( const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ const btVector3& d,
+ btScalar* w,U& m)
+ {
+ static const U imd3[]={1,2,0};
+ const btVector3* vt[]={&a,&b,&c,&d};
+ const btVector3 dl[]={a-d,b-d,c-d};
+ const btScalar vl=det(dl[0],dl[1],dl[2]);
+ const bool ng=(vl*dot(a,cross(b-c,a-b)))<=0;
+ if(ng&&(btFabs(vl)>GJK_SIMPLEX4_EPS))
+ {
+ btScalar mindist=-1;
+ btScalar subw[3];
+ U subm;
+ for(U i=0;i<3;++i)
+ {
+ const U j=imd3[i];
+ const btScalar s=vl*dot(d,cross(dl[i],dl[j]));
+ if(s>0)
+ {
+ const btScalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
+ if((mindist<0)||(subd<mindist))
+ {
+ mindist = subd;
+ m = static_cast<U>((subm&1?1<<i:0)+
+ (subm&2?1<<j:0)+
+ (subm&4?8:0));
+ w[i] = subw[0];
+ w[j] = subw[1];
+ w[imd3[j]] = 0;
+ w[3] = subw[2];
+ }
+ }
+ }
+ if(mindist<0)
+ {
+ mindist = 0;
+ m = 15;
+ w[0] = det(c,b,d)/vl;
+ w[1] = det(a,c,d)/vl;
+ w[2] = det(b,a,d)/vl;
+ w[3] = 1-(w[0]+w[1]+w[2]);
+ }
+ return(mindist);
+ }
+ return(-1);
+ }
+};
+
+// EPA
+struct EPA
+{
+/* Types */
+typedef GJK::sSV sSV;
+struct sFace
+ {
+ btVector3 n;
+ btScalar d;
+ btScalar p;
+ sSV* c[3];
+ sFace* f[3];
+ sFace* l[2];
+ U1 e[3];
+ U1 pass;
+ };
+struct sList
+ {
+ sFace* root;
+ U count;
+ sList() : root(0),count(0) {}
+ };
+struct sHorizon
+ {
+ sFace* cf;
+ sFace* ff;
+ U nf;
+ sHorizon() : cf(0),ff(0),nf(0) {}
+ };
+struct eStatus { enum _ {
+ Valid,
+ Touching,
+ Degenerated,
+ NonConvex,
+ InvalidHull,
+ OutOfFaces,
+ OutOfVertices,
+ AccuraryReached,
+ FallBack,
+ Failed };};
+/* Fields */
+eStatus::_ m_status;
+GJK::sSimplex m_result;
+btVector3 m_normal;
+btScalar m_depth;
+sSV m_sv_store[EPA_MAX_VERTICES];
+sFace m_fc_store[EPA_MAX_FACES];
+U m_nextsv;
+sList m_hull;
+sList m_stock;
+/* Methods */
+ EPA()
+ {
+ Initialize();
+ }
+
+
+ static inline void bind(sFace* fa,U ea,sFace* fb,U eb)
+ {
+ fa->e[ea]=(U1)eb;fa->f[ea]=fb;
+ fb->e[eb]=(U1)ea;fb->f[eb]=fa;
+ }
+static inline void append(sList& list,sFace* face)
+ {
+ face->l[0] = 0;
+ face->l[1] = list.root;
+ if(list.root) list.root->l[0]=face;
+ list.root = face;
+ ++list.count;
+ }
+static inline void remove(sList& list,sFace* face)
+ {
+ if(face->l[1]) face->l[1]->l[0]=face->l[0];
+ if(face->l[0]) face->l[0]->l[1]=face->l[1];
+ if(face==list.root) list.root=face->l[1];
+ --list.count;
+ }
+
+
+void Initialize()
+ {
+ m_status = eStatus::Failed;
+ m_normal = btVector3(0,0,0);
+ m_depth = 0;
+ m_nextsv = 0;
+ for(U i=0;i<EPA_MAX_FACES;++i)
+ {
+ append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
+ }
+ }
+eStatus::_ Evaluate(GJK& gjk,const btVector3& guess)
+ {
+ GJK::sSimplex& simplex=*gjk.m_simplex;
+ if((simplex.rank>1)&&gjk.EncloseOrigin())
+ {
+
+ /* Clean up */
+ while(m_hull.root)
+ {
+ sFace* f = m_hull.root;
+ remove(m_hull,f);
+ append(m_stock,f);
+ }
+ m_status = eStatus::Valid;
+ m_nextsv = 0;
+ /* Orient simplex */
+ if(gjk.det( simplex.c[0]->w-simplex.c[3]->w,
+ simplex.c[1]->w-simplex.c[3]->w,
+ simplex.c[2]->w-simplex.c[3]->w)<0)
+ {
+ btSwap(simplex.c[0],simplex.c[1]);
+ btSwap(simplex.p[0],simplex.p[1]);
+ }
+ /* Build initial hull */
+ sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
+ newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
+ newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
+ newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
+ if(m_hull.count==4)
+ {
+ sFace* best=findbest();
+ sFace outer=*best;
+ U pass=0;
+ U iterations=0;
+ bind(tetra[0],0,tetra[1],0);
+ bind(tetra[0],1,tetra[2],0);
+ bind(tetra[0],2,tetra[3],0);
+ bind(tetra[1],1,tetra[3],2);
+ bind(tetra[1],2,tetra[2],1);
+ bind(tetra[2],2,tetra[3],1);
+ m_status=eStatus::Valid;
+ for(;iterations<EPA_MAX_ITERATIONS;++iterations)
+ {
+ if(m_nextsv<EPA_MAX_VERTICES)
+ {
+ sHorizon horizon;
+ sSV* w=&m_sv_store[m_nextsv++];
+ bool valid=true;
+ best->pass = (U1)(++pass);
+ gjk.getsupport(best->n,*w);
+ const btScalar wdist=dot(best->n,w->w)-best->d;
+ if(wdist>EPA_ACCURACY)
+ {
+ for(U j=0;(j<3)&&valid;++j)
+ {
+ valid&=expand( pass,w,
+ best->f[j],best->e[j],
+ horizon);
+ }
+ if(valid&&(horizon.nf>=3))
+ {
+ bind(horizon.cf,1,horizon.ff,2);
+ remove(m_hull,best);
+ append(m_stock,best);
+ best=findbest();
+ if(best->p>=outer.p) outer=*best;
+ } else { m_status=eStatus::InvalidHull;break; }
+ } else { m_status=eStatus::AccuraryReached;break; }
+ } else { m_status=eStatus::OutOfVertices;break; }
+ }
+ const btVector3 projection=outer.n*outer.d;
+ m_normal = outer.n;
+ m_depth = outer.d;
+ m_result.rank = 3;
+ m_result.c[0] = outer.c[0];
+ m_result.c[1] = outer.c[1];
+ m_result.c[2] = outer.c[2];
+ m_result.p[0] = cross( outer.c[1]->w-projection,
+ outer.c[2]->w-projection).length();
+ m_result.p[1] = cross( outer.c[2]->w-projection,
+ outer.c[0]->w-projection).length();
+ m_result.p[2] = cross( outer.c[0]->w-projection,
+ outer.c[1]->w-projection).length();
+ const btScalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
+ m_result.p[0] /= sum;
+ m_result.p[1] /= sum;
+ m_result.p[2] /= sum;
+ return(m_status);
+ }
+ }
+ /* Fallback */
+ m_status = eStatus::FallBack;
+ m_normal = -guess;
+ const btScalar nl=m_normal.length();
+ if(nl>0)
+ m_normal = m_normal/nl;
+ else
+ m_normal = btVector3(1,0,0);
+ m_depth = 0;
+ m_result.rank=1;
+ m_result.c[0]=simplex.c[0];
+ m_result.p[0]=1;
+ return(m_status);
+ }
+sFace* newface(sSV* a,sSV* b,sSV* c,bool forced)
+ {
+ if(m_stock.root)
+ {
+ sFace* face=m_stock.root;
+ remove(m_stock,face);
+ append(m_hull,face);
+ face->pass = 0;
+ face->c[0] = a;
+ face->c[1] = b;
+ face->c[2] = c;
+ face->n = cross(b->w-a->w,c->w-a->w);
+ const btScalar l=face->n.length();
+ const bool v=l>EPA_ACCURACY;
+ face->p = btMin(btMin(
+ dot(a->w,cross(face->n,a->w-b->w)),
+ dot(b->w,cross(face->n,b->w-c->w))),
+ dot(c->w,cross(face->n,c->w-a->w))) /
+ (v?l:1);
+ face->p = face->p>=-EPA_INSIDE_EPS?0:face->p;
+ if(v)
+ {
+ face->d = dot(a->w,face->n)/l;
+ face->n /= l;
+ if(forced||(face->d>=-EPA_PLANE_EPS))
+ {
+ return(face);
+ } else m_status=eStatus::NonConvex;
+ } else m_status=eStatus::Degenerated;
+ remove(m_hull,face);
+ append(m_stock,face);
+ return(0);
+ }
+ m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces;
+ return(0);
+ }
+sFace* findbest()
+ {
+ sFace* minf=m_hull.root;
+ btScalar mind=minf->d*minf->d;
+ btScalar maxp=minf->p;
+ for(sFace* f=minf->l[1];f;f=f->l[1])
+ {
+ const btScalar sqd=f->d*f->d;
+ if((f->p>=maxp)&&(sqd<mind))
+ {
+ minf=f;
+ mind=sqd;
+ maxp=f->p;
+ }
+ }
+ return(minf);
+ }
+bool expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon)
+ {
+ static const U i1m3[]={1,2,0};
+ static const U i2m3[]={2,0,1};
+ if(f->pass!=pass)
+ {
+ const U e1=i1m3[e];
+ if((dot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
+ {
+ sFace* nf=newface(f->c[e1],f->c[e],w,false);
+ if(nf)
+ {
+ bind(nf,0,f,e);
+ if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
+ horizon.cf=nf;
+ ++horizon.nf;
+ return(true);
+ }
+ }
+ else
+ {
+ const U e2=i2m3[e];
+ f->pass = (U1)pass;
+ if( expand(pass,w,f->f[e1],f->e[e1],horizon)&&
+ expand(pass,w,f->f[e2],f->e[e2],horizon))
+ {
+ remove(m_hull,f);
+ append(m_stock,f);
+ return(true);
+ }
+ }
+ }
+ return(false);
+ }
+
+};
+
+//
+static void Initialize( const btConvexShape* shape0,const btTransform& wtrs0,
+ const btConvexShape* shape1,const btTransform& wtrs1,
+ btGjkEpaSolver2::sResults& results,
+ tShape& shape,
+ bool withmargins)
+{
+/* Results */
+results.witnesses[0] =
+results.witnesses[1] = btVector3(0,0,0);
+results.status = btGjkEpaSolver2::sResults::Separated;
+/* Shape */
+shape.m_shapes[0] = shape0;
+shape.m_shapes[1] = shape1;
+shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis());
+shape.m_toshape0 = wtrs0.inverseTimes(wtrs1);
+shape.EnableMargin(withmargins);
+}
+
+}
+
+//
+// Api
+//
+
+using namespace gjkepa2_impl;
+
+//
+int btGjkEpaSolver2::StackSizeRequirement()
+{
+return(sizeof(GJK)+sizeof(EPA));
+}
+
+//
+bool btGjkEpaSolver2::Distance( const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ const btConvexShape* shape1,
+ const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results)
+{
+tShape shape;
+Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false);
+GJK gjk;
+GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess);
+if(gjk_status==GJK::eStatus::Valid)
+ {
+ btVector3 w0=btVector3(0,0,0);
+ btVector3 w1=btVector3(0,0,0);
+ for(U i=0;i<gjk.m_simplex->rank;++i)
+ {
+ const btScalar p=gjk.m_simplex->p[i];
+ w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
+ w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+ }
+ results.witnesses[0] = wtrs0*w0;
+ results.witnesses[1] = wtrs0*w1;
+ results.normal = w0-w1;
+ results.distance = results.normal.length();
+ results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1;
+ return(true);
+ }
+ else
+ {
+ results.status = gjk_status==GJK::eStatus::Inside?
+ sResults::Penetrating :
+ sResults::GJK_Failed ;
+ return(false);
+ }
+}
+
+//
+bool btGjkEpaSolver2::Penetration( const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ const btConvexShape* shape1,
+ const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results,
+ bool usemargins)
+{
+tShape shape;
+Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins);
+GJK gjk;
+GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess);
+switch(gjk_status)
+ {
+ case GJK::eStatus::Inside:
+ {
+ EPA epa;
+ EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess);
+ if(epa_status!=EPA::eStatus::Failed)
+ {
+ btVector3 w0=btVector3(0,0,0);
+ for(U i=0;i<epa.m_result.rank;++i)
+ {
+ w0+=shape.Support(epa.m_result.c[i]->d,0)*epa.m_result.p[i];
+ }
+ results.status = sResults::Penetrating;
+ results.witnesses[0] = wtrs0*w0;
+ results.witnesses[1] = wtrs0*(w0-epa.m_normal*epa.m_depth);
+ results.normal = -epa.m_normal;
+ results.distance = -epa.m_depth;
+ return(true);
+ } else results.status=sResults::EPA_Failed;
+ }
+ break;
+ case GJK::eStatus::Failed:
+ results.status=sResults::GJK_Failed;
+ break;
+ }
+return(false);
+}
+
+//
+btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position,
+ btScalar margin,
+ const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ sResults& results)
+{
+tShape shape;
+btSphereShape shape1(margin);
+btTransform wtrs1(btQuaternion(0,0,0,1),position);
+Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false);
+GJK gjk;
+GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,btVector3(1,1,1));
+if(gjk_status==GJK::eStatus::Valid)
+ {
+ btVector3 w0=btVector3(0,0,0);
+ btVector3 w1=btVector3(0,0,0);
+ for(U i=0;i<gjk.m_simplex->rank;++i)
+ {
+ const btScalar p=gjk.m_simplex->p[i];
+ w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
+ w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+ }
+ results.witnesses[0] = wtrs0*w0;
+ results.witnesses[1] = wtrs0*w1;
+ const btVector3 delta= results.witnesses[1]-
+ results.witnesses[0];
+ const btScalar margin= shape0->getMargin()+
+ shape1.getMargin();
+ const btScalar length= delta.length();
+ results.normal = delta/length;
+ results.witnesses[0] += results.normal*margin;
+ return(length-margin);
+ }
+ else
+ {
+ if(gjk_status==GJK::eStatus::Inside)
+ {
+ if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results))
+ {
+ const btVector3 delta= results.witnesses[0]-
+ results.witnesses[1];
+ const btScalar length= delta.length();
+ if (length >= SIMD_EPSILON)
+ results.normal = delta/length;
+ return(-length);
+ }
+ }
+ }
+return(SIMD_INFINITY);
+}
+
+//
+bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0,
+ const btTransform& wtrs0,
+ const btConvexShape* shape1,
+ const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results)
+{
+if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results))
+ return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false));
+ else
+ return(true);
+}
+
+/* Symbols cleanup */
+
+#undef GJK_MAX_ITERATIONS
+#undef GJK_ACCURARY
+#undef GJK_MIN_DISTANCE
+#undef GJK_DUPLICATED_EPS
+#undef GJK_SIMPLEX2_EPS
+#undef GJK_SIMPLEX3_EPS
+#undef GJK_SIMPLEX4_EPS
+
+#undef EPA_MAX_VERTICES
+#undef EPA_MAX_FACES
+#undef EPA_MAX_ITERATIONS
+#undef EPA_ACCURACY
+#undef EPA_FALLBACK
+#undef EPA_PLANE_EPS
+#undef EPA_INSIDE_EPS
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
new file mode 100644
index 00000000000..a55214203d3
--- /dev/null
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
@@ -0,0 +1,71 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as 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, 2008
+*/
+#ifndef _68DA1F85_90B7_4bb0_A705_83B4040A75C6_
+#define _68DA1F85_90B7_4bb0_A705_83B4040A75C6_
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+///btGjkEpaSolver contributed under zlib by Nathanael Presson
+struct btGjkEpaSolver2
+{
+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 distance;
+ };
+
+static int StackSizeRequirement();
+
+static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0,
+ const btConvexShape* shape1,const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results);
+
+static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0,
+ const btConvexShape* shape1,const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results,
+ bool usemargins=true);
+
+static btScalar SignedDistance( const btVector3& position,
+ btScalar margin,
+ const btConvexShape* shape,
+ const btTransform& wtrs,
+ sResults& results);
+
+static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0,
+ const btConvexShape* shape1,const btTransform& wtrs1,
+ const btVector3& guess,
+ sResults& results);
+};
+
+#endif
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
index 87330493b60..c4f84ed4d75 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
@@ -18,9 +18,10 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btConvexShape.h"
#include "btGjkEpaPenetrationDepthSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.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 )
@@ -32,10 +33,20 @@ bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& sim
const btScalar radialmargin(btScalar(0.));
+//#define USE_ORIGINAL_GJK 1
+#ifdef USE_ORIGINAL_GJK
btGjkEpaSolver::sResults results;
if(btGjkEpaSolver::Collide( pConvexA,transformA,
pConvexB,transformB,
radialmargin,stackAlloc,results))
+#else
+ btVector3 guessVector(transformA.getOrigin()-transformB.getOrigin());
+ btGjkEpaSolver2::sResults results;
+ if(btGjkEpaSolver2::Penetration(pConvexA,transformA,
+ pConvexB,transformB,
+ guessVector,results))
+
+#endif
{
// debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
//resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
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..01fb1a4b068 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),
@@ -47,7 +47,7 @@ m_catchDegeneracies(1)
{
}
-void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
+void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
{
btScalar distance=btScalar(0.);
btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.));
@@ -144,6 +144,13 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result&
break;
}
+ if(m_cachedSeparatingAxis.length2()<REL_ERROR2)
+ {
+ m_degenerateSimplex = 6;
+ checkSimplex = true;
+ break;
+ }
+
btScalar previousSquaredDistance = squaredDistance;
squaredDistance = m_cachedSeparatingAxis.length2();
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
index af0fe32f6c7..550fc4677e0 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,10 +49,10 @@ 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);
+ virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
void setMinkowskiA(btConvexShape* minkA)
{
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
index f6a893151da..e75fc1bee96 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"
@@ -30,6 +30,8 @@ class btManifoldPoint
public:
btManifoldPoint()
:m_userPersistentData(0),
+ m_appliedImpulse(0.f),
+ m_lateralFrictionInitialized(false),
m_lifeTime(0)
{
}
@@ -43,7 +45,11 @@ class btManifoldPoint
m_distance1( distance ),
m_combinedFriction(btScalar(0.)),
m_combinedRestitution(btScalar(0.)),
- m_userPersistentData(0),
+ m_userPersistentData(0),
+ m_appliedImpulse(0.f),
+ m_lateralFrictionInitialized(false),
+ m_appliedImpulseLateral1(0.f),
+ m_appliedImpulseLateral2(0.f),
m_lifeTime(0)
{
@@ -63,11 +69,23 @@ class btManifoldPoint
btScalar m_combinedFriction;
btScalar m_combinedRestitution;
+ //BP mod, store contact triangles.
+ int m_partId0;
+ int m_partId1;
+ int m_index0;
+ int m_index1;
mutable void* m_userPersistentData;
+ btScalar m_appliedImpulse;
- int m_lifeTime;//lifetime of the contactpoint in frames
+ bool m_lateralFrictionInitialized;
+ btScalar m_appliedImpulseLateral1;
+ btScalar m_appliedImpulseLateral2;
+ int m_lifeTime;//lifetime of the contactpoint in frames
+ btVector3 m_lateralFrictionDir1;
+ btVector3 m_lateralFrictionDir2;
+
btScalar getDistance() const
{
return m_distance1;
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
index c4bab3a134a..0e6fa2e6dfe 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
@@ -14,10 +14,10 @@ subject to the following restrictions:
*/
#include "btMinkowskiPenetrationDepthSolver.h"
-#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
@@ -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..386885d2ac8 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
@@ -20,6 +20,7 @@ subject to the following restrictions:
btScalar gContactBreakingThreshold = btScalar(0.02);
ContactDestroyedCallback gContactDestroyedCallback = 0;
+ContactProcessedCallback gContactProcessedCallback = 0;
@@ -27,20 +28,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<m_cachedPoints;i++)
- {
- clearUserCache(m_pointCache[i]);
- }
- m_cachedPoints = 0;
-}
+
#ifdef DEBUG_PERSISTENCY
#include <stdio.h>
@@ -169,7 +162,7 @@ int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
return nearestPoint;
}
-void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint)
+int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint)
{
assert(validContactDistance(newPoint));
@@ -182,7 +175,7 @@ void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint)
#else
insertIndex = 0;
#endif
-
+ clearUserCache(m_pointCache[insertIndex]);
} else
{
@@ -190,7 +183,9 @@ void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint)
}
- replaceContactPoint(newPoint,insertIndex);
+ btAssert(m_pointCache[insertIndex].m_userPersistentData==0);
+ m_pointCache[insertIndex] = newPoint;
+ return insertIndex;
}
btScalar btPersistentManifold::getContactBreakingThreshold() const
@@ -198,10 +193,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--)
{
@@ -232,6 +237,11 @@ void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btT
if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() )
{
removeContactPoint(i);
+ } else
+ {
+ //contact point processed callback
+ if (gContactProcessedCallback)
+ (*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1);
}
}
}
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
index a5918b84db3..c122eb865e8 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;
@@ -27,6 +28,7 @@ struct btCollisionResult;
extern btScalar gContactBreakingThreshold;
typedef bool (*ContactDestroyedCallback)(void* userPersistentData);
+typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1);
extern ContactDestroyedCallback gContactDestroyedCallback;
@@ -34,8 +36,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 +62,23 @@ 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)
{
+ (void)bla;
}
- 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 +92,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];
@@ -101,7 +111,7 @@ public:
int getCacheEntry(const btManifoldPoint& newPoint) const;
- void AddManifoldPoint( const btManifoldPoint& newPoint);
+ int addManifoldPoint( const btManifoldPoint& newPoint);
void removeContactPoint (int index)
{
@@ -114,6 +124,11 @@ public:
m_pointCache[index] = m_pointCache[lastUsedIndex];
//get rid of duplicated userPersistentData pointer
m_pointCache[lastUsedIndex].m_userPersistentData = 0;
+ m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
+ m_pointCache[lastUsedIndex].m_lateralFrictionInitialized = false;
+ m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f;
+ m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f;
+ m_pointCache[lastUsedIndex].m_lifeTime = 0;
}
btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0);
@@ -126,12 +141,20 @@ public:
#define MAINTAIN_PERSISTENCY 1
#ifdef MAINTAIN_PERSISTENCY
int lifeTime = m_pointCache[insertIndex].getLifeTime();
+ btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse;
+ btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1;
+ btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2;
+
btAssert(lifeTime>=0);
void* cache = m_pointCache[insertIndex].m_userPersistentData;
m_pointCache[insertIndex] = newPoint;
m_pointCache[insertIndex].m_userPersistentData = cache;
+ m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
+ m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
+ m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
+
m_pointCache[insertIndex].m_lifeTime = lifeTime;
#else
clearUserCache(m_pointCache[insertIndex]);
@@ -147,7 +170,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<m_cachedPoints;i++)
+ {
+ clearUserCache(m_pointCache[i]);
+ }
+ m_cachedPoints = 0;
+ }
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
index 68ac93ec3cc..a70a3ae56c4 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
@@ -13,14 +13,20 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-
+//#include <stdio.h>
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
#include "btRaycastCallback.h"
-btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to,bool faceNormal)
+btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to)
:
m_from(from),
m_to(to),
- m_faceNormal(faceNormal),
m_hitFraction(btScalar(1.))
{
@@ -30,8 +36,6 @@ btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const
void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
{
-
-
const btVector3 &vert0=triangle[0];
const btVector3 &vert1=triangle[1];
const btVector3 &vert2=triangle[2];
@@ -85,7 +89,8 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId,
if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance)
{
- if (m_faceNormal || dist_a > 0)
+
+ if ( dist_a > 0 )
{
m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex);
}
@@ -99,3 +104,60 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId,
}
}
}
+
+
+btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin)
+{
+ m_convexShape = convexShape;
+ m_convexShapeFrom = convexShapeFrom;
+ m_convexShapeTo = convexShapeTo;
+ m_triangleToWorld = triangleToWorld;
+ m_hitFraction = 1.0;
+ m_triangleCollisionMargin = triangleCollisionMargin;
+}
+
+void
+btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex)
+{
+ btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]);
+ triangleShape.setMargin(m_triangleCollisionMargin);
+
+ btVoronoiSimplexSolver simplexSolver;
+ btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
+
+//#define USE_SUBSIMPLEX_CONVEX_CAST 1
+//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+ btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver);
+#else
+ //btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver);
+ btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver);
+#endif //#USE_SUBSIMPLEX_CONVEX_CAST
+
+ btConvexCast::CastResult castResult;
+ castResult.m_fraction = btScalar(1.);
+ if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult))
+ {
+ //add hit
+ if (castResult.m_normal.length2() > btScalar(0.0001))
+ {
+ if (castResult.m_fraction < m_hitFraction)
+ {
+/* btContinuousConvexCast's normal is already in world space */
+/*
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+ //rotate normal into worldspace
+ castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal;
+#endif //USE_SUBSIMPLEX_CONVEX_CAST
+*/
+ castResult.m_normal.normalize();
+
+ reportHit (castResult.m_normal,
+ castResult.m_hitPoint,
+ castResult.m_fraction,
+ partId,
+ triangleIndex);
+ }
+ }
+ }
+}
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
index 71ed9fead49..d2b4b80f8ba 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
@@ -16,22 +16,22 @@ subject to the following restrictions:
#ifndef RAYCAST_TRI_CALLBACK_H
#define RAYCAST_TRI_CALLBACK_H
-#include "../CollisionShapes/btTriangleCallback.h"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "LinearMath/btTransform.h"
struct btBroadphaseProxy;
-
+class btConvexShape;
class btTriangleRaycastCallback: public btTriangleCallback
{
public:
- //input
+ //input
btVector3 m_from;
btVector3 m_to;
- bool m_faceNormal;
btScalar m_hitFraction;
- btTriangleRaycastCallback(const btVector3& from,const btVector3& to,bool faceNormal);
+ btTriangleRaycastCallback(const btVector3& from,const btVector3& to);
virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
@@ -39,5 +39,22 @@ public:
};
+class btTriangleConvexcastCallback : public btTriangleCallback
+{
+public:
+ const btConvexShape* m_convexShape;
+ btTransform m_convexShapeFrom;
+ btTransform m_convexShapeTo;
+ btTransform m_triangleToWorld;
+ btScalar m_hitFraction;
+ btScalar m_triangleCollisionMargin;
+
+ btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin);
+
+ virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex);
+
+ virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, 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
index 58393b2eab9..cf65f46505b 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
@@ -18,8 +18,8 @@ subject to the following restrictions:
#ifndef SIMPLEX_SOLVER_INTERFACE_H
#define SIMPLEX_SOLVER_INTERFACE_H
-#include "../../LinearMath/btVector3.h"
-#include "../../LinearMath/btPoint3.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btPoint3.h"
#define NO_VIRTUAL_INTERFACE 1
#ifdef NO_VIRTUAL_INTERFACE
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
index 687738b7fa9..4c709a8c3a9 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
@@ -16,9 +16,11 @@ subject to the following restrictions:
#include "btSubSimplexConvexCast.h"
#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
-
+#include "btPointCollector.h"
+#include "LinearMath/btTransformUtil.h"
btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver)
:m_simplexSolver(simplexSolver),
@@ -41,34 +43,24 @@ bool btSubsimplexConvexCast::calcTimeOfImpact(
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);
+ btVector3 linVelA,linVelB;
+ linVelA = toA.getOrigin()-fromA.getOrigin();
+ linVelB = toB.getOrigin()-fromB.getOrigin();
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;
+
+ btTransform interpolatedTransA = fromA;
+ btTransform interpolatedTransB = fromB;
+
+ ///take relative motion
+ btVector3 r = (linVelA-linVelB);
btVector3 v;
- btVector3 arbitraryPoint = convex->localGetSupportingVertex(r);
- v = x - arbitraryPoint;
-
+ btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r*fromA.getBasis()));
+ btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r*fromB.getBasis()));
+ v = supVertexA-supVertexB;
int maxIter = MAX_ITERATIONS;
btVector3 n;
@@ -90,11 +82,17 @@ bool btSubsimplexConvexCast::calcTimeOfImpact(
while ( (dist2 > epsilon) && maxIter--)
{
- p = convex->localGetSupportingVertex( v);
- w = x - p;
+ supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v*interpolatedTransA.getBasis()));
+ supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v*interpolatedTransB.getBasis()));
+ w = supVertexA-supVertexB;
btScalar VdotW = v.dot(w);
+ if (lambda > btScalar(1.0))
+ {
+ return false;
+ }
+
if ( VdotW > btScalar(0.))
{
VdotR = v.dot(r);
@@ -104,20 +102,25 @@ bool btSubsimplexConvexCast::calcTimeOfImpact(
else
{
lambda = lambda - VdotW / VdotR;
- x = s + lambda * r;
- m_simplexSolver->reset();
+ //interpolate to next lambda
+ // x = s + lambda * r;
+ interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
+ interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
+ //m_simplexSolver->reset();
//check next line
- w = x-p;
+ w = supVertexA-supVertexB;
lastLambda = lambda;
n = v;
hasResult = true;
}
}
- m_simplexSolver->addVertex( w, x , p);
+ m_simplexSolver->addVertex( w, supVertexA , supVertexB);
if (m_simplexSolver->closest(v))
{
dist2 = v.length2();
hasResult = true;
+ //todo: check this normal for validity
+ //n=v;
//printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
//printf("DIST2=%f\n",dist2);
//printf("numverts = %i\n",m_simplexSolver->numVertices());
@@ -129,11 +132,26 @@ bool btSubsimplexConvexCast::calcTimeOfImpact(
//int numiter = MAX_ITERATIONS - maxIter;
// printf("number of iterations: %d", numiter);
- result.m_fraction = lambda;
- result.m_normal = n;
+
+ //don't report a time of impact when moving 'away' from the hitnormal
+
+ result.m_fraction = lambda;
+ if (n.length2() >= (SIMD_EPSILON*SIMD_EPSILON))
+ result.m_normal = n.normalized();
+ else
+ result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+
+ //don't report time of impact for motion away from the contact normal (or causes minor penetration)
+ if (result.m_normal.dot(r)>=-result.m_allowedPenetration)
+ return false;
+
+ btVector3 hitA,hitB;
+ m_simplexSolver->compute_points(hitA,hitB);
+ result.m_hitPoint=hitB;
return true;
}
+
diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
index 105b7eccefa..cf8a3ab5eb1 100644
--- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
+++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
@@ -26,7 +26,7 @@ subject to the following restrictions:
#include "btVoronoiSimplexSolver.h"
#include <assert.h>
-#include <stdio.h>
+//#include <stdio.h>
#define VERTA 0
#define VERTB 1
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
index 2289621e8e3..e11b49d9420 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
@@ -19,24 +19,20 @@ Written by: Marcus Hennix
#include "btConeTwistConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
-#include "LinearMath/btSimdMinMax.h"
+#include "LinearMath/btMinMax.h"
#include <new>
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
- 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);
@@ -49,20 +45,11 @@ 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;
- // 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);
@@ -142,7 +129,7 @@ void btConeTwistConstraint::buildJacobian()
btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1);
btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2);
- btScalar EllipseAngle = btFabs(swing1)* RMaxAngle1Sq + btFabs(swing2) * RMaxAngle2Sq;
+ btScalar EllipseAngle = btFabs(swing1*swing1)* RMaxAngle1Sq + btFabs(swing2*swing2) * RMaxAngle2Sq;
if (EllipseAngle > 1.0f)
{
@@ -246,7 +233,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;
@@ -264,7 +251,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..7a8e9c1953d 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..4d7cd05feb7 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;
}
@@ -237,6 +237,12 @@ btScalar resolveSingleFrictionOriginal(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
+ const btContactSolverInfo& solverInfo);
+
+btScalar resolveSingleFrictionOriginal(
+ btRigidBody& body1,
+ btRigidBody& body2,
+ btManifoldPoint& contactPoint,
const btContactSolverInfo& solverInfo)
{
@@ -270,8 +276,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 +296,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 +394,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);
}
@@ -404,6 +410,12 @@ btScalar resolveSingleFrictionEmpty(
btRigidBody& body1,
btRigidBody& body2,
btManifoldPoint& contactPoint,
+ const btContactSolverInfo& solverInfo);
+
+btScalar resolveSingleFrictionEmpty(
+ btRigidBody& body1,
+ btRigidBody& body2,
+ btManifoldPoint& contactPoint,
const btContactSolverInfo& solverInfo)
{
(void)contactPoint;
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..916d4581f79 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
@@ -16,10 +16,43 @@ subject to the following restrictions:
#ifndef CONTACT_SOLVER_INFO
#define CONTACT_SOLVER_INFO
+enum btSolverMode
+{
+ SOLVER_RANDMIZE_ORDER = 1,
+ SOLVER_FRICTION_SEPARATE = 2,
+ SOLVER_USE_WARMSTARTING = 4,
+ SOLVER_CACHE_FRIENDLY = 8
+};
+
+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;//used as Baumgarte factor
+ btScalar m_erp2;//used in Split Impulse
+ int m_splitImpulse;
+ btScalar m_splitImpulsePenetrationThreshold;
+ btScalar m_linearSlop;
+ btScalar m_warmstartingFactor;
+
+ int m_solverMode;
-struct btContactSolverInfo
+
+};
+
+struct btContactSolverInfo : public btContactSolverInfoData
{
+
+
inline btContactSolverInfo()
{
m_tau = btScalar(0.6);
@@ -28,20 +61,15 @@ struct btContactSolverInfo
m_restitution = btScalar(0.);
m_maxErrorReduction = btScalar(20.);
m_numIterations = 10;
- m_erp = btScalar(0.4);
+ m_erp = btScalar(0.2);
+ m_erp2 = btScalar(0.1);
m_sor = btScalar(1.3);
+ m_splitImpulse = false;
+ m_splitImpulsePenetrationThreshold = -0.02f;
+ m_linearSlop = btScalar(0.0);
+ m_warmstartingFactor=btScalar(0.85);
+ m_solverMode = SOLVER_RANDMIZE_ORDER | SOLVER_CACHE_FRIENDLY | SOLVER_USE_WARMSTARTING;
}
-
- 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..077b326d13a 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,504 @@ subject to the following restrictions:
#include "LinearMath/btTransformUtil.h"
#include <new>
+
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);
+btScalar btGetMatrixElem(const btMatrix3x3& mat, int index)
{
+ int i = index%3;
+ int j = index/3;
+ return mat[i][j];
}
-btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB)
-: btTypedConstraint(rbA, rbB)
-, m_frameInA(frameInA)
-, m_frameInB(frameInB)
+///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)
{
- //free means upper < lower,
- //locked means upper == lower
- //limited means upper > lower
- //so start all locked
- for (int i=0; i<6;++i)
+// // 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_lowerLimit[i] = btScalar(0.0);
- m_upperLimit[i] = btScalar(0.0);
- m_accumulatedImpulse[i] = btScalar(0.0);
+ 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;
+ };
+ m_currentLimit = 0;//Free from violation
+ return 0;
+
}
-void btGeneric6DofConstraint::buildJacobian()
+btScalar btRotationalLimitMotor::solveAngularLimits(
+ btScalar timeStep,btVector3& axis,btScalar jacDiagABInv,
+ btRigidBody * body0, btRigidBody * body1)
{
- btVector3 localNormalInA(0,0,0);
+ if (needApplyTorques()==false) return 0.0f;
- const btVector3& pivotInA = m_frameInA.getOrigin();
- const btVector3& pivotInB = m_frameInB.getOrigin();
+ btScalar target_velocity = m_targetVelocity;
+ btScalar maxMotorForce = m_maxMotorForce;
- btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_frameInA.getOrigin();
- btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_frameInB.getOrigin();
+ //current error correction
+ if (m_currentLimit!=0)
+ {
+ target_velocity = -m_ERP*m_currentLimitError/(timeStep);
+ maxMotorForce = m_maxLimitForce;
+ }
- btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
- btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
+ maxMotorForce *= timeStep;
- 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;
- }
- }
+ // current velocity difference
+ btVector3 vel_diff = body0->getAngularVelocity();
+ if (body1)
+ {
+ vel_diff -= body1->getAngularVelocity();
+ }
- // 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());
+ btScalar rel_vel = axis.dot(vel_diff);
-#ifdef GENERIC_D6_DISABLE_WARMSTARTING
- m_accumulatedImpulse[i + 3] = btScalar(0.);
-#endif //GENERIC_D6_DISABLE_WARMSTARTING
+ // correction velocity
+ btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel);
- // Apply accumulated impulse
- btVector3 impulse_vector = m_accumulatedImpulse[i + 3] * axis;
- m_rbA.applyTorqueImpulse( impulse_vector);
- m_rbB.applyTorqueImpulse(-impulse_vector);
- }
- }
-}
+ 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;
+
-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)
+//////////////////////////// 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,
+ const btVector3 & anchorPos)
{
- // 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
+///find relative velocity
+// btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition();
+// btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition();
+ btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition();
+ btVector3 rel_pos2 = anchorPos - 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
- if (getMatrixElem(mat,2) < btScalar(1.0))
+//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 (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;
+ if (depth > maxLimit)
+ {
+ depth -= maxLimit;
+ lo = btScalar(0.);
+
+ }
+ else
+ {
+ if (depth < minLimit)
+ {
+ depth -= minLimit;
+ hi = btScalar(0.);
+ }
+ else
+ {
+ return 0.0f;
+ }
+ }
}
- 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;
+
+ 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::solveConstraint(btScalar timeStep)
+
+
+
+void btGeneric6DofConstraint::calculateAngleInfo()
{
- btScalar tau = btScalar(0.1);
- btScalar damping = btScalar(1.0);
+ 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);
+// }
- 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;
+void btGeneric6DofConstraint::calculateTransforms()
+{
+ m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA;
+ m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB;
- // 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;
- }
- }
- }
- }
+ calculateAngleInfo();
+}
- 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;
+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());
- 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);
+}
+
+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());
- // 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)
+bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index)
{
- (void)timeStep;
+ btScalar angle = m_calculatedAxisAngleDiff[axis_index];
+ //test limits
+ m_angularLimits[axis_index].testLimitValue(angle);
+ return m_angularLimits[axis_index].needApplyTorques();
}
-btScalar btGeneric6DofConstraint::computeAngle(int axis) const
- {
- btScalar angle = btScalar(0.f);
+void btGeneric6DofConstraint::buildJacobian()
+{
- 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);
+ // Clear accumulated impulses for the next simulation step
+ m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+ int i;
+ for(i = 0; i < 3; i++)
+ {
+ m_angularLimits[i].m_accumulatedImpulse = btScalar(0.);
+ }
+ //calculates transform
+ calculateTransforms();
+
+// const btVector3& pivotAInW = m_calculatedTransformA.getOrigin();
+// const btVector3& pivotBInW = m_calculatedTransformB.getOrigin();
+ calcAnchorPos();
+ btVector3 pivotAInW = m_AnchorPos;
+ btVector3 pivotBInW = m_AnchorPos;
+
+// not used here
+// btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
+// btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
+
+ btVector3 normalWorld;
+ //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);
- btScalar s = v1.dot(w2);
- btScalar c = v1.dot(v2);
+ buildLinearJacobian(
+ m_jacLinear[i],normalWorld ,
+ pivotAInW,pivotBInW);
- 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);
+ // 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);
+ }
+ }
- 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);
+void btGeneric6DofConstraint::solveConstraint(btScalar timeStep)
+{
+ m_timeStep = timeStep;
- angle = btAtan2( s, c );
- }
- break;
- default:
- btAssert ( 0 ) ;
-
- break ;
- }
+ //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, m_AnchorPos);
+
+ }
+ }
+
+ // 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];
+}
- return angle;
+btScalar btGeneric6DofConstraint::getAngle(int axis_index) const
+{
+ return m_calculatedAxisAngleDiff[axis_index];
+}
+
+void btGeneric6DofConstraint::calcAnchorPos(void)
+{
+ btScalar imA = m_rbA.getInvMass();
+ btScalar imB = m_rbB.getInvMass();
+ btScalar weight;
+ if(imB == btScalar(0.0))
+ {
+ weight = btScalar(1.0);
+ }
+ else
+ {
+ weight = imA / (imA + imB);
}
+ const btVector3& pA = m_calculatedTransformA.getOrigin();
+ const btVector3& pB = m_calculatedTransformB.getOrigin();
+ m_AnchorPos = pA * weight + pB * (btScalar(1.0) - weight);
+ return;
+} // btGeneric6DofConstraint::calcAnchorPos()
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
index b114e54fa69..f0718d2d4a0 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
@@ -4,116 +4,433 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this 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,
+ const btVector3 & anchorPos);
+
+
+};
/// 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<br>
+<ul>
+<li> 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. </li>
+
+<li> 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. </li>
+
+<li> Angulars limits have these possible ranges:
+<table border=1 >
+<tr
+
+ <td><b>AXIS</b></td>
+ <td><b>MIN ANGLE</b></td>
+ <td><b>MAX ANGLE</b></td>
+ <td>X</td>
+ <td>-PI</td>
+ <td>PI</td>
+ <td>Y</td>
+ <td>-PI/2</td>
+ <td>PI/2</td>
+ <td>Z</td>
+ <td>-PI/2</td>
+ <td>PI/2</td>
+</tr>
+</table>
+</li>
+</ul>
+
+*/
class btGeneric6DofConstraint : public btTypedConstraint
{
- btJacobianEntry m_jacLinear[3]; // 3 orthogonal linear constraints
- btJacobianEntry m_jacAng[3]; // 3 orthogonal angular constraints
+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
+ //!@}
- btTransform m_frameInA; // the constraint space w.r.t body A
- btTransform m_frameInB; // the constraint space w.r.t body B
+ //! 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];
+
+ btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes
+
+ 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();
-
-
- 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;
- }
-
+ 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;
+ }
+
+ virtual void calcAnchorPos(void); // overridable
};
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
index 27e30987549..114abce24c7 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
@@ -17,58 +17,185 @@ subject to the following restrictions:
#include "btHingeConstraint.h"
#include "BulletDynamics/Dynamics/btRigidBody.h"
#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btMinMax.h"
#include <new>
-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);
+
+ btVector3 rbAxisA2;
+ btScalar projection = axisInA.dot(rbAxisA1);
+ if (projection >= 1.0f - SIMD_EPSILON) {
+ rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2);
+ rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
+ } else if (projection <= -1.0f + SIMD_EPSILON) {
+ rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2);
+ rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
+ } else {
+ rbAxisA2 = axisInA.cross(rbAxisA1);
+ rbAxisA1 = rbAxisA2.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 = axisInB.cross(rbAxisB1);
+
+ 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 +206,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 +232,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 +304,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 +327,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 +343,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 +375,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 +395,12 @@ 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..4fa9972f6d8 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;
- bool m_angularOnly;
+ btScalar m_motorTargetVelocity;
+ btScalar m_maxMotorImpulse;
+
+ btScalar m_limitSoftness;
+ btScalar m_biasFactor;
+ btScalar m_relaxationFactor;
- btScalar m_motorTargetVelocity;
- btScalar m_maxMotorImpulse;
+ 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,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,61 @@ 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 getLowerLimit() const
+ {
+ return m_lowerLimit;
+ }
+
+ btScalar getUpperLimit() const
+ {
+ return m_upperLimit;
+ }
+
+
+ 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;
+ }
+
+ inline bool getAngularOnly()
+ {
+ return m_angularOnly;
+ }
+ inline bool getEnableAngularMotor()
+ {
+ return m_enableAngularMotor;
+ }
+ inline btScalar getMotorTargetVelosity()
+ {
+ return m_motorTargetVelocity;
+ }
+ inline btScalar getMaxMotorImpulse()
+ {
+ return m_maxMotorImpulse;
+ }
+
};
#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..2b69ad90438 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))
{
}
@@ -99,6 +100,16 @@ void btPoint2PointConstraint::solveConstraint(btScalar timeStep)
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;
+
+ btScalar impulseClamp = m_setting.m_impulseClamp;
+ if (impulseClamp > 0)
+ {
+ if (impulse < -impulseClamp)
+ impulse = -impulseClamp;
+ if (impulse > impulseClamp)
+ impulse = impulseClamp;
+ }
+
m_appliedImpulse+=impulse;
btVector3 impulse_vector = normal * impulse;
m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition());
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
index 71da8ac0347..c9d5968530c 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"
@@ -26,16 +26,21 @@ struct btConstraintSetting
{
btConstraintSetting() :
m_tau(btScalar(0.3)),
- m_damping(btScalar(1.))
+ m_damping(btScalar(1.)),
+ m_impulseClamp(btScalar(0.))
{
}
btScalar m_tau;
btScalar m_damping;
+ btScalar m_impulseClamp;
};
/// 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 +75,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..b8afbd6aac5 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"
@@ -30,11 +33,9 @@ subject to the following restrictions:
#include "btSolverBody.h"
#include "btSolverConstraint.h"
+
#include "LinearMath/btAlignedObjectArray.h"
-#ifdef USE_PROFILE
-#include "LinearMath/btQuickprof.h"
-#endif //USE_PROFILE
int totalCpd = 0;
@@ -64,7 +65,7 @@ unsigned long btSequentialImpulseConstraintSolver::btRand2()
int btSequentialImpulseConstraintSolver::btRandInt2 (int n)
{
// seems good; xor-fold and modulus
- const unsigned long un = n;
+ const unsigned long un = static_cast<unsigned long>(n);
unsigned long r = btRand2();
// note: probably more aggressive than it needs to be -- might be
@@ -91,12 +92,12 @@ int btSequentialImpulseConstraintSolver::btRandInt2 (int n)
-
+bool MyContactDestroyedCallback(void* userPersistentData);
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;
@@ -105,8 +106,7 @@ bool MyContactDestroyedCallback(void* userPersistentData)
btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
-:m_solverMode(SOLVER_RANDMIZE_ORDER | SOLVER_CACHE_FRIENDLY), //not using SOLVER_USE_WARMSTARTING,
-m_btSeed2(0)
+:m_btSeed2(0)
{
gContactDestroyedCallback = &MyContactDestroyedCallback;
@@ -121,27 +121,42 @@ m_btSeed2(0)
}
}
-
-void initSolverBody(btSolverBody* solverBody, btRigidBody* rigidbody)
+btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
{
-/* int size = sizeof(btSolverBody);
- int sizeofrb = sizeof(btRigidBody);
- int sizemanifold = sizeof(btPersistentManifold);
- int sizeofmp = sizeof(btManifoldPoint);
- int sizeofPersistData = sizeof (btConstraintPersistentData);
-*/
- solverBody->m_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);
+void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject);
+void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject)
+{
+ btRigidBody* rb = btRigidBody::upcast(collisionObject);
+ if (rb)
+ {
+ solverBody->m_angularVelocity = rb->getAngularVelocity() ;
+ solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin();
+ solverBody->m_friction = collisionObject->getFriction();
+ solverBody->m_invMass = rb->getInvMass();
+ solverBody->m_linearVelocity = rb->getLinearVelocity();
+ solverBody->m_originalBody = rb;
+ solverBody->m_angularFactor = rb->getAngularFactor();
+ } else
+ {
+ solverBody->m_angularVelocity.setValue(0,0,0);
+ solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin();
+ solverBody->m_friction = collisionObject->getFriction();
+ solverBody->m_invMass = 0.f;
+ solverBody->m_linearVelocity.setValue(0,0,0);
+ solverBody->m_originalBody = 0;
+ solverBody->m_angularFactor = 1.f;
+ }
+ solverBody->m_pushVelocity.setValue(0.f,0.f,0.f);
+ solverBody->m_turnVelocity.setValue(0.f,0.f,0.f);
+}
+
+
+int gNumSplitImpulseRecoveries = 0;
+
+btScalar restitutionCurve(btScalar rel_vel, btScalar restitution);
btScalar restitutionCurve(btScalar rel_vel, btScalar restitution)
{
btScalar rest = restitution * -rel_vel;
@@ -149,30 +164,95 @@ btScalar restitutionCurve(btScalar rel_vel, btScalar restitution)
}
+void resolveSplitPenetrationImpulseCacheFriendly(
+ btSolverBody& body1,
+ btSolverBody& body2,
+ const btSolverConstraint& contactConstraint,
+ const btContactSolverInfo& solverInfo);
+
+//SIMD_FORCE_INLINE
+void resolveSplitPenetrationImpulseCacheFriendly(
+ btSolverBody& body1,
+ btSolverBody& body2,
+ const btSolverConstraint& contactConstraint,
+ const btContactSolverInfo& solverInfo)
+{
+ (void)solverInfo;
+
+ if (contactConstraint.m_penetration < solverInfo.m_splitImpulsePenetrationThreshold)
+ {
+ gNumSplitImpulseRecoveries++;
+ 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_pushVelocity)
+ + contactConstraint.m_relpos1CrossNormal.dot(body1.m_turnVelocity);
+ btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_pushVelocity)
+ + contactConstraint.m_relpos2CrossNormal.dot(body2.m_turnVelocity);
+
+ rel_vel = vel1Dotn-vel2Dotn;
+
+
+ btScalar positionalError = -contactConstraint.m_penetration * solverInfo.m_erp2/solverInfo.m_timeStep;
+ // 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_appliedPushImpulse;
+ btScalar sum = oldNormalImpulse + normalImpulse;
+ contactConstraint.m_appliedPushImpulse = btScalar(0.) > sum ? btScalar(0.): sum;
+
+ normalImpulse = contactConstraint.m_appliedPushImpulse - oldNormalImpulse;
+
+ body1.internalApplyPushImpulse(contactConstraint.m_contactNormal*body1.m_invMass, contactConstraint.m_angularComponentA,normalImpulse);
+
+ body2.internalApplyPushImpulse(contactConstraint.m_contactNormal*body2.m_invMass, contactConstraint.m_angularComponentB,-normalImpulse);
+
+ }
+
+}
//velocity + friction
//response between two dynamic objects with friction
-SIMD_FORCE_INLINE btScalar resolveSingleCollisionCombinedCacheFriendly(
+
+btScalar resolveSingleCollisionCombinedCacheFriendly(
btSolverBody& body1,
btSolverBody& body2,
- btSolverConstraint& contactConstraint,
+ const btSolverConstraint& contactConstraint,
+ const btContactSolverInfo& solverInfo);
+
+//SIMD_FORCE_INLINE
+btScalar resolveSingleCollisionCombinedCacheFriendly(
+ btSolverBody& body1,
+ btSolverBody& body2,
+ const btSolverConstraint& contactConstraint,
const btContactSolverInfo& solverInfo)
{
(void)solverInfo;
- btScalar normalImpulse(0.f);
+ btScalar normalImpulse;
+
{
- 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);
+
+ // 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)
@@ -182,50 +262,51 @@ SIMD_FORCE_INLINE btScalar resolveSingleCollisionCombinedCacheFriendly(
rel_vel = vel1Dotn-vel2Dotn;
+ btScalar positionalError = 0.f;
+ if (!solverInfo.m_splitImpulse || (contactConstraint.m_penetration > solverInfo.m_splitImpulsePenetrationThreshold))
+ {
+ positionalError = -contactConstraint.m_penetration * solverInfo.m_erp/solverInfo.m_timeStep;
+ }
- 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;
+ 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,
+ body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass,
contactConstraint.m_angularComponentA,normalImpulse);
- }
- if (body2.m_invMass)
- {
- body2.internalApplyImpulse(contactConstraint.m_contactNormal*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(
+btScalar resolveSingleFrictionCacheFriendly(
btSolverBody& body1,
btSolverBody& body2,
- btSolverConstraint& contactConstraint,
+ const btSolverConstraint& contactConstraint,
+ const btContactSolverInfo& solverInfo,
+ btScalar appliedNormalImpulse);
+
+//SIMD_FORCE_INLINE
+btScalar resolveSingleFrictionCacheFriendly(
+ btSolverBody& body1,
+ btSolverBody& body2,
+ const btSolverConstraint& contactConstraint,
const btContactSolverInfo& solverInfo,
btScalar appliedNormalImpulse)
{
@@ -252,22 +333,42 @@ 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);
+
+
}
- 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);
- }
+ body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass,contactConstraint.m_angularComponentA,j1);
+
+ body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass,contactConstraint.m_angularComponentB,-j1);
}
return 0.f;
@@ -309,7 +410,6 @@ btScalar resolveSingleFrictionCacheFriendly(
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);
@@ -319,7 +419,7 @@ btScalar resolveSingleFrictionCacheFriendly(
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;
+ btScalar normal_impulse = contactConstraint.m_appliedImpulse * combinedFriction;
GEN_set_min(friction_impulse, normal_impulse);
GEN_set_max(friction_impulse, -normal_impulse);
@@ -333,39 +433,111 @@ btScalar resolveSingleFrictionCacheFriendly(
#endif //NO_FRICTION_TANGENTIALS
-btAlignedObjectArray<btSolverBody> tmpSolverBodyPool;
-btAlignedObjectArray<btSolverConstraint> tmpSolverConstraintPool;
-btAlignedObjectArray<btSolverConstraint> 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,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation)
+{
+
+ btRigidBody* body0=btRigidBody::upcast(colObj0);
+ btRigidBody* body1=btRigidBody::upcast(colObj1);
+
+ 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_originalContactPoint = 0;
+
+ solverConstraint.m_appliedImpulse = btScalar(0.);
+ solverConstraint.m_appliedPushImpulse = 0.f;
+ solverConstraint.m_penetration = 0.f;
+ {
+ btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal);
+ solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0);
+ }
+ {
+ btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal);
+ solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
+ solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0);
+ }
+
+#ifdef COMPUTE_IMPULSE_DENOM
+ btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal);
+ btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal);
+#else
+ btVector3 vec;
+ btScalar denom0 = 0.f;
+ btScalar denom1 = 0.f;
+ if (body0)
+ {
+ vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ denom0 = body0->getInvMass() + normalAxis.dot(vec);
+ }
+ if (body1)
+ {
+ vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2);
+ denom1 = body1->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)
{
+ BT_PROFILE("solveGroupCacheFriendlySetup");
(void)stackAlloc;
(void)debugDrawer;
+
if (!(numConstraints + numManifolds))
{
// printf("empty\n");
return 0.f;
}
+ btPersistentManifold* manifold = 0;
+ btCollisionObject* colObj0=0,*colObj1=0;
+
+ //btRigidBody* rb0=0,*rb1=0;
+
+
+#ifdef FORCE_REFESH_CONTACT_MANIFOLDS
BEGIN_PROFILE("refreshManifolds");
int i;
+
+
+
for (i=0;i<numManifolds;i++)
{
- btPersistentManifold* manifold = manifoldPtr[i];
- btRigidBody* rb0 = (btRigidBody*)manifold->getBody0();
- 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
+
+
- BEGIN_PROFILE("gatherSolverData");
//int sizeofSB = sizeof(btSolverBody);
//int sizeofSC = sizeof(btSolverConstraint);
@@ -382,10 +554,12 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio
//todo: use stack allocator for this temp memory
- int minReservation = numManifolds*2;
+// 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;i<numBodies;i++)
{
@@ -393,26 +567,26 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio
if (rb && (rb->getIslandTag() >= 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;i<numManifolds;i++)
{
- btPersistentManifold* manifold = manifoldPtr[i];
- btRigidBody* rb0 = (btRigidBody*)manifold->getBody0();
- btRigidBody* rb1 = (btRigidBody*)manifold->getBody1();
-
+ manifold = manifoldPtr[i];
+ colObj0 = (btCollisionObject*)manifold->getBody0();
+ colObj1 = (btCollisionObject*)manifold->getBody1();
int solverBodyIdA=-1;
int solverBodyIdB=-1;
@@ -422,61 +596,108 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio
- if (rb0->getIslandTag() >= 0)
+ if (colObj0->getIslandTag() >= 0)
{
- solverBodyIdA = rb0->getCompanionId();
+ if (colObj0->getCompanionId() >= 0)
+ {
+ //body has already been converted
+ solverBodyIdA = colObj0->getCompanionId();
+ } else
+ {
+ solverBodyIdA = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&solverBody,colObj0);
+ colObj0->setCompanionId(solverBodyIdA);
+ }
} else
{
//create a static body
- solverBodyIdA = tmpSolverBodyPool.size();
- btSolverBody& solverBody = tmpSolverBodyPool.expand();
- initSolverBody(&solverBody,rb0);
+ solverBodyIdA = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&solverBody,colObj0);
}
- if (rb1->getIslandTag() >= 0)
+ if (colObj1->getIslandTag() >= 0)
{
- solverBodyIdB = rb1->getCompanionId();
+ if (colObj1->getCompanionId() >= 0)
+ {
+ solverBodyIdB = colObj1->getCompanionId();
+ } else
+ {
+ solverBodyIdB = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&solverBody,colObj1);
+ colObj1->setCompanionId(solverBodyIdB);
+ }
} else
{
//create a static body
- solverBodyIdB = tmpSolverBodyPool.size();
- btSolverBody& solverBody = tmpSolverBodyPool.expand();
- initSolverBody(&solverBody,rb1);
+ solverBodyIdB = m_tmpSolverBodyPool.size();
+ btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+ initSolverBody(&solverBody,colObj1);
}
}
+ btVector3 rel_pos1;
+ btVector3 rel_pos2;
+ btScalar relaxation;
+
for (int j=0;j<manifold->getNumContacts();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();
+ rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
+ rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
- 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();
+ btRigidBody* rb0 = btRigidBody::upcast(colObj0);
+ btRigidBody* rb1 = btRigidBody::upcast(colObj1);
solverConstraint.m_solverBodyIdA = solverBodyIdA;
solverConstraint.m_solverBodyIdB = solverBodyIdB;
solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_CONTACT_1D;
-
+ solverConstraint.m_originalContactPoint = &cp;
+ btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
+ solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0 : btVector3(0,0,0);
+ btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
+ solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*torqueAxis1 : btVector3(0,0,0);
{
- //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;
+ btScalar denom0 = 0.f;
+ btScalar denom1 = 0.f;
+ if (rb0)
+ {
+ vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+ denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
+ }
+ if (rb1)
+ {
+ vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2);
+ denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
+ }
+#endif //COMPUTE_IMPULSE_DENOM
+
btScalar denom = relaxation/(denom0+denom1);
solverConstraint.m_jacDiagABInv = denom;
}
@@ -486,121 +707,115 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio
solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(cp.m_normalWorldOnB);
- btVector3 vel1 = rb0->getVelocityInLocalPoint(rel_pos1);
- btVector3 vel2 = rb1->getVelocityInLocalPoint(rel_pos2);
+ btVector3 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0);
+ btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
- btVector3 vel = vel1 - vel2;
- btScalar rel_vel;
+ vel = vel1 - vel2;
+
rel_vel = cp.m_normalWorldOnB.dot(vel);
+ solverConstraint.m_penetration = btMin(cp.getDistance()+infoGlobal.m_linearSlop,btScalar(0.));
+ //solverConstraint.m_penetration = cp.getDistance();
- 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);
- 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;
+ if (solverConstraint.m_restitution > penVel)
{
- btVector3 ftorqueAxis0 = rel_pos1.cross(solverConstraint.m_contactNormal);
- solverConstraint.m_relpos1CrossNormal = ftorqueAxis0;
- solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis0;
+ solverConstraint.m_penetration = btScalar(0.);
}
+
+
+
+ ///warm starting (or zero if disabled)
+ if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+ {
+ solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
+ if (rb0)
+ m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
+ if (rb1)
+ m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass(),solverConstraint.m_angularComponentB,-solverConstraint.m_appliedImpulse);
+ } else
{
- btVector3 ftorqueAxis0 = rel_pos2.cross(solverConstraint.m_contactNormal);
- solverConstraint.m_relpos2CrossNormal = ftorqueAxis0;
- solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis0;
+ solverConstraint.m_appliedImpulse = 0.f;
}
- }
-
-
- {
-
- 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_appliedPushImpulse = 0.f;
+
+ solverConstraint.m_frictionIndex = m_tmpSolverFrictionConstraintPool.size();
+ if (!cp.m_lateralFrictionInitialized)
+ {
+ cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
+ btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
+ if (lat_rel_vel > SIMD_EPSILON)//0.0f)
+ {
+ cp.m_lateralFrictionDir1 /= btSqrt(lat_rel_vel);
+ addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
+ cp.m_lateralFrictionDir2.normalize();//??
+ addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ } else
+ {
+ //re-calculate friction direction every frame, todo: check if this is really needed
+
+ btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2);
+ addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ }
+ cp.m_lateralFrictionInitialized = true;
+
+ } else
+ {
+ addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+ }
- 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;
+ btSolverConstraint& frictionConstraint1 = m_tmpSolverFrictionConstraintPool[solverConstraint.m_frictionIndex];
+ if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+ {
+ frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
+ if (rb0)
+ m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse);
+ if (rb1)
+ m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass(),frictionConstraint1.m_angularComponentB,-frictionConstraint1.m_appliedImpulse);
+ } else
+ {
+ frictionConstraint1.m_appliedImpulse = 0.f;
}
+ }
{
- btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal);
- solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis1;
+ btSolverConstraint& frictionConstraint2 = m_tmpSolverFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
+ if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+ {
+ frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
+ if (rb0)
+ m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(frictionConstraint2.m_contactNormal*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse);
+ if (rb1)
+ m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(frictionConstraint2.m_contactNormal*rb1->getInvMass(),frictionConstraint2.m_angularComponentB,-frictionConstraint2.m_appliedImpulse);
+ } else
+ {
+ frictionConstraint2.m_appliedImpulse = 0.f;
}
}
+ }
+
}
}
}
}
}
- END_PROFILE("gatherSolverData");
-
- BEGIN_PROFILE("prepareConstraints");
-
+
btContactSolverInfo info = infoGlobal;
{
@@ -612,57 +827,60 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio
}
}
- btAlignedObjectArray<int> gOrderTmpConstraintPool;
- btAlignedObjectArray<int> 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;i<numConstraintPool;i++)
{
- gOrderTmpConstraintPool[i] = i;
+ m_orderTmpConstraintPool[i] = i;
}
for (i=0;i<numFrictionPool;i++)
{
- gOrderFrictionConstraintPool[i] = i;
+ m_orderFrictionConstraintPool[i] = i;
}
}
+ return 0.f;
- END_PROFILE("prepareConstraints");
-
+}
- BEGIN_PROFILE("solveConstraints");
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/,btStackAlloc* /*stackAlloc*/)
+{
+ BT_PROFILE("solveGroupCacheFriendlyIterations");
+ int numConstraintPool = m_tmpSolverConstraintPool.size();
+ int numFrictionPool = m_tmpSolverFrictionConstraintPool.size();
//should traverse the contacts random order...
int iteration;
{
- for ( iteration = 0;iteration<info.m_numIterations;iteration++)
+ for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
{
int j;
- if (m_solverMode & SOLVER_RANDMIZE_ORDER)
+ if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
{
if ((iteration & 7) == 0) {
for (j=0; j<numConstraintPool; ++j) {
- int tmp = gOrderTmpConstraintPool[j];
+ int tmp = m_orderTmpConstraintPool[j];
int swapi = btRandInt2(j+1);
- gOrderTmpConstraintPool[j] = gOrderTmpConstraintPool[swapi];
- gOrderTmpConstraintPool[swapi] = tmp;
+ m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
+ m_orderTmpConstraintPool[swapi] = tmp;
}
for (j=0; j<numFrictionPool; ++j) {
- int tmp = gOrderFrictionConstraintPool[j];
+ int tmp = m_orderFrictionConstraintPool[j];
int swapi = btRandInt2(j+1);
- gOrderFrictionConstraintPool[j] = gOrderFrictionConstraintPool[swapi];
- gOrderFrictionConstraintPool[swapi] = tmp;
+ m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
+ m_orderFrictionConstraintPool[swapi] = tmp;
}
}
}
@@ -674,86 +892,145 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio
if ((constraint->getRigidBodyA().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;j<numPoolConstraints;j++)
{
- btSolverConstraint& solveManifold = tmpSolverConstraintPool[gOrderTmpConstraintPool[j]];
- resolveSingleCollisionCombinedCacheFriendly(tmpSolverBodyPool[solveManifold.m_solverBodyIdA],
- tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold,info);
+
+ const btSolverConstraint& solveManifold = m_tmpSolverConstraintPool[m_orderTmpConstraintPool[j]];
+ resolveSingleCollisionCombinedCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],
+ m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold,infoGlobal);
}
}
{
- int numFrictionPoolConstraints = tmpSolverFrictionConstraintPool.size();
- for (j=0;j<numFrictionPoolConstraints;j++)
+ int numFrictionPoolConstraints = m_tmpSolverFrictionConstraintPool.size();
+
+ for (j=0;j<numFrictionPoolConstraints;j++)
{
- btSolverConstraint& solveManifold = tmpSolverFrictionConstraintPool[gOrderFrictionConstraintPool[j]];
- btScalar appliedNormalImpulse = tmpSolverConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ const btSolverConstraint& solveManifold = m_tmpSolverFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+ btScalar totalImpulse = m_tmpSolverConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse+
+ m_tmpSolverConstraintPool[solveManifold.m_frictionIndex].m_appliedPushImpulse;
- resolveSingleFrictionCacheFriendly(tmpSolverBodyPool[solveManifold.m_solverBodyIdA],
- tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold,info,appliedNormalImpulse);
+ resolveSingleFrictionCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],
+ m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold,infoGlobal,
+ totalImpulse);
}
}
}
+
+ if (infoGlobal.m_splitImpulse)
+ {
+
+ for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
+ {
+ {
+ int numPoolConstraints = m_tmpSolverConstraintPool.size();
+ int j;
+ for (j=0;j<numPoolConstraints;j++)
+ {
+ const btSolverConstraint& solveManifold = m_tmpSolverConstraintPool[m_orderTmpConstraintPool[j]];
+
+ resolveSplitPenetrationImpulseCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA],
+ m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB],solveManifold,infoGlobal);
+ }
+ }
+ }
+
+ }
+
}
-
- for ( i=0;i<tmpSolverBodyPool.size();i++)
+
+ return 0.f;
+}
+
+
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
+{
+ int i;
+
+ solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
+ solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
+
+ int numPoolConstraints = m_tmpSolverConstraintPool.size();
+ int j;
+ for (j=0;j<numPoolConstraints;j++)
{
- tmpSolverBodyPool[i].writebackVelocity();
+
+ const btSolverConstraint& solveManifold = m_tmpSolverConstraintPool[j];
+ btManifoldPoint* pt = (btManifoldPoint*) solveManifold.m_originalContactPoint;
+ btAssert(pt);
+ pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
+ pt->m_appliedImpulseLateral1 = m_tmpSolverFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+ pt->m_appliedImpulseLateral1 = m_tmpSolverFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse;
+
+ //do a callback here?
+
}
- END_PROFILE("solveConstraints");
+ if (infoGlobal.m_splitImpulse)
+ {
+ for ( i=0;i<m_tmpSolverBodyPool.size();i++)
+ {
+ m_tmpSolverBodyPool[i].writebackVelocity(infoGlobal.m_timeStep);
+ }
+ } else
+ {
+ for ( i=0;i<m_tmpSolverBodyPool.size();i++)
+ {
+ m_tmpSolverBodyPool[i].writebackVelocity();
+ }
+ }
-// printf("tmpSolverConstraintPool.size() = %i\n",tmpSolverConstraintPool.size());
+// printf("m_tmpSolverConstraintPool.size() = %i\n",m_tmpSolverConstraintPool.size());
/*
- printf("tmpSolverBodyPool.size() = %i\n",tmpSolverBodyPool.size());
- printf("tmpSolverConstraintPool.size() = %i\n",tmpSolverConstraintPool.size());
- printf("tmpSolverFrictionConstraintPool.size() = %i\n",tmpSolverFrictionConstraintPool.size());
+ printf("m_tmpSolverBodyPool.size() = %i\n",m_tmpSolverBodyPool.size());
+ printf("m_tmpSolverConstraintPool.size() = %i\n",m_tmpSolverConstraintPool.size());
+ printf("m_tmpSolverFrictionConstraintPool.size() = %i\n",m_tmpSolverFrictionConstraintPool.size());
- printf("tmpSolverBodyPool.capacity() = %i\n",tmpSolverBodyPool.capacity());
- printf("tmpSolverConstraintPool.capacity() = %i\n",tmpSolverConstraintPool.capacity());
- printf("tmpSolverFrictionConstraintPool.capacity() = %i\n",tmpSolverFrictionConstraintPool.capacity());
+ printf("m_tmpSolverBodyPool.capacity() = %i\n",m_tmpSolverBodyPool.capacity());
+ printf("m_tmpSolverConstraintPool.capacity() = %i\n",m_tmpSolverConstraintPool.capacity());
+ printf("m_tmpSolverFrictionConstraintPool.capacity() = %i\n",m_tmpSolverFrictionConstraintPool.capacity());
*/
- tmpSolverBodyPool.resize(0);
- tmpSolverConstraintPool.resize(0);
- tmpSolverFrictionConstraintPool.resize(0);
+ m_tmpSolverBodyPool.resize(0);
+ m_tmpSolverConstraintPool.resize(0);
+ m_tmpSolverFrictionConstraintPool.resize(0);
return 0.f;
}
/// btSequentialImpulseConstraintSolver Sequentially applies impulses
-btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
+btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* /*dispatcher*/)
{
-
- if (getSolverMode() & SOLVER_CACHE_FRIENDLY)
+ BT_PROFILE("solveGroup");
+ if (infoGlobal.m_solverMode & SOLVER_CACHE_FRIENDLY)
{
//you need to provide at least some bodies
//btSimpleDynamicsWorld needs to switch off SOLVER_CACHE_FRIENDLY
@@ -762,16 +1039,11 @@ btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bod
return solveGroupCacheFriendly(bodies,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer,stackAlloc);
}
-
- BEGIN_PROFILE("prepareConstraints");
btContactSolverInfo info = infoGlobal;
int numiter = infoGlobal.m_numIterations;
-#ifdef USE_PROFILE
- btProfiler::beginBlock("solve");
-#endif //USE_PROFILE
int totalPoints = 0;
@@ -801,10 +1073,6 @@ btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bod
}
}
- END_PROFILE("prepareConstraints");
-
-
- BEGIN_PROFILE("solveConstraints");
//should traverse the contacts random order...
int iteration;
@@ -813,7 +1081,7 @@ btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bod
for ( iteration = 0;iteration<numiter;iteration++)
{
int j;
- if (m_solverMode & SOLVER_RANDMIZE_ORDER)
+ if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
{
if ((iteration & 7) == 0) {
for (j=0; j<totalPoints; ++j) {
@@ -845,16 +1113,10 @@ btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bod
solveFriction((btRigidBody*)manifold->getBody0(),
(btRigidBody*)manifold->getBody1(),manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer);
}
+
}
}
- END_PROFILE("solveConstraints");
-
-
-#ifdef USE_PROFILE
- btProfiler::endBlock("solve");
-#endif //USE_PROFILE
-
@@ -878,13 +1140,14 @@ 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;
- btVector3 color(0,1,0);
+
for (int i=0;i<numpoints ;i++)
{
btManifoldPoint& cp = manifoldPtr->getContactPoint(i);
@@ -925,7 +1188,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,10 +1237,9 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol
cpd->m_penetration = btScalar(0.);
}
-
btScalar relaxation = info.m_damping;
- if (m_solverMode & SOLVER_USE_WARMSTARTING)
+ if (info.m_solverMode & SOLVER_USE_WARMSTARTING)
{
cpd->m_appliedImpulse *= relaxation;
} else
@@ -1060,16 +1324,12 @@ btScalar btSequentialImpulseConstraintSolver::solveCombinedContactFriction(btRig
{
- 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);
- }
+
{
@@ -1098,16 +1358,12 @@ btScalar btSequentialImpulseConstraintSolver::solve(btRigidBody* body0,btRigidBo
{
- 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);
- }
+
{
@@ -1136,7 +1392,7 @@ btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,b
{
- btVector3 color(0,1,0);
+
{
if (cp.getDistance() <= btScalar(0.))
@@ -1156,3 +1412,11 @@ 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..7143bc41991 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,29 +30,29 @@ class btIDebugDraw;
class btSequentialImpulseConstraintSolver : public btConstraintSolver
{
+ btAlignedObjectArray<btSolverBody> m_tmpSolverBodyPool;
+ btAlignedObjectArray<btSolverConstraint> m_tmpSolverConstraintPool;
+ btAlignedObjectArray<btSolverConstraint> m_tmpSolverFrictionConstraintPool;
+ btAlignedObjectArray<int> m_orderTmpConstraintPool;
+ btAlignedObjectArray<int> 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,btCollisionObject* colObj0,btCollisionObject* colObj1, 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
@@ -68,25 +69,22 @@ 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);
- btScalar solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer);
+ ///clear internal cached data and reset random seed
+ virtual void reset();
- void setSolverMode(int mode)
- {
- m_solverMode = mode;
- }
+ btScalar solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer);
- int getSolverMode() const
- {
- return m_solverMode;
- }
+
unsigned long btRand2();
int btRandInt2 (int n);
@@ -102,7 +100,9 @@ public:
};
-
+#ifndef BT_PREFER_SIMD
+typedef btSequentialImpulseConstraintSolver btSequentialImpulseConstraintSolverPrefered;
+#endif
#endif //SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
new file mode 100644
index 00000000000..e7f07a428eb
--- /dev/null
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
@@ -0,0 +1,414 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+Added by Roman Ponomarev (rponom@gmail.com)
+April 04, 2008
+*/
+
+//-----------------------------------------------------------------------------
+
+#include "btSliderConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include <new>
+
+//-----------------------------------------------------------------------------
+
+void btSliderConstraint::initParams()
+{
+ m_lowerLinLimit = btScalar(1.0);
+ m_upperLinLimit = btScalar(-1.0);
+ m_lowerAngLimit = btScalar(0.);
+ m_upperAngLimit = btScalar(0.);
+ m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingDirLin = btScalar(0.);
+ m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingDirAng = btScalar(0.);
+ m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING;
+ m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING;
+ m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING;
+ m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+ m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+ m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING;
+
+ m_poweredLinMotor = false;
+ m_targetLinMotorVelocity = btScalar(0.);
+ m_maxLinMotorForce = btScalar(0.);
+ m_accumulatedLinMotorImpulse = btScalar(0.0);
+
+ m_poweredAngMotor = false;
+ m_targetAngMotorVelocity = btScalar(0.);
+ m_maxAngMotorForce = btScalar(0.);
+ m_accumulatedAngMotorImpulse = btScalar(0.0);
+
+} // btSliderConstraint::initParams()
+
+//-----------------------------------------------------------------------------
+
+btSliderConstraint::btSliderConstraint()
+ :btTypedConstraint(SLIDER_CONSTRAINT_TYPE),
+ m_useLinearReferenceFrameA(true)
+{
+ initParams();
+} // btSliderConstraint::btSliderConstraint()
+
+//-----------------------------------------------------------------------------
+
+btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
+ : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB)
+ , m_frameInA(frameInA)
+ , m_frameInB(frameInB),
+ m_useLinearReferenceFrameA(useLinearReferenceFrameA)
+{
+ initParams();
+} // btSliderConstraint::btSliderConstraint()
+
+//-----------------------------------------------------------------------------
+
+void btSliderConstraint::buildJacobian()
+{
+ if(m_useLinearReferenceFrameA)
+ {
+ buildJacobianInt(m_rbA, m_rbB, m_frameInA, m_frameInB);
+ }
+ else
+ {
+ buildJacobianInt(m_rbB, m_rbA, m_frameInB, m_frameInA);
+ }
+} // btSliderConstraint::buildJacobian()
+
+//-----------------------------------------------------------------------------
+
+void btSliderConstraint::buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB)
+{
+ //calculate transforms
+ m_calculatedTransformA = rbA.getCenterOfMassTransform() * frameInA;
+ m_calculatedTransformB = rbB.getCenterOfMassTransform() * frameInB;
+ m_realPivotAInW = m_calculatedTransformA.getOrigin();
+ m_realPivotBInW = m_calculatedTransformB.getOrigin();
+ m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
+ m_delta = m_realPivotBInW - m_realPivotAInW;
+ m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
+ m_relPosA = m_projPivotInW - rbA.getCenterOfMassPosition();
+ m_relPosB = m_realPivotBInW - rbB.getCenterOfMassPosition();
+ btVector3 normalWorld;
+ int i;
+ //linear part
+ for(i = 0; i < 3; i++)
+ {
+ normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
+ new (&m_jacLin[i]) btJacobianEntry(
+ rbA.getCenterOfMassTransform().getBasis().transpose(),
+ rbB.getCenterOfMassTransform().getBasis().transpose(),
+ m_relPosA,
+ m_relPosB,
+ normalWorld,
+ rbA.getInvInertiaDiagLocal(),
+ rbA.getInvMass(),
+ rbB.getInvInertiaDiagLocal(),
+ rbB.getInvMass()
+ );
+ m_jacLinDiagABInv[i] = btScalar(1.) / m_jacLin[i].getDiagonal();
+ m_depth[i] = m_delta.dot(normalWorld);
+ }
+ testLinLimits();
+ // angular part
+ for(i = 0; i < 3; i++)
+ {
+ normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
+ new (&m_jacAng[i]) btJacobianEntry(
+ normalWorld,
+ rbA.getCenterOfMassTransform().getBasis().transpose(),
+ rbB.getCenterOfMassTransform().getBasis().transpose(),
+ rbA.getInvInertiaDiagLocal(),
+ rbB.getInvInertiaDiagLocal()
+ );
+ }
+ testAngLimits();
+ btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0);
+ m_kAngle = btScalar(1.0 )/ (rbA.computeAngularImpulseDenominator(axisA) + rbB.computeAngularImpulseDenominator(axisA));
+ // clear accumulator for motors
+ m_accumulatedLinMotorImpulse = btScalar(0.0);
+ m_accumulatedAngMotorImpulse = btScalar(0.0);
+} // btSliderConstraint::buildJacobianInt()
+
+//-----------------------------------------------------------------------------
+
+void btSliderConstraint::solveConstraint(btScalar timeStep)
+{
+ m_timeStep = timeStep;
+ if(m_useLinearReferenceFrameA)
+ {
+ solveConstraintInt(m_rbA, m_rbB);
+ }
+ else
+ {
+ solveConstraintInt(m_rbB, m_rbA);
+ }
+} // btSliderConstraint::solveConstraint()
+
+//-----------------------------------------------------------------------------
+
+void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB)
+{
+ int i;
+ // linear
+ btVector3 velA = rbA.getVelocityInLocalPoint(m_relPosA);
+ btVector3 velB = rbB.getVelocityInLocalPoint(m_relPosB);
+ btVector3 vel = velA - velB;
+ for(i = 0; i < 3; i++)
+ {
+ const btVector3& normal = m_jacLin[i].m_linearJointAxis;
+ btScalar rel_vel = normal.dot(vel);
+ // calculate positional error
+ btScalar depth = m_depth[i];
+ // get parameters
+ btScalar softness = (i) ? m_softnessOrthoLin : (m_solveLinLim ? m_softnessLimLin : m_softnessDirLin);
+ btScalar restitution = (i) ? m_restitutionOrthoLin : (m_solveLinLim ? m_restitutionLimLin : m_restitutionDirLin);
+ btScalar damping = (i) ? m_dampingOrthoLin : (m_solveLinLim ? m_dampingLimLin : m_dampingDirLin);
+ // calcutate and apply impulse
+ btScalar normalImpulse = softness * (restitution * depth / m_timeStep - damping * rel_vel) * m_jacLinDiagABInv[i];
+ btVector3 impulse_vector = normal * normalImpulse;
+ rbA.applyImpulse( impulse_vector, m_relPosA);
+ rbB.applyImpulse(-impulse_vector, m_relPosB);
+ if(m_poweredLinMotor && (!i))
+ { // apply linear motor
+ if(m_accumulatedLinMotorImpulse < m_maxLinMotorForce)
+ {
+ btScalar desiredMotorVel = m_targetLinMotorVelocity;
+ btScalar motor_relvel = desiredMotorVel + rel_vel;
+ normalImpulse = -motor_relvel * m_jacLinDiagABInv[i];
+ // clamp accumulated impulse
+ btScalar new_acc = m_accumulatedLinMotorImpulse + btFabs(normalImpulse);
+ if(new_acc > m_maxLinMotorForce)
+ {
+ new_acc = m_maxLinMotorForce;
+ }
+ btScalar del = new_acc - m_accumulatedLinMotorImpulse;
+ if(normalImpulse < btScalar(0.0))
+ {
+ normalImpulse = -del;
+ }
+ else
+ {
+ normalImpulse = del;
+ }
+ m_accumulatedLinMotorImpulse = new_acc;
+ // apply clamped impulse
+ impulse_vector = normal * normalImpulse;
+ rbA.applyImpulse( impulse_vector, m_relPosA);
+ rbB.applyImpulse(-impulse_vector, m_relPosB);
+ }
+ }
+ }
+ // angular
+ // get axes in world space
+ btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0);
+ btVector3 axisB = m_calculatedTransformB.getBasis().getColumn(0);
+
+ const btVector3& angVelA = rbA.getAngularVelocity();
+ const btVector3& angVelB = rbB.getAngularVelocity();
+
+ btVector3 angVelAroundAxisA = axisA * axisA.dot(angVelA);
+ btVector3 angVelAroundAxisB = axisB * axisB.dot(angVelB);
+
+ btVector3 angAorthog = angVelA - angVelAroundAxisA;
+ btVector3 angBorthog = angVelB - angVelAroundAxisB;
+ btVector3 velrelOrthog = angAorthog-angBorthog;
+ //solve orthogonal angular velocity correction
+ btScalar len = velrelOrthog.length();
+ if (len > btScalar(0.00001))
+ {
+ btVector3 normal = velrelOrthog.normalized();
+ btScalar denom = rbA.computeAngularImpulseDenominator(normal) + rbB.computeAngularImpulseDenominator(normal);
+ velrelOrthog *= (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng;
+ }
+ //solve angular positional correction
+ btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/m_timeStep);
+ btScalar len2 = angularError.length();
+ if (len2>btScalar(0.00001))
+ {
+ btVector3 normal2 = angularError.normalized();
+ btScalar denom2 = rbA.computeAngularImpulseDenominator(normal2) + rbB.computeAngularImpulseDenominator(normal2);
+ angularError *= (btScalar(1.)/denom2) * m_restitutionOrthoAng * m_softnessOrthoAng;
+ }
+ // apply impulse
+ rbA.applyTorqueImpulse(-velrelOrthog+angularError);
+ rbB.applyTorqueImpulse(velrelOrthog-angularError);
+ btScalar impulseMag;
+ //solve angular limits
+ if(m_solveAngLim)
+ {
+ impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingLimAng + m_angDepth * m_restitutionLimAng / m_timeStep;
+ impulseMag *= m_kAngle * m_softnessLimAng;
+ }
+ else
+ {
+ impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingDirAng + m_angDepth * m_restitutionDirAng / m_timeStep;
+ impulseMag *= m_kAngle * m_softnessDirAng;
+ }
+ btVector3 impulse = axisA * impulseMag;
+ rbA.applyTorqueImpulse(impulse);
+ rbB.applyTorqueImpulse(-impulse);
+ //apply angular motor
+ if(m_poweredAngMotor)
+ {
+ if(m_accumulatedAngMotorImpulse < m_maxAngMotorForce)
+ {
+ btVector3 velrel = angVelAroundAxisA - angVelAroundAxisB;
+ btScalar projRelVel = velrel.dot(axisA);
+
+ btScalar desiredMotorVel = m_targetAngMotorVelocity;
+ btScalar motor_relvel = desiredMotorVel - projRelVel;
+
+ btScalar angImpulse = m_kAngle * motor_relvel;
+ // clamp accumulated impulse
+ btScalar new_acc = m_accumulatedAngMotorImpulse + btFabs(angImpulse);
+ if(new_acc > m_maxAngMotorForce)
+ {
+ new_acc = m_maxAngMotorForce;
+ }
+ btScalar del = new_acc - m_accumulatedAngMotorImpulse;
+ if(angImpulse < btScalar(0.0))
+ {
+ angImpulse = -del;
+ }
+ else
+ {
+ angImpulse = del;
+ }
+ m_accumulatedAngMotorImpulse = new_acc;
+ // apply clamped impulse
+ btVector3 motorImp = angImpulse * axisA;
+ m_rbA.applyTorqueImpulse(motorImp);
+ m_rbB.applyTorqueImpulse(-motorImp);
+ }
+ }
+} // btSliderConstraint::solveConstraint()
+
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+
+void btSliderConstraint::calculateTransforms(void){
+ if(m_useLinearReferenceFrameA)
+ {
+ m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA;
+ m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB;
+ }
+ else
+ {
+ m_calculatedTransformA = m_rbB.getCenterOfMassTransform() * m_frameInB;
+ m_calculatedTransformB = m_rbA.getCenterOfMassTransform() * m_frameInA;
+ }
+ m_realPivotAInW = m_calculatedTransformA.getOrigin();
+ m_realPivotBInW = m_calculatedTransformB.getOrigin();
+ m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
+ m_delta = m_realPivotBInW - m_realPivotAInW;
+ m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
+ btVector3 normalWorld;
+ int i;
+ //linear part
+ for(i = 0; i < 3; i++)
+ {
+ normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
+ m_depth[i] = m_delta.dot(normalWorld);
+ }
+} // btSliderConstraint::calculateTransforms()
+
+//-----------------------------------------------------------------------------
+
+void btSliderConstraint::testLinLimits(void)
+{
+ m_solveLinLim = false;
+ if(m_lowerLinLimit <= m_upperLinLimit)
+ {
+ if(m_depth[0] > m_upperLinLimit)
+ {
+ m_depth[0] -= m_upperLinLimit;
+ m_solveLinLim = true;
+ }
+ else if(m_depth[0] < m_lowerLinLimit)
+ {
+ m_depth[0] -= m_lowerLinLimit;
+ m_solveLinLim = true;
+ }
+ else
+ {
+ m_depth[0] = btScalar(0.);
+ }
+ }
+ else
+ {
+ m_depth[0] = btScalar(0.);
+ }
+} // btSliderConstraint::testLinLimits()
+
+//-----------------------------------------------------------------------------
+
+
+void btSliderConstraint::testAngLimits(void)
+{
+ m_angDepth = btScalar(0.);
+ m_solveAngLim = false;
+ if(m_lowerAngLimit <= m_upperAngLimit)
+ {
+ const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1);
+ const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2);
+ const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1);
+ btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
+ if(rot < m_lowerAngLimit)
+ {
+ m_angDepth = rot - m_lowerAngLimit;
+ m_solveAngLim = true;
+ }
+ else if(rot > m_upperAngLimit)
+ {
+ m_angDepth = rot - m_upperAngLimit;
+ m_solveAngLim = true;
+ }
+ }
+} // btSliderConstraint::testAngLimits()
+
+
+//-----------------------------------------------------------------------------
+
+
+
+btVector3 btSliderConstraint::getAncorInA(void)
+{
+ btVector3 ancorInA;
+ ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis;
+ ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA;
+ return ancorInA;
+} // btSliderConstraint::getAncorInA()
+
+//-----------------------------------------------------------------------------
+
+btVector3 btSliderConstraint::getAncorInB(void)
+{
+ btVector3 ancorInB;
+ ancorInB = m_frameInB.getOrigin();
+ return ancorInB;
+} // btSliderConstraint::getAncorInB();
diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
new file mode 100644
index 00000000000..f69dfcf3aa7
--- /dev/null
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h
@@ -0,0 +1,215 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+Added by Roman Ponomarev (rponom@gmail.com)
+April 04, 2008
+
+TODO:
+ - add clamping od accumulated impulse to improve stability
+ - add conversion for ODE constraint solver
+*/
+
+#ifndef SLIDER_CONSTRAINT_H
+#define SLIDER_CONSTRAINT_H
+
+//-----------------------------------------------------------------------------
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+//-----------------------------------------------------------------------------
+
+class btRigidBody;
+
+//-----------------------------------------------------------------------------
+
+#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0))
+#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0))
+#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7))
+
+//-----------------------------------------------------------------------------
+
+class btSliderConstraint : public btTypedConstraint
+{
+protected:
+ btTransform m_frameInA;
+ btTransform m_frameInB;
+ // use frameA fo define limits, if true
+ bool m_useLinearReferenceFrameA;
+ // linear limits
+ btScalar m_lowerLinLimit;
+ btScalar m_upperLinLimit;
+ // angular limits
+ btScalar m_lowerAngLimit;
+ btScalar m_upperAngLimit;
+ // softness, restitution and damping for different cases
+ // DirLin - moving inside linear limits
+ // LimLin - hitting linear limit
+ // DirAng - moving inside angular limits
+ // LimAng - hitting angular limit
+ // OrthoLin, OrthoAng - against constraint axis
+ btScalar m_softnessDirLin;
+ btScalar m_restitutionDirLin;
+ btScalar m_dampingDirLin;
+ btScalar m_softnessDirAng;
+ btScalar m_restitutionDirAng;
+ btScalar m_dampingDirAng;
+ btScalar m_softnessLimLin;
+ btScalar m_restitutionLimLin;
+ btScalar m_dampingLimLin;
+ btScalar m_softnessLimAng;
+ btScalar m_restitutionLimAng;
+ btScalar m_dampingLimAng;
+ btScalar m_softnessOrthoLin;
+ btScalar m_restitutionOrthoLin;
+ btScalar m_dampingOrthoLin;
+ btScalar m_softnessOrthoAng;
+ btScalar m_restitutionOrthoAng;
+ btScalar m_dampingOrthoAng;
+
+ // for interlal use
+ bool m_solveLinLim;
+ bool m_solveAngLim;
+
+ btJacobianEntry m_jacLin[3];
+ btScalar m_jacLinDiagABInv[3];
+
+ btJacobianEntry m_jacAng[3];
+
+ btScalar m_timeStep;
+ btTransform m_calculatedTransformA;
+ btTransform m_calculatedTransformB;
+
+ btVector3 m_sliderAxis;
+ btVector3 m_realPivotAInW;
+ btVector3 m_realPivotBInW;
+ btVector3 m_projPivotInW;
+ btVector3 m_delta;
+ btVector3 m_depth;
+ btVector3 m_relPosA;
+ btVector3 m_relPosB;
+
+ btScalar m_angDepth;
+ btScalar m_kAngle;
+
+ bool m_poweredLinMotor;
+ btScalar m_targetLinMotorVelocity;
+ btScalar m_maxLinMotorForce;
+ btScalar m_accumulatedLinMotorImpulse;
+
+ bool m_poweredAngMotor;
+ btScalar m_targetAngMotorVelocity;
+ btScalar m_maxAngMotorForce;
+ btScalar m_accumulatedAngMotorImpulse;
+
+ //------------------------
+ void initParams();
+public:
+ // constructors
+ btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
+ btSliderConstraint();
+ // overrides
+ virtual void buildJacobian();
+ virtual void solveConstraint(btScalar timeStep);
+ // access
+ const btRigidBody& getRigidBodyA() const { return m_rbA; }
+ const btRigidBody& getRigidBodyB() const { return m_rbB; }
+ const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; }
+ 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; }
+ btScalar getLowerLinLimit() { return m_lowerLinLimit; }
+ void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; }
+ btScalar getUpperLinLimit() { return m_upperLinLimit; }
+ void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; }
+ btScalar getLowerAngLimit() { return m_lowerAngLimit; }
+ void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = lowerLimit; }
+ btScalar getUpperAngLimit() { return m_upperAngLimit; }
+ void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = upperLimit; }
+ bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; }
+ btScalar getSoftnessDirLin() { return m_softnessDirLin; }
+ btScalar getRestitutionDirLin() { return m_restitutionDirLin; }
+ btScalar getDampingDirLin() { return m_dampingDirLin ; }
+ btScalar getSoftnessDirAng() { return m_softnessDirAng; }
+ btScalar getRestitutionDirAng() { return m_restitutionDirAng; }
+ btScalar getDampingDirAng() { return m_dampingDirAng; }
+ btScalar getSoftnessLimLin() { return m_softnessLimLin; }
+ btScalar getRestitutionLimLin() { return m_restitutionLimLin; }
+ btScalar getDampingLimLin() { return m_dampingLimLin; }
+ btScalar getSoftnessLimAng() { return m_softnessLimAng; }
+ btScalar getRestitutionLimAng() { return m_restitutionLimAng; }
+ btScalar getDampingLimAng() { return m_dampingLimAng; }
+ btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; }
+ btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; }
+ btScalar getDampingOrthoLin() { return m_dampingOrthoLin; }
+ btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; }
+ btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; }
+ btScalar getDampingOrthoAng() { return m_dampingOrthoAng; }
+ void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; }
+ void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; }
+ void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; }
+ void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; }
+ void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; }
+ void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; }
+ void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; }
+ void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; }
+ void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; }
+ void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; }
+ void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; }
+ void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; }
+ void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; }
+ void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; }
+ void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; }
+ void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; }
+ void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; }
+ void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; }
+ void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; }
+ bool getPoweredLinMotor() { return m_poweredLinMotor; }
+ void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; }
+ btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; }
+ void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; }
+ btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; }
+ void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; }
+ bool getPoweredAngMotor() { return m_poweredAngMotor; }
+ void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; }
+ btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; }
+ void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; }
+ btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; }
+
+ // access for ODE solver
+ bool getSolveLinLimit() { return m_solveLinLim; }
+ btScalar getLinDepth() { return m_depth[0]; }
+ bool getSolveAngLimit() { return m_solveAngLim; }
+ btScalar getAngDepth() { return m_angDepth; }
+ // internal
+ void buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB);
+ void solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB);
+ // shared code used by ODE solver
+ void calculateTransforms(void);
+ void testLinLimits(void);
+ void testAngLimits(void);
+ // access for PE Solver
+ btVector3 getAncorInA(void);
+ btVector3 getAncorInB(void);
+};
+
+//-----------------------------------------------------------------------------
+
+#endif //SLIDER_CONSTRAINT_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..b3f0c9d7444 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h
@@ -19,38 +19,78 @@ subject to the following restrictions:
class btRigidBody;
#include "LinearMath/btVector3.h"
#include "LinearMath/btMatrix3x3.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btTransformUtil.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;
+
+ btVector3 m_pushVelocity;
+ btVector3 m_turnVelocity;
+
+
+ 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)
+ {
+ if (m_invMass)
+ {
+ m_linearVelocity += linearComponent*impulseMagnitude;
+ m_angularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+ SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude)
{
- m_linearVelocity += linearComponent*impulseMagnitude;
- m_angularVelocity += angularComponent*impulseMagnitude*m_angularFactor;
+ if (m_invMass)
+ {
+ m_pushVelocity += linearComponent*impulseMagnitude;
+ m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
}
+
void writebackVelocity()
{
if (m_invMass)
{
m_originalBody->setLinearVelocity(m_linearVelocity);
m_originalBody->setAngularVelocity(m_angularVelocity);
+
+ //m_originalBody->setCompanionId(-1);
+ }
+ }
+
+
+ void writebackVelocity(btScalar timeStep)
+ {
+ if (m_invMass)
+ {
+ m_originalBody->setLinearVelocity(m_linearVelocity);
+ m_originalBody->setAngularVelocity(m_angularVelocity);
+
+ //correct the position/orientation based on push/turn recovery
+ btTransform newTransform;
+ btTransformUtil::integrateTransform(m_originalBody->getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform);
+ m_originalBody->setWorldTransform(newTransform);
+
+ //m_originalBody->setCompanionId(-1);
}
}
@@ -69,3 +109,5 @@ 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..2c71360c5b9 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h
@@ -1,5 +1,3 @@
-
-
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
@@ -27,24 +25,34 @@ 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
{
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
btVector3 m_relpos1CrossNormal;
- btVector3 m_relpos2CrossNormal;
btVector3 m_contactNormal;
+
+ btVector3 m_relpos2CrossNormal;
btVector3 m_angularComponentA;
+
btVector3 m_angularComponentB;
- btScalar m_appliedVelocityImpulse;
+ mutable btScalar m_appliedPushImpulse;
+
+ 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];
+ void* m_originalContactPoint;
+ int m_unusedPadding[1];
+
enum btSolverConstraintType
{
@@ -61,3 +69,4 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint
#endif //BT_SOLVER_CONSTRAINT_H
+
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..c50ec6ec579 100644
--- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h
+++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h
@@ -17,7 +17,17 @@ 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,
+ SLIDER_CONSTRAINT_TYPE
+};
///TypedConstraint is the baseclass for Bullet constraints and vehicles
class btTypedConstraint
@@ -25,6 +35,8 @@ class btTypedConstraint
int m_userConstraintType;
int m_userConstraintId;
+ btTypedConstraintType m_constraintType;
+
btTypedConstraint& operator=(btTypedConstraint& other)
{
btAssert(0);
@@ -40,11 +52,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 +71,7 @@ public:
return m_rbB;
}
- btRigidBody& getRigidBodyA()
+ btRigidBody& getRigidBodyA()
{
return m_rbA;
}
@@ -83,14 +95,26 @@ public:
m_userConstraintId = uid;
}
- int getUserConstraintId()
+ int getUserConstraintId() const
{
return m_userConstraintId;
}
- btScalar getAppliedImpulse()
+
+ int getUid() 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
index 248c582dcd8..b28a46e299e 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp
@@ -24,97 +24,287 @@ subject to the following restrictions:
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btAlignedAllocator.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)
+ {
+
+ }
-#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)
+};
+
+plPhysicsSdkHandle plNewBulletSdk()
+{
+ void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16);
+ return (plPhysicsSdkHandle)new (mem)btPhysicsSdk;
+}
+
+void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk)
+{
+ btPhysicsSdk* phys = reinterpret_cast<btPhysicsSdk*>(physicsSdk);
+ btAlignedFree(phys);
+}
+
+
+/* Dynamics World */
+plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdkHandle)
+{
+ btPhysicsSdk* physicsSdk = reinterpret_cast<btPhysicsSdk*>(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<btCollisionShape*>( cshape);
+ assert(shape);
+ if (mass)
{
-
- 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;
+ shape->calculateLocalInertia(mass,localInertia);
}
- return -1.0f;
+ void* mem = btAlignedAlloc(sizeof(btRigidBody),16);
+ btRigidBody::btRigidBodyConstructionInfo rbci(mass, 0,shape,localInertia);
+ btRigidBody* body = new (mem)btRigidBody(rbci);
+ 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<btCollisionShape*>(compoundShapeHandle);
+ btAssert(colShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
+ btCompoundShape* compoundShape = reinterpret_cast<btCompoundShape*>(colShape);
+ btCollisionShape* childShape = reinterpret_cast<btCollisionShape*>(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<btCollisionShape*>( cshape);
+ (void)colShape;
+ btAssert(colShape->getShapeType()==CONVEX_HULL_SHAPE_PROXYTYPE);
+ btConvexHullShape* convexHullShape = reinterpret_cast<btConvexHullShape*>( cshape);
+ convexHullShape->addPoint(btPoint3(x,y,z));
+
+}
+
+void plDeleteShape(plCollisionShapeHandle cshape)
+{
+ btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape);
+ assert(shape);
+ btAlignedFree(shape);
+}
+void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling)
+{
+ btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( 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);
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp
new file mode 100644
index 00000000000..19443adc723
--- /dev/null
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp
@@ -0,0 +1,193 @@
+/*
+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 <stdio.h>
+
+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 );
+
+ if(0 != m_internalTickCallback) {
+ (*m_internalTickCallback)(this, 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
+ btScalar 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
+
+
+ btDispatcher* dispatcher = getDispatcher();
+ if (dispatcher)
+ dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
+
+ toi = dispatchInfo.m_timeOfImpact;
+
+ dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE;
+
+}
+
+void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep)
+{
+
+ btVector3 temporalAabbMin,temporalAabbMax;
+
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ body->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),temporalAabbMin,temporalAabbMax);
+ const btVector3& linvel = body->getLinearVelocity();
+
+ //make the AABB temporal
+ 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;
+
+ 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);
+
+
+
+}
+
+
+
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 1017c8af6ea..c7b1af245e9 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
@@ -21,7 +21,8 @@ subject to the following restrictions:
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
-#include <LinearMath/btTransformUtil.h>
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btQuickprof.h"
//rigidbody & constraints
#include "BulletDynamics/Dynamics/btRigidBody.h"
@@ -41,6 +42,7 @@ subject to the following restrictions:
#include "BulletCollision/CollisionShapes/btSphereShape.h"
#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
#include "LinearMath/btIDebugDraw.h"
@@ -57,17 +59,29 @@ subject to the following restrictions:
-btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver)
-:btDynamicsWorld(dispatcher,pairCache),
-m_constraintSolver(constraintSolver? constraintSolver: new btSequentialImpulseConstraintSolver),
-m_debugDrawer(0),
+btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
+:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
+m_constraintSolver(constraintSolver),
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 +89,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)
@@ -102,14 +123,35 @@ void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
}
}
-void btDiscreteDynamicsWorld::synchronizeMotionStates()
+void btDiscreteDynamicsWorld::debugDrawWorld()
{
- //debug vehicle wheels
-
-
+
+ if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
+ {
+ int numManifolds = getDispatcher()->getNumManifolds();
+ btVector3 color(0,0,0);
+ for (int i=0;i<numManifolds;i++)
+ {
+ btPersistentManifold* contactManifold = getDispatcher()->getManifoldByIndexInternal(i);
+ //btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
+ //btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
+
+ int numContacts = contactManifold->getNumContacts();
+ for (int j=0;j<numContacts;j++)
+ {
+ btManifoldPoint& cp = contactManifold->getContactPoint(j);
+ getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color);
+ }
+ }
+ }
+
+
+ if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb))
{
+ int i;
+
//todo: iterate over awake simulation islands!
- for ( int i=0;i<m_collisionObjects.size();i++)
+ for ( i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe)
@@ -135,26 +177,17 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates()
debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color);
}
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body && body->getMotionState() && !body->isStaticOrKinematicObject())
+ if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
{
- //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);
- }
+ btPoint3 minAabb,maxAabb;
+ btVector3 colorvec(1,0,0);
+ colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+ m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec);
}
- }
- }
- if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe)
- {
- for ( int i=0;i<this->m_vehicles.size();i++)
+ }
+
+ for ( i=0;i<this->m_vehicles.size();i++)
{
for (int v=0;v<m_vehicles[i]->getNumWheels();v++)
{
@@ -166,10 +199,7 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates()
{
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(
@@ -186,12 +216,87 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates()
}
}
}
+}
+
+void btDiscreteDynamicsWorld::clearForces()
+{
+ //todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ body->clearForces();
+ }
+ }
+}
+
+///apply gravity, call this once per timestep
+void btDiscreteDynamicsWorld::applyGravity()
+{
+ //todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body && body->isActive())
+ {
+ body->applyGravity();
+ }
+ }
+}
+
+
+
+void btDiscreteDynamicsWorld::synchronizeMotionStates()
+{
+ {
+ //todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+
+ 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;i<this->m_vehicles.size();i++)
+ {
+ for (int v=0;v<m_vehicles[i]->getNumWheels();v++)
+ {
+ //synchronize the wheels with the (interpolated) chassis worldtransform
+ m_vehicles[i]->updateWheelTransform(v,true);
+ }
+ }
+ }
}
int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
{
+ startProfiling(timeStep);
+
+ BT_PROFILE("stepSimulation");
+
int numSimulationSubSteps = 0;
if (maxSubSteps)
@@ -229,6 +334,8 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
saveKinematicState(fixedTimeStep);
+ applyGravity();
+
//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
@@ -242,16 +349,19 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps,
synchronizeMotionStates();
+ clearForces();
+
+#ifndef BT_NO_PROFILE
+ CProfileManager::Increment_Frame_Counter();
+#endif //BT_NO_PROFILE
+
return numSimulationSubSteps;
}
void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
{
- startProfiling(timeStep);
-
- ///update aabbs information
- updateAabbs();
+ BT_PROFILE("internalSingleStepSimulation");
///apply gravity, predict motion
predictUnconstraintMotion(timeStep);
@@ -286,8 +396,9 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
updateActivationState( timeStep );
-
-
+ if(0 != m_internalTickCallback) {
+ (*m_internalTickCallback)(this, timeStep);
+ }
}
void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
@@ -304,6 +415,11 @@ void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
}
}
+btVector3 btDiscreteDynamicsWorld::getGravity () const
+{
+ return m_gravity;
+}
+
void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
{
@@ -343,19 +459,18 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short
void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep)
{
- BEGIN_PROFILE("updateVehicles");
-
+ BT_PROFILE("updateVehicles");
+
for ( int i=0;i<m_vehicles.size();i++)
{
btRaycastVehicle* vehicle = m_vehicles[i];
vehicle->updateVehicle( timeStep);
}
- END_PROFILE("updateVehicles");
}
void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
{
- BEGIN_PROFILE("updateActivationState");
+ BT_PROFILE("updateActivationState");
for ( int i=0;i<m_collisionObjects.size();i++)
{
@@ -374,6 +489,12 @@ void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
{
if (body->getActivationState() == ACTIVE_TAG)
body->setActivationState( WANTS_DEACTIVATION );
+ if (body->getActivationState() == ISLAND_SLEEPING)
+ {
+ body->setAngularVelocity(btVector3(0,0,0));
+ body->setLinearVelocity(btVector3(0,0,0));
+ }
+
}
} else
{
@@ -382,7 +503,6 @@ void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
}
}
}
- END_PROFILE("updateActivationState");
}
void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies)
@@ -412,7 +532,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;
@@ -442,6 +562,7 @@ class btSortConstraintOnIslandPredicate
void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
{
+ BT_PROFILE("solveConstraints");
struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
{
@@ -452,7 +573,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
int m_numConstraints;
btIDebugDraw* m_debugDrawer;
btStackAlloc* m_stackAlloc;
-
+ btDispatcher* m_dispatcher;
InplaceSolverIslandCallback(
btContactSolverInfo& solverInfo,
@@ -460,13 +581,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 +602,42 @@ 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;i<m_numConstraints;i++)
+ 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
{
- 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;i<m_numConstraints;i++)
{
- startConstraint = &m_sortedConstraints[i];
- break;
+ if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
+ {
+ startConstraint = &m_sortedConstraints[i];
+ break;
+ }
}
- }
- //count the number of constraints in this island
- for (;i<m_numConstraints;i++)
- {
- if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
+ //count the number of constraints in this island
+ for (;i<m_numConstraints;i++)
{
- numCurConstraints++;
+ if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
+ {
+ numCurConstraints++;
+ }
}
- }
- m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc);
+ ///only call solveGroup if there is some work: avoid virtual function call, its overhead can be excessive
+ if (numManifolds + numCurConstraints)
+ {
+ m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
+ }
+
+ }
}
};
@@ -520,18 +655,18 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
- sortedConstraints.heapSort(btSortConstraintOnIslandPredicate());
+ sortedConstraints.quickSort(btSortConstraintOnIslandPredicate());
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);
}
@@ -539,7 +674,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
void btDiscreteDynamicsWorld::calculateSimulationIslands()
{
- BEGIN_PROFILE("calculateSimulationIslands");
+ BT_PROFILE("calculateSimulationIslands");
getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
@@ -569,66 +704,14 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands()
//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;i<m_collisionObjects.size();i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
-
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body)
- {
- // if (body->IsActive() && (!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");
+ BT_PROFILE("integrateTransforms");
btTransform predictedTrans;
for ( int i=0;i<m_collisionObjects.size();i++)
{
@@ -643,14 +726,13 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
}
}
}
- END_PROFILE("integrateTransforms");
}
void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
{
- BEGIN_PROFILE("predictUnconstraintMotion");
+ BT_PROFILE("predictUnconstraintMotion");
for ( int i=0;i<m_collisionObjects.size();i++)
{
btCollisionObject* colObj = m_collisionObjects[i];
@@ -661,51 +743,26 @@ void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
{
if (body->isActive())
{
- body->applyForces( timeStep);
body->integrateVelocities( timeStep);
+ //damping
+ body->applyDamping(timeStep);
+
body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
}
}
}
}
- END_PROFILE("predictUnconstraintMotion");
}
void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
{
(void)timeStep;
- #ifdef USE_QUICKPROF
+#ifndef BT_NO_PROFILE
+ CProfileManager::Reset();
+#endif //BT_NO_PROFILE
- //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
}
@@ -827,27 +884,52 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform,
btScalar radius = capsuleShape->getRadius();
btScalar halfHeight = capsuleShape->getHalfHeight();
+
+ int upAxis = capsuleShape->getUpAxis();
+
+
+ btVector3 capStart(0.f,0.f,0.f);
+ capStart[upAxis] = -halfHeight;
+
+ btVector3 capEnd(0.f,0.f,0.f);
+ capEnd[upAxis] = halfHeight;
// Draw the ends
{
+
btTransform childTransform = worldTransform;
- childTransform.getOrigin() = worldTransform * btVector3(0,halfHeight,0);
+ childTransform.getOrigin() = worldTransform * capStart;
debugDrawSphere(radius, childTransform, color);
}
{
btTransform childTransform = worldTransform;
- childTransform.getOrigin() = worldTransform * btVector3(0,-halfHeight,0);
+ childTransform.getOrigin() = worldTransform * capEnd;
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);
+
+ capStart[(upAxis+1)%3] = radius;
+ capEnd[(upAxis+1)%3] = radius;
+ getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color);
+ capStart[(upAxis+1)%3] = -radius;
+ capEnd[(upAxis+1)%3] = -radius;
+ getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color);
+
+ capStart[(upAxis+1)%3] = 0.f;
+ capEnd[(upAxis+1)%3] = 0.f;
+
+ capStart[(upAxis+2)%3] = radius;
+ capEnd[(upAxis+2)%3] = radius;
+ getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color);
+ capStart[(upAxis+2)%3] = -radius;
+ capEnd[(upAxis+2)%3] = -radius;
+ getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color);
+
+
break;
}
case CONE_SHAPE_PROXYTYPE:
@@ -856,9 +938,10 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform,
btScalar radius = coneShape->getRadius();//+coneShape->getMargin();
btScalar height = coneShape->getHeight();//+coneShape->getMargin();
btVector3 start = worldTransform.getOrigin();
- // insert here Bullet 2.69 that fixes representation of cone
+
int upAxis= coneShape->getConeUpIndex();
+
btVector3 offsetHeight(0,0,0);
offsetHeight[upAxis] = height * btScalar(0.5);
btVector3 offsetRadius(0,0,0);
@@ -871,11 +954,8 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform,
getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offset2Radius),color);
getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offset2Radius),color);
- // buggy code that does not take into account the direction of the cone
- //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;
}
@@ -884,7 +964,7 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform,
const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(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;
@@ -894,6 +974,25 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform,
getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight-offsetRadius),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color);
break;
}
+
+ case STATIC_PLANE_PROXYTYPE:
+ {
+ const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
+ btScalar planeConst = staticPlaneShape->getPlaneConstant();
+ const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
+ btVector3 planeOrigin = planeNormal * planeConst;
+ btVector3 vec0,vec1;
+ btPlaneSpace1(planeNormal,vec0,vec1);
+ btScalar vecLen = 100.f;
+ btVector3 pt0 = planeOrigin + vec0*vecLen;
+ btVector3 pt1 = planeOrigin - vec0*vecLen;
+ btVector3 pt2 = planeOrigin + vec1*vecLen;
+ btVector3 pt3 = planeOrigin - vec1*vecLen;
+ getDebugDrawer()->drawLine(worldTransform*pt0,worldTransform*pt1,color);
+ getDebugDrawer()->drawLine(worldTransform*pt2,worldTransform*pt3,color);
+ break;
+
+ }
default:
{
@@ -918,7 +1017,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);
}
@@ -950,12 +1049,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..d206a604960 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"
+
class btRaycastVehicle;
class btIDebugDraw;
-#include "../../LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btAlignedObjectArray.h"
///btDiscreteDynamicsWorld provides discrete rigid body simulation
@@ -42,7 +42,6 @@ protected:
btAlignedObjectArray<btTypedConstraint*> m_constraints;
- btIDebugDraw* m_debugDrawer;
btVector3 m_gravity;
@@ -53,14 +52,12 @@ protected:
bool m_ownsIslandManager;
bool m_ownsConstraintSolver;
- btContactSolverInfo m_solverInfo;
-
-
+
btAlignedObjectArray<btRaycastVehicle*> m_vehicles;
int m_profileTimings;
- void predictUnconstraintMotion(btScalar timeStep);
+ virtual void predictUnconstraintMotion(btScalar timeStep);
void integrateTransforms(btScalar timeStep);
@@ -86,14 +83,13 @@ 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();
///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);
@@ -118,17 +114,9 @@ public:
return this;
}
- virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
- {
- m_debugDrawer = debugDrawer;
- }
-
- virtual btIDebugDraw* getDebugDrawer()
- {
- return m_debugDrawer;
- }
virtual void setGravity(const btVector3& gravity);
+ virtual btVector3 getGravity () const;
virtual void addRigidBody(btRigidBody* body);
@@ -138,7 +126,11 @@ public:
void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
+ virtual void debugDrawWorld();
+
virtual void setConstraintSolver(btConstraintSolver* solver);
+
+ virtual btConstraintSolver* getConstraintSolver();
virtual int getNumConstraints() const;
@@ -146,11 +138,21 @@ public:
virtual const btTypedConstraint* getConstraint(int index) const;
- btContactSolverInfo& getSolverInfo()
+
+ virtual btDynamicsWorldType getWorldType() const
{
- return m_solverInfo;
+ return BT_DISCRETE_DYNAMICS_WORLD;
}
+
+ ///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep.
+ virtual void clearForces();
+
+ ///apply gravity, call this once per timestep
+ virtual void applyGravity();
+ virtual void setNumTasks(int numTasks)
+ {
+ }
};
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h
index 65b63fad4b5..dd9dfa71b7f 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h
@@ -16,20 +16,39 @@ 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"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
class btTypedConstraint;
class btRaycastVehicle;
class btConstraintSolver;
+class btDynamicsWorld;
+
+/// Type for the callback for each tick
+typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep);
+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
+///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
class btDynamicsWorld : public btCollisionWorld
{
- public:
+
+protected:
+ btInternalTickCallback m_internalTickCallback;
+ void* m_worldUserInfo;
+
+ btContactSolverInfo m_solverInfo;
+
+public:
- btDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache)
- :btCollisionWorld(dispatcher,pairCache)
+ btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
+ :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0), m_worldUserInfo(0)
{
}
@@ -37,34 +56,37 @@ class btDynamicsWorld : public btCollisionWorld
{
}
- ///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;
+ ///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds.
+ ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'.
+ ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'.
+ ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant.
+ virtual int stepSimulation( btScalar timeStep,int maxSubSteps=10, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0;
- virtual void updateAabbs() = 0;
+ virtual void debugDrawWorld() = 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 addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false)
+ {
+ (void)constraint; (void)disableCollisionsBetweenLinkedBodies;
+ }
+ virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;}
- virtual void setDebugDrawer(btIDebugDraw* debugDrawer) = 0;
+ virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}
- virtual btIDebugDraw* getDebugDrawer() = 0;
+ virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}
//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 btVector3 getGravity () const = 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; }
@@ -72,7 +94,35 @@ class btDynamicsWorld : public btCollisionWorld
virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; }
+ virtual btDynamicsWorldType getWorldType() const=0;
+
+ virtual void clearForces() = 0;
+
+ /// Set the callback for when an internal tick (simulation substep) happens, optional user info
+ void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0)
+ {
+ m_internalTickCallback = cb;
+ m_worldUserInfo = worldUserInfo;
+ }
+
+ void setWorldUserInfo(void* worldUserInfo)
+ {
+ m_worldUserInfo = worldUserInfo;
+ }
+
+ void* getWorldUserInfo() const
+ {
+ return m_worldUserInfo;
+ }
+
+ btContactSolverInfo& getSolverInfo()
+ {
+ return m_solverInfo;
+ }
+
+
};
#endif //BT_DYNAMICS_WORLD_H
+
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
index 9ed3579d89c..e2afb687ac6 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp
@@ -20,36 +20,53 @@ subject to the following restrictions:
#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)
+
+btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
+{
+ setupRigidBody(constructionInfo);
+}
+
+btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia)
+{
+ btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia);
+ setupRigidBody(cinfo);
+}
+
+void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
{
- if (motionState)
+ m_internalType=CO_RIGID_BODY;
+
+ m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ m_angularFactor = btScalar(1.);
+ m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
+ m_linearDamping = btScalar(0.);
+ m_angularDamping = btScalar(0.5);
+ m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold;
+ m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold;
+ m_optionalMotionState = constructionInfo.m_motionState;
+ m_contactSolverType = 0;
+ m_frictionSolverType = 0;
+ m_additionalDamping = constructionInfo.m_additionalDamping;
+ m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor;
+ m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr;
+ m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr;
+ m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor;
+
+ if (m_optionalMotionState)
{
- motionState->getWorldTransform(m_worldTransform);
+ m_optionalMotionState->getWorldTransform(m_worldTransform);
} else
{
- m_worldTransform = btTransform::getIdentity();
+ m_worldTransform = constructionInfo.m_startWorldTransform;
}
m_interpolationWorldTransform = m_worldTransform;
@@ -57,90 +74,21 @@ btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionS
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_friction = constructionInfo.m_friction;
+ m_restitution = constructionInfo.m_restitution;
- m_collisionShape = collisionShape;
+ setCollisionShape( constructionInfo.m_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);
+ setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia);
+ setDamping(constructionInfo.m_linearDamping, constructionInfo.m_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);
}
@@ -191,50 +139,63 @@ void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
-#include <stdio.h>
-
-void btRigidBody::applyForces(btScalar step)
+///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
+void btRigidBody::applyDamping(btScalar timeStep)
{
- 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));
+ m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+ m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * 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)
+ if (m_additionalDamping)
{
- btScalar dampVel = btScalar(0.005);
- if (speed > dampVel)
+ //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
+ //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
+ if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) &&
+ (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr))
{
- btVector3 dir = m_linearVelocity.normalized();
- m_linearVelocity -= dir * dampVel;
- } else
- {
- m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ m_angularVelocity *= m_additionalDampingFactor;
+ m_linearVelocity *= m_additionalDampingFactor;
}
- }
+
- btScalar angSpeed = m_angularVelocity.length();
- if (angSpeed < m_angularDamping)
- {
- btScalar angDampVel = btScalar(0.005);
- if (angSpeed > angDampVel)
+ btScalar speed = m_linearVelocity.length();
+ if (speed < m_linearDamping)
{
- btVector3 dir = m_angularVelocity.normalized();
- m_angularVelocity -= dir * angDampVel;
- } else
+ 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)
{
- m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ 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::applyGravity()
+{
+ if (isStaticOrKinematicObject())
+ return;
+ applyCentralForce(m_gravity);
+
}
void btRigidBody::proceedToTransform(const btTransform& newTrans)
@@ -285,7 +246,6 @@ void btRigidBody::integrateVelocities(btScalar step)
m_angularVelocity *= (MAX_ANGVEL/step) /angvel;
}
- clearForces();
}
btQuaternion btRigidBody::getOrientation() const
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
index 0707595d48e..4596f90a00f 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h
@@ -16,27 +16,29 @@ 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;
class btTypedConstraint;
-extern btScalar gLinearAirDamping;
-
extern btScalar gDeactivationTime;
extern bool gDisableDeactivation;
-extern btScalar gLinearSleepingThreshold;
-extern btScalar gAngularSleepingThreshold;
-/// btRigidBody class for btRigidBody Dynamics
-///
+///btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape.
+///It is recommended for performance and memory use to share btCollisionShape objects whenever possible.
+///There are 3 types of rigid bodies:
+///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics.
+///- B) Fixed objects with zero mass. They are not moving (basically collision objects)
+///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform.
+///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time.
+///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects)
class btRigidBody : public btCollisionObject
{
@@ -53,7 +55,16 @@ class btRigidBody : public btCollisionObject
btScalar m_linearDamping;
btScalar m_angularDamping;
-
+
+ bool m_additionalDamping;
+ btScalar m_additionalDampingFactor;
+ btScalar m_additionalLinearDampingThresholdSqr;
+ btScalar m_additionalAngularDampingThresholdSqr;
+ btScalar m_additionalAngularDampingFactor;
+
+
+ btScalar m_linearSleepingThreshold;
+ btScalar m_angularSleepingThreshold;
//m_optionalMotionState allows to automatic synchronize the world transform for active objects
btMotionState* m_optionalMotionState;
@@ -63,12 +74,85 @@ class btRigidBody : public btCollisionObject
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.));
+ ///btRigidBodyConstructionInfo provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body.
+ ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument)
+ ///You can use the motion state to synchronize the world transform between physics and graphics objects.
+ ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state,
+ ///m_startWorldTransform is only used when you don't provide a motion state.
+ struct btRigidBodyConstructionInfo
+ {
+ btScalar m_mass;
+
+ ///When a motionState is provided, the rigid body will initialize its world transform from the motion state
+ ///In this case, m_startWorldTransform is ignored.
+ btMotionState* m_motionState;
+ btTransform m_startWorldTransform;
+
+ btCollisionShape* m_collisionShape;
+ btVector3 m_localInertia;
+ btScalar m_linearDamping;
+ btScalar m_angularDamping;
+
+ ///best simulation results when friction is non-zero
+ btScalar m_friction;
+ ///best simulation results using zero restitution.
+ btScalar m_restitution;
+
+ btScalar m_linearSleepingThreshold;
+ btScalar m_angularSleepingThreshold;
+
+ //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
+ //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
+ bool m_additionalDamping;
+ btScalar m_additionalDampingFactor;
+ btScalar m_additionalLinearDampingThresholdSqr;
+ btScalar m_additionalAngularDampingThresholdSqr;
+ btScalar m_additionalAngularDampingFactor;
+
+
+ btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)):
+ m_mass(mass),
+ m_motionState(motionState),
+ m_collisionShape(collisionShape),
+ m_localInertia(localInertia),
+ m_linearDamping(btScalar(0.)),
+ m_angularDamping(btScalar(0.)),
+ m_friction(btScalar(0.5)),
+ m_restitution(btScalar(0.)),
+ m_linearSleepingThreshold(btScalar(0.8)),
+ m_angularSleepingThreshold(btScalar(1.f)),
+ m_additionalDamping(false),
+ m_additionalDampingFactor(btScalar(0.005)),
+ m_additionalLinearDampingThresholdSqr(btScalar(0.01)),
+ m_additionalAngularDampingThresholdSqr(btScalar(0.01)),
+ m_additionalAngularDampingFactor(btScalar(0.01))
+ {
+ m_startWorldTransform.setIdentity();
+ }
+ };
+
+ ///btRigidBody constructor using construction info
+ btRigidBody( const btRigidBodyConstructionInfo& constructionInfo);
+
+ ///btRigidBody constructor for backwards compatibility.
+ ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo)
+ btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,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);
+ }
+
+protected:
+
+ ///setupRigidBody is only used internally by the constructor
+ void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
+
+public:
void proceedToTransform(const btTransform& newTrans);
@@ -76,11 +160,15 @@ public:
///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();
+ if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY)
+ return (const btRigidBody*)colObj;
+ return 0;
}
static btRigidBody* upcast(btCollisionObject* colObj)
{
- return (btRigidBody*)colObj->getInternalOwner();
+ if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY)
+ return (btRigidBody*)colObj;
+ return 0;
}
/// continuous collision detection needs prediction
@@ -88,8 +176,7 @@ public:
void saveKinematicState(btScalar step);
-
- void applyForces(btScalar step);
+ void applyGravity();
void setGravity(const btVector3& acceleration);
@@ -99,12 +186,34 @@ public:
}
void setDamping(btScalar lin_damping, btScalar ang_damping);
-
- inline const btCollisionShape* getCollisionShape() const {
+
+ btScalar getLinearDamping() const
+ {
+ return m_linearDamping;
+ }
+
+ btScalar getAngularDamping() const
+ {
+ return m_angularDamping;
+ }
+
+ btScalar getLinearSleepingThreshold() const
+ {
+ return m_linearSleepingThreshold;
+ }
+
+ btScalar getAngularSleepingThreshold() const
+ {
+ return m_angularSleepingThreshold;
+ }
+
+ void applyDamping(btScalar timeStep);
+
+ SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const {
return m_collisionShape;
}
- inline btCollisionShape* getCollisionShape() {
+ SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() {
return m_collisionShape;
}
@@ -134,6 +243,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;
@@ -142,7 +257,7 @@ public:
void applyForce(const btVector3& force, const btVector3& rel_pos)
{
applyCentralForce(force);
- applyTorque(rel_pos.cross(force));
+ applyTorque(rel_pos.cross(force)*m_angularFactor);
}
void applyCentralImpulse(const btVector3& impulse)
@@ -168,7 +283,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 +353,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 +365,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 +388,7 @@ public:
}
- inline bool wantsSleeping()
+ SIMD_FORCE_INLINE bool wantsSleeping()
{
if (getActivationState() == DISABLE_DEACTIVATION)
@@ -348,6 +463,16 @@ 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..3be04d1a4ad 100644
--- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
+++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
@@ -27,16 +27,19 @@ subject to the following restrictions:
can be used by probes that are checking whether the
library is actually installed.
*/
-extern "C" void btBulletDynamicsProbe () {}
+extern "C"
+{
+ void btBulletDynamicsProbe ();
+ 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),
m_gravity(0,0,-10)
{
@@ -46,7 +49,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 +77,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
@@ -85,10 +89,27 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b
synchronizeMotionStates();
+ clearForces();
+
return 1;
}
+void btSimpleDynamicsWorld::clearForces()
+{
+ //todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ body->clearForces();
+ }
+ }
+}
+
void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
{
@@ -104,6 +125,11 @@ void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
}
}
+btVector3 btSimpleDynamicsWorld::getGravity () const
+{
+ return m_gravity;
+}
+
void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body)
{
removeCollisionObject(body);
@@ -133,7 +159,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);
}
}
}
@@ -171,8 +197,9 @@ void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
{
if (body->isActive())
{
- body->applyForces( timeStep);
+ body->applyGravity();
body->integrateVelocities( timeStep);
+ body->applyDamping(timeStep);
body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
}
}
@@ -204,8 +231,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..5c56fdf1327 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:
@@ -35,8 +32,6 @@ protected:
bool m_ownsConstraintSolver;
- btIDebugDraw* m_debugDrawer;
-
void predictUnconstraintMotion(btScalar timeStep);
void integrateTransforms(btScalar timeStep);
@@ -48,25 +43,17 @@ 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();
///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 btVector3 getGravity () const;
+
virtual void addRigidBody(btRigidBody* body);
virtual void removeRigidBody(btRigidBody* body);
@@ -77,6 +64,15 @@ public:
virtual void setConstraintSolver(btConstraintSolver* solver);
+ virtual btConstraintSolver* getConstraintSolver();
+
+ virtual btDynamicsWorldType getWorldType() const
+ {
+ return BT_SIMPLE_DYNAMICS_WORLD;
+ }
+
+ virtual void clearForces();
+
};
#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..fe65245c2a1 100644
--- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp
+++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp
@@ -23,12 +23,11 @@
#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
-
-
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;
@@ -487,6 +486,7 @@ struct btWheelContactPoint
};
+btScalar calcRollingFriction(btWheelContactPoint& contactPoint);
btScalar calcRollingFriction(btWheelContactPoint& contactPoint)
{
@@ -507,8 +507,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;
}
@@ -525,11 +525,10 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
if (!numWheel)
return;
-
- btVector3* forwardWS = new btVector3[numWheel];
- btVector3* axle = new btVector3[numWheel];
- btScalar* forwardImpulse = new btScalar[numWheel];
- btScalar* sideImpulse = new btScalar[numWheel];
+ m_forwardWS.resize(numWheel);
+ m_axle.resize(numWheel);
+ m_forwardImpulse.resize(numWheel);
+ m_sideImpulse.resize(numWheel);
int numWheelsOnGround = 0;
@@ -541,8 +540,8 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
if (groundObject)
numWheelsOnGround++;
- sideImpulse[i] = btScalar(0.);
- forwardImpulse[i] = btScalar(0.);
+ m_sideImpulse[i] = btScalar(0.);
+ m_forwardImpulse[i] = btScalar(0.);
}
@@ -561,25 +560,25 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
const btTransform& wheelTrans = getWheelTransformWS( i );
btMatrix3x3 wheelBasis0 = wheelTrans.getBasis();
- axle[i] = btVector3(
+ m_axle[i] = btVector3(
wheelBasis0[0][m_indexRightAxis],
wheelBasis0[1][m_indexRightAxis],
wheelBasis0[2][m_indexRightAxis]);
const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
- btScalar proj = axle[i].dot(surfNormalWS);
- axle[i] -= surfNormalWS * proj;
- axle[i] = axle[i].normalize();
+ btScalar proj = m_axle[i].dot(surfNormalWS);
+ m_axle[i] -= surfNormalWS * proj;
+ m_axle[i] = m_axle[i].normalize();
- forwardWS[i] = surfNormalWS.cross(axle[i]);
- forwardWS[i].normalize();
+ m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
+ m_forwardWS[i].normalize();
resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS,
*groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
- btScalar(0.), axle[i],sideImpulse[i],timeStep);
+ btScalar(0.), m_axle[i],m_sideImpulse[i],timeStep);
- sideImpulse[i] *= sideFrictionStiffness2;
+ m_sideImpulse[i] *= sideFrictionStiffness2;
}
@@ -608,7 +607,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
{
btScalar defaultRollingFrictionImpulse = 0.f;
btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
- btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,forwardWS[wheel],maxImpulse);
+ btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
rollingFriction = calcRollingFriction(contactPt);
}
}
@@ -618,7 +617,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
- forwardImpulse[wheel] = btScalar(0.);
+ m_forwardImpulse[wheel] = btScalar(0.);
m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
if (groundObject)
@@ -631,10 +630,10 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
btScalar maximpSquared = maximp * maximpSide;
- forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
+ m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
- btScalar x = (forwardImpulse[wheel] ) * fwdFactor;
- btScalar y = (sideImpulse[wheel] ) * sideFactor;
+ btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor;
+ btScalar y = (m_sideImpulse[wheel] ) * sideFactor;
btScalar impulseSquared = (x*x + y*y);
@@ -658,12 +657,12 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
{
for (int wheel = 0;wheel < getNumWheels(); wheel++)
{
- if (sideImpulse[wheel] != btScalar(0.))
+ if (m_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;
+ m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
+ m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
}
}
}
@@ -678,11 +677,11 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
m_chassisBody->getCenterOfMassPosition();
- if (forwardImpulse[wheel] != btScalar(0.))
+ if (m_forwardImpulse[wheel] != btScalar(0.))
{
- m_chassisBody->applyImpulse(forwardWS[wheel]*(forwardImpulse[wheel]),rel_pos);
+ m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos);
}
- if (sideImpulse[wheel] != btScalar(0.))
+ if (m_sideImpulse[wheel] != btScalar(0.))
{
class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
@@ -690,7 +689,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
groundObject->getCenterOfMassPosition();
- btVector3 sideImp = axle[wheel] * sideImpulse[wheel];
+ btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
rel_pos[2] *= wheelInfo.m_rollInfluence;
m_chassisBody->applyImpulse(sideImp,rel_pos);
@@ -701,10 +700,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep)
}
}
- delete []forwardWS;
- delete [] axle;
- delete[]forwardImpulse;
- delete[] sideImpulse;
+
}
@@ -716,11 +712,11 @@ void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3&
m_dynamicsWorld->rayTest(from, to, rayCallback);
- if (rayCallback.HasHit())
+ if (rayCallback.hasHit())
{
btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
- if (body)
+ if (body && body->hasContactResponse())
{
result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h
index f4249599615..8361dcabe4b 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;
@@ -23,6 +23,12 @@ class btVehicleTuning;
///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle.
class btRaycastVehicle : public btTypedConstraint
{
+
+ btAlignedObjectArray<btVector3> m_forwardWS;
+ btAlignedObjectArray<btVector3> m_axle;
+ btAlignedObjectArray<btScalar> m_forwardImpulse;
+ btAlignedObjectArray<btScalar> m_sideImpulse;
+
public:
class btVehicleTuning
{
@@ -114,7 +120,7 @@ public:
void updateSuspension(btScalar deltaTime);
- void updateFriction(btScalar timeStep);
+ virtual void updateFriction(btScalar timeStep);
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/BulletSoftBody/CMakeLists.txt b/extern/bullet2/src/BulletSoftBody/CMakeLists.txt
new file mode 100644
index 00000000000..a725e10ff77
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/CMakeLists.txt
@@ -0,0 +1,21 @@
+
+INCLUDE_DIRECTORIES(
+${BULLET_PHYSICS_SOURCE_DIR}/src }
+)
+
+ADD_LIBRARY(LibBulletSoftBody
+ btSoftBody.cpp
+ btSoftBody.h
+ btSoftBodyHelpers.cpp
+ btSparseSDF.h
+ btSoftBodyHelpers.h
+ btSoftBodyRigidBodyCollisionConfiguration.cpp
+ btSoftRigidCollisionAlgorithm.cpp
+ btSoftRigidCollisionAlgorithm.h
+ btSoftSoftCollisionAlgorithm.cpp
+ btSoftSoftCollisionAlgorithm.h
+ btSoftBodyConcaveCollisionAlgorithm.cpp
+ btSoftBodyConcaveCollisionAlgorithm.h
+ btSoftRigidDynamicsWorld.h
+ btSoftRigidDynamicsWorld.cpp
+)
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp
new file mode 100644
index 00000000000..dfb48e2ff2d
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp
@@ -0,0 +1,2590 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btSoftBody implementation by Nathanael Presson
+
+#include "btSoftBodyInternals.h"
+
+//
+btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m)
+:m_worldInfo(worldInfo)
+{
+ /* Init */
+ m_internalType = CO_SOFT_BODY;
+ m_cfg.aeromodel = eAeroModel::V_Point;
+ m_cfg.kVCF = 1;
+ m_cfg.kDG = 0;
+ m_cfg.kLF = 0;
+ m_cfg.kDP = 0;
+ m_cfg.kPR = 0;
+ m_cfg.kVC = 0;
+ m_cfg.kDF = (btScalar)0.2;
+ m_cfg.kMT = 0;
+ m_cfg.kCHR = (btScalar)1.0;
+ m_cfg.kKHR = (btScalar)0.1;
+ m_cfg.kSHR = (btScalar)1.0;
+ m_cfg.kAHR = (btScalar)0.7;
+ m_cfg.kSRHR_CL = (btScalar)0.1;
+ m_cfg.kSKHR_CL = (btScalar)1;
+ m_cfg.kSSHR_CL = (btScalar)0.5;
+ m_cfg.kSR_SPLT_CL = (btScalar)0.5;
+ m_cfg.kSK_SPLT_CL = (btScalar)0.5;
+ m_cfg.kSS_SPLT_CL = (btScalar)0.5;
+ m_cfg.maxvolume = (btScalar)1;
+ m_cfg.timescale = 1;
+ m_cfg.viterations = 0;
+ m_cfg.piterations = 1;
+ m_cfg.diterations = 0;
+ m_cfg.citerations = 4;
+ m_cfg.collisions = fCollision::Default;
+ m_pose.m_bvolume = false;
+ m_pose.m_bframe = false;
+ m_pose.m_volume = 0;
+ m_pose.m_com = btVector3(0,0,0);
+ m_pose.m_rot.setIdentity();
+ m_pose.m_scl.setIdentity();
+ m_tag = 0;
+ m_timeacc = 0;
+ m_bUpdateRtCst = true;
+ m_bounds[0] = btVector3(0,0,0);
+ m_bounds[1] = btVector3(0,0,0);
+ m_worldTransform.setIdentity();
+ setSolver(eSolverPresets::Positions);
+ /* Default material */
+ Material* pm=appendMaterial();
+ pm->m_kLST = 1;
+ pm->m_kAST = 1;
+ pm->m_kVST = 1;
+ pm->m_flags = fMaterial::Default;
+ /* Collision shape */
+ ///for now, create a collision shape internally
+ setCollisionShape(new btSoftBodyCollisionShape(this));
+ m_collisionShape->setMargin(0.25);
+ /* Nodes */
+ const btScalar margin=getCollisionShape()->getMargin();
+ m_nodes.resize(node_count);
+ for(int i=0,ni=node_count;i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ ZeroInitialize(n);
+ n.m_x = x?*x++:btVector3(0,0,0);
+ n.m_q = n.m_x;
+ n.m_im = m?*m++:1;
+ n.m_im = n.m_im>0?1/n.m_im:0;
+ n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
+ n.m_material= pm;
+ }
+ updateBounds();
+
+
+}
+
+//
+btSoftBody::~btSoftBody()
+{
+ //for now, delete the internal shape
+ delete m_collisionShape;
+ int i;
+
+ for(i=0;i<m_clusters.size();++i)
+ btAlignedFree(m_clusters[i]);
+ for(i=0;i<m_materials.size();++i)
+ btAlignedFree(m_materials[i]);
+ for(i=0;i<m_joints.size();++i)
+ btAlignedFree(m_joints[i]);
+}
+
+//
+bool btSoftBody::checkLink(int node0,int node1) const
+{
+ return(checkLink(&m_nodes[node0],&m_nodes[node1]));
+}
+
+//
+bool btSoftBody::checkLink(const Node* node0,const Node* node1) const
+{
+ const Node* n[]={node0,node1};
+ for(int i=0,ni=m_links.size();i<ni;++i)
+ {
+ const Link& l=m_links[i];
+ if( (l.m_n[0]==n[0]&&l.m_n[1]==n[1])||
+ (l.m_n[0]==n[1]&&l.m_n[1]==n[0]))
+ {
+ return(true);
+ }
+ }
+ return(false);
+}
+
+//
+bool btSoftBody::checkFace(int node0,int node1,int node2) const
+{
+ const Node* n[]={ &m_nodes[node0],
+ &m_nodes[node1],
+ &m_nodes[node2]};
+ for(int i=0,ni=m_faces.size();i<ni;++i)
+ {
+ const Face& f=m_faces[i];
+ int c=0;
+ for(int j=0;j<3;++j)
+ {
+ if( (f.m_n[j]==n[0])||
+ (f.m_n[j]==n[1])||
+ (f.m_n[j]==n[2])) c|=1<<j; else break;
+ }
+ if(c==7) return(true);
+ }
+ return(false);
+}
+
+//
+btSoftBody::Material* btSoftBody::appendMaterial()
+{
+Material* pm=new(btAlignedAlloc(sizeof(Material),16)) Material();
+if(m_materials.size()>0)
+ *pm=*m_materials[0];
+ else
+ ZeroInitialize(*pm);
+m_materials.push_back(pm);
+return(pm);
+}
+
+//
+void btSoftBody::appendNote( const char* text,
+ const btVector3& o,
+ const btVector4& c,
+ Node* n0,
+ Node* n1,
+ Node* n2,
+ Node* n3)
+{
+Note n;
+ZeroInitialize(n);
+n.m_rank = 0;
+n.m_text = text;
+n.m_offset = o;
+n.m_coords[0] = c.x();
+n.m_coords[1] = c.y();
+n.m_coords[2] = c.z();
+n.m_coords[3] = c.w();
+n.m_nodes[0] = n0;n.m_rank+=n0?1:0;
+n.m_nodes[1] = n1;n.m_rank+=n1?1:0;
+n.m_nodes[2] = n2;n.m_rank+=n2?1:0;
+n.m_nodes[3] = n3;n.m_rank+=n3?1:0;
+m_notes.push_back(n);
+}
+
+//
+void btSoftBody::appendNote( const char* text,
+ const btVector3& o,
+ Node* feature)
+{
+appendNote(text,o,btVector4(1,0,0,0),feature);
+}
+
+//
+void btSoftBody::appendNote( const char* text,
+ const btVector3& o,
+ Link* feature)
+{
+static const btScalar w=1/(btScalar)2;
+appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0],
+ feature->m_n[1]);
+}
+
+//
+void btSoftBody::appendNote( const char* text,
+ const btVector3& o,
+ Face* feature)
+{
+static const btScalar w=1/(btScalar)3;
+appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0],
+ feature->m_n[1],
+ feature->m_n[2]);
+}
+
+//
+void btSoftBody::appendNode( const btVector3& x,btScalar m)
+{
+if(m_nodes.capacity()==m_nodes.size())
+ {
+ pointersToIndices();
+ m_nodes.reserve(m_nodes.size()*2+1);
+ indicesToPointers();
+ }
+const btScalar margin=getCollisionShape()->getMargin();
+m_nodes.push_back(Node());
+Node& n=m_nodes[m_nodes.size()-1];
+ZeroInitialize(n);
+n.m_x = x;
+n.m_q = n.m_x;
+n.m_im = m>0?1/m:0;
+n.m_material = m_materials[0];
+n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n);
+}
+
+//
+void btSoftBody::appendLink(int model,Material* mat)
+{
+Link l;
+if(model>=0)
+ l=m_links[model];
+ else
+ { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; }
+m_links.push_back(l);
+}
+
+//
+void btSoftBody::appendLink( int node0,
+ int node1,
+ Material* mat,
+ bool bcheckexist)
+{
+ appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist);
+}
+
+//
+void btSoftBody::appendLink( Node* node0,
+ Node* node1,
+ Material* mat,
+ bool bcheckexist)
+{
+ if((!bcheckexist)||(!checkLink(node0,node1)))
+ {
+ appendLink(-1,mat);
+ Link& l=m_links[m_links.size()-1];
+ l.m_n[0] = node0;
+ l.m_n[1] = node1;
+ l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
+ m_bUpdateRtCst=true;
+ }
+}
+
+//
+void btSoftBody::appendFace(int model,Material* mat)
+{
+Face f;
+if(model>=0)
+ { f=m_faces[model]; }
+ else
+ { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; }
+m_faces.push_back(f);
+}
+
+//
+void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat)
+{
+ appendFace(-1,mat);
+ Face& f=m_faces[m_faces.size()-1];
+ btAssert(node0!=node1);
+ btAssert(node1!=node2);
+ btAssert(node2!=node0);
+ f.m_n[0] = &m_nodes[node0];
+ f.m_n[1] = &m_nodes[node1];
+ f.m_n[2] = &m_nodes[node2];
+ f.m_ra = AreaOf( f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x);
+ m_bUpdateRtCst=true;
+}
+
+//
+void btSoftBody::appendAnchor(int node,btRigidBody* body)
+{
+ Anchor a;
+ a.m_node = &m_nodes[node];
+ a.m_body = body;
+ a.m_local = body->getInterpolationWorldTransform().inverse()*a.m_node->m_x;
+ a.m_node->m_battach = 1;
+ m_anchors.push_back(a);
+}
+
+//
+void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1)
+{
+LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint();
+pj->m_bodies[0] = body0;
+pj->m_bodies[1] = body1;
+pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position;
+pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position;
+pj->m_cfm = specs.cfm;
+pj->m_erp = specs.erp;
+pj->m_split = specs.split;
+m_joints.push_back(pj);
+}
+
+//
+void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body)
+{
+appendLinearJoint(specs,m_clusters[0],body);
+}
+
+//
+void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body)
+{
+appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]);
+}
+
+//
+void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1)
+{
+AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint();
+pj->m_bodies[0] = body0;
+pj->m_bodies[1] = body1;
+pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis;
+pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis;
+pj->m_cfm = specs.cfm;
+pj->m_erp = specs.erp;
+pj->m_split = specs.split;
+pj->m_icontrol = specs.icontrol;
+m_joints.push_back(pj);
+}
+
+//
+void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body)
+{
+appendAngularJoint(specs,m_clusters[0],body);
+}
+
+//
+void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body)
+{
+appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]);
+}
+
+//
+void btSoftBody::addForce(const btVector3& force)
+{
+ for(int i=0,ni=m_nodes.size();i<ni;++i) addForce(force,i);
+}
+
+//
+void btSoftBody::addForce(const btVector3& force,int node)
+{
+ Node& n=m_nodes[node];
+ if(n.m_im>0)
+ {
+ n.m_f += force;
+ }
+}
+
+//
+void btSoftBody::addVelocity(const btVector3& velocity)
+{
+ for(int i=0,ni=m_nodes.size();i<ni;++i) addVelocity(velocity,i);
+}
+
+//
+void btSoftBody::addVelocity(const btVector3& velocity,int node)
+{
+ Node& n=m_nodes[node];
+ if(n.m_im>0)
+ {
+ n.m_v += velocity;
+ }
+}
+
+//
+void btSoftBody::setMass(int node,btScalar mass)
+{
+ m_nodes[node].m_im=mass>0?1/mass:0;
+ m_bUpdateRtCst=true;
+}
+
+//
+btScalar btSoftBody::getMass(int node) const
+{
+ return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0);
+}
+
+//
+btScalar btSoftBody::getTotalMass() const
+{
+ btScalar mass=0;
+ for(int i=0;i<m_nodes.size();++i)
+ {
+ mass+=getMass(i);
+ }
+ return(mass);
+}
+
+//
+void btSoftBody::setTotalMass(btScalar mass,bool fromfaces)
+{
+ int i;
+
+ if(fromfaces)
+ {
+
+ for(i=0;i<m_nodes.size();++i)
+ {
+ m_nodes[i].m_im=0;
+ }
+ for(i=0;i<m_faces.size();++i)
+ {
+ const Face& f=m_faces[i];
+ const btScalar twicearea=AreaOf( f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x);
+ for(int j=0;j<3;++j)
+ {
+ f.m_n[j]->m_im+=twicearea;
+ }
+ }
+ for( i=0;i<m_nodes.size();++i)
+ {
+ m_nodes[i].m_im=1/m_nodes[i].m_im;
+ }
+ }
+ const btScalar tm=getTotalMass();
+ const btScalar itm=1/tm;
+ for( i=0;i<m_nodes.size();++i)
+ {
+ m_nodes[i].m_im/=itm*mass;
+ }
+ m_bUpdateRtCst=true;
+}
+
+//
+void btSoftBody::setTotalDensity(btScalar density)
+{
+ setTotalMass(getVolume()*density,true);
+}
+
+//
+void btSoftBody::transform(const btTransform& trs)
+{
+ const btScalar margin=getCollisionShape()->getMargin();
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_x=trs*n.m_x;
+ n.m_q=trs*n.m_q;
+ n.m_n=trs.getBasis()*n.m_n;
+ m_ndbvt.update(n.m_leaf,btDbvtVolume::FromCR(n.m_x,margin));
+ }
+ updateNormals();
+ updateBounds();
+ updateConstants();
+}
+
+//
+void btSoftBody::translate(const btVector3& trs)
+{
+btTransform t;
+t.setIdentity();
+t.setOrigin(trs);
+transform(t);
+}
+
+//
+void btSoftBody::rotate( const btQuaternion& rot)
+{
+btTransform t;
+t.setIdentity();
+t.setRotation(rot);
+transform(t);
+}
+
+//
+void btSoftBody::scale(const btVector3& scl)
+{
+ const btScalar margin=getCollisionShape()->getMargin();
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_x*=scl;
+ n.m_q*=scl;
+ m_ndbvt.update(n.m_leaf,btDbvtVolume::FromCR(n.m_x,margin));
+ }
+ updateNormals();
+ updateBounds();
+ updateConstants();
+}
+
+//
+void btSoftBody::setPose(bool bvolume,bool bframe)
+{
+ m_pose.m_bvolume = bvolume;
+ m_pose.m_bframe = bframe;
+ int i,ni;
+
+ /* Weights */
+ const btScalar omass=getTotalMass();
+ const btScalar kmass=omass*m_nodes.size()*1000;
+ btScalar tmass=omass;
+ m_pose.m_wgh.resize(m_nodes.size());
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ if(m_nodes[i].m_im<=0) tmass+=kmass;
+ }
+ for( i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ m_pose.m_wgh[i]= n.m_im>0 ?
+ 1/(m_nodes[i].m_im*tmass) :
+ kmass/tmass;
+ }
+ /* Pos */
+ const btVector3 com=evaluateCom();
+ m_pose.m_pos.resize(m_nodes.size());
+ for( i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ m_pose.m_pos[i]=m_nodes[i].m_x-com;
+ }
+ m_pose.m_volume = bvolume?getVolume():0;
+ m_pose.m_com = com;
+ m_pose.m_rot.setIdentity();
+ m_pose.m_scl.setIdentity();
+ /* Aqq */
+ m_pose.m_aqq[0] =
+ m_pose.m_aqq[1] =
+ m_pose.m_aqq[2] = btVector3(0,0,0);
+ for( i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ const btVector3& q=m_pose.m_pos[i];
+ const btVector3 mq=m_pose.m_wgh[i]*q;
+ m_pose.m_aqq[0]+=mq.x()*q;
+ m_pose.m_aqq[1]+=mq.y()*q;
+ m_pose.m_aqq[2]+=mq.z()*q;
+ }
+ m_pose.m_aqq=m_pose.m_aqq.inverse();
+ updateConstants();
+}
+
+//
+btScalar btSoftBody::getVolume() const
+{
+ btScalar vol=0;
+ if(m_nodes.size()>0)
+ {
+ int i,ni;
+
+ const btVector3 org=m_nodes[0].m_x;
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ const Face& f=m_faces[i];
+ vol+=dot(f.m_n[0]->m_x-org,cross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org));
+ }
+ vol/=(btScalar)6;
+ }
+ return(vol);
+}
+
+//
+int btSoftBody::clusterCount() const
+{
+return(m_clusters.size());
+}
+
+//
+btVector3 btSoftBody::clusterCom(const Cluster* cluster)
+{
+btVector3 com(0,0,0);
+for(int i=0,ni=cluster->m_nodes.size();i<ni;++i)
+ {
+ com+=cluster->m_nodes[i]->m_x*cluster->m_masses[i];
+ }
+return(com*cluster->m_imass);
+}
+
+//
+btVector3 btSoftBody::clusterCom(int cluster) const
+{
+return(clusterCom(m_clusters[cluster]));
+}
+
+//
+btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos)
+{
+return(cluster->m_lv+cross(cluster->m_av,rpos));
+}
+
+//
+void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
+{
+const btVector3 li=cluster->m_imass*impulse;
+const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
+cluster->m_vimpulses[0]+=li;cluster->m_lv+=li;
+cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
+cluster->m_nvimpulses++;
+}
+
+//
+void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse)
+{
+const btVector3 li=cluster->m_imass*impulse;
+const btVector3 ai=cluster->m_invwi*cross(rpos,impulse);
+cluster->m_dimpulses[0]+=li;
+cluster->m_dimpulses[1]+=ai;
+cluster->m_ndimpulses++;
+}
+
+//
+void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse)
+{
+if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity);
+if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift);
+}
+
+//
+void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse)
+{
+const btVector3 ai=cluster->m_invwi*impulse;
+cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai;
+cluster->m_nvimpulses++;
+}
+
+//
+void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse)
+{
+const btVector3 ai=cluster->m_invwi*impulse;
+cluster->m_dimpulses[1]+=ai;
+cluster->m_ndimpulses++;
+}
+
+//
+void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse)
+{
+if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity);
+if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift);
+}
+
+//
+void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse)
+{
+cluster->m_dimpulses[0]+=impulse*cluster->m_imass;
+cluster->m_ndimpulses++;
+}
+
+//
+int btSoftBody::generateBendingConstraints(int distance,Material* mat)
+{
+ int i,j;
+
+ if(distance>1)
+ {
+ /* Build graph */
+ const int n=m_nodes.size();
+ const unsigned inf=(~(unsigned)0)>>1;
+ unsigned* adj=new unsigned[n*n];
+#define IDX(_x_,_y_) ((_y_)*n+(_x_))
+ for(j=0;j<n;++j)
+ {
+ for(i=0;i<n;++i)
+ {
+ if(i!=j) adj[IDX(i,j)]=adj[IDX(j,i)]=inf;
+ else
+ adj[IDX(i,j)]=adj[IDX(j,i)]=0;
+ }
+ }
+ for( i=0;i<m_links.size();++i)
+ {
+ const int ia=(int)(m_links[i].m_n[0]-&m_nodes[0]);
+ const int ib=(int)(m_links[i].m_n[1]-&m_nodes[0]);
+ adj[IDX(ia,ib)]=1;
+ adj[IDX(ib,ia)]=1;
+ }
+ for(int k=0;k<n;++k)
+ {
+ for(j=0;j<n;++j)
+ {
+ for(i=j+1;i<n;++i)
+ {
+ const unsigned sum=adj[IDX(i,k)]+adj[IDX(k,j)];
+ if(adj[IDX(i,j)]>sum)
+ {
+ adj[IDX(i,j)]=adj[IDX(j,i)]=sum;
+ }
+ }
+ }
+ }
+ /* Build links */
+ int nlinks=0;
+ for(j=0;j<n;++j)
+ {
+ for(i=j+1;i<n;++i)
+ {
+ if(adj[IDX(i,j)]==(unsigned)distance)
+ {
+ appendLink(i,j,mat);
+ m_links[m_links.size()-1].m_bbending=1;
+ ++nlinks;
+ }
+ }
+ }
+ delete[] adj;
+ return(nlinks);
+ }
+ return(0);
+}
+
+//
+void btSoftBody::randomizeConstraints()
+{
+unsigned long seed=243703;
+#define NEXTRAND (seed=(1664525L*seed+1013904223L)&0xffffffff)
+int i,ni;
+
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ btSwap(m_links[i],m_links[NEXTRAND%ni]);
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ btSwap(m_faces[i],m_faces[NEXTRAND%ni]);
+ }
+#undef NEXTRAND
+}
+
+//
+int btSoftBody::generateClusters(int k,int maxiterations)
+{
+ int i;
+
+for(i=0;i<m_clusters.size();++i)
+ {
+ if(m_clusters[i]->m_leaf) m_cdbvt.remove(m_clusters[i]->m_leaf);
+ btAlignedFree(m_clusters[i]);
+ }
+m_clusters.resize(btMin(k,m_nodes.size()));
+
+
+
+for(i=0;i<m_clusters.size();++i)
+ {
+ m_clusters[i] = new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
+ m_clusters[i]->m_collide= true;
+ }
+k=m_clusters.size();
+if(k>0)
+ {
+ /* Initialize */
+ btAlignedObjectArray<btVector3> centers;
+ btVector3 cog(0,0,0);
+ int i;
+ for(i=0;i<m_nodes.size();++i)
+ {
+ cog+=m_nodes[i].m_x;
+ m_clusters[(i*29873)%m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
+ }
+ cog/=(btScalar)m_nodes.size();
+ centers.resize(k,cog);
+ /* Iterate */
+ const btScalar slope=16;
+ bool changed;
+ int iterations=0;
+ do {
+ const btScalar w=2-btMin<btScalar>(1,iterations/slope);
+ changed=false;
+ iterations++;
+ int i;
+
+ for(i=0;i<k;++i)
+ {
+ btVector3 c(0,0,0);
+ for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
+ {
+ c+=m_clusters[i]->m_nodes[j]->m_x;
+ }
+ if(m_clusters[i]->m_nodes.size())
+ {
+ c /= (btScalar)m_clusters[i]->m_nodes.size();
+ c = centers[i]+(c-centers[i])*w;
+ changed |= ((c-centers[i]).length2()>SIMD_EPSILON);
+ centers[i] = c;
+ m_clusters[i]->m_nodes.resize(0);
+ }
+ }
+ for(i=0;i<m_nodes.size();++i)
+ {
+ const btVector3 nx=m_nodes[i].m_x;
+ int kbest=0;
+ btScalar kdist=ClusterMetric(centers[0],nx);
+ for(int j=1;j<k;++j)
+ {
+ const btScalar d=ClusterMetric(centers[j],nx);
+ if(d<kdist)
+ {
+ kbest=j;
+ kdist=d;
+ }
+ }
+ m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
+ }
+ } while(changed&&(iterations<maxiterations));
+ /* Merge */
+ btAlignedObjectArray<int> cids;
+ cids.resize(m_nodes.size(),-1);
+ for(i=0;i<m_clusters.size();++i)
+ {
+ for(int j=0;j<m_clusters[i]->m_nodes.size();++j)
+ {
+ cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i;
+ }
+ }
+ for(i=0;i<m_faces.size();++i)
+ {
+ const int idx[]={ int(m_faces[i].m_n[0]-&m_nodes[0]),
+ int(m_faces[i].m_n[1]-&m_nodes[0]),
+ int(m_faces[i].m_n[2]-&m_nodes[0])};
+ for(int j=0;j<3;++j)
+ {
+ const int cid=cids[idx[j]];
+ for(int q=1;q<3;++q)
+ {
+ const int kid=idx[(j+q)%3];
+ if(cids[kid]!=cid)
+ {
+ if(m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size())
+ {
+ m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
+ }
+ }
+ }
+ }
+ }
+ /* Master */
+ if(m_clusters.size()>1)
+ {
+ Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster();
+ pmaster->m_collide = false;
+ pmaster->m_nodes.reserve(m_nodes.size());
+ for(int i=0;i<m_nodes.size();++i) pmaster->m_nodes.push_back(&m_nodes[i]);
+ m_clusters.push_back(pmaster);
+ btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]);
+ }
+ /* Terminate */
+ for(i=0;i<m_clusters.size();++i)
+ {
+ if(m_clusters[i]->m_nodes.size()==0)
+ {
+ btAlignedFree(m_clusters[i]);
+ btSwap(m_clusters[i],m_clusters[m_clusters.size()-1]);
+ m_clusters.pop_back();
+ --i;
+ }
+ }
+
+ initializeClusters();
+ updateClusters();
+ return(m_clusters.size());
+ }
+return(0);
+}
+
+//
+void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut)
+{
+const Node* nbase = &m_nodes[0];
+int ncount = m_nodes.size();
+btSymMatrix<int> edges(ncount,-2);
+int newnodes=0;
+int i,j,k,ni;
+
+/* Filter out */
+for(i=0;i<m_links.size();++i)
+ {
+ Link& l=m_links[i];
+ if(l.m_bbending)
+ {
+ if(!SameSign(ifn->Eval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x)))
+ {
+ btSwap(m_links[i],m_links[m_links.size()-1]);
+ m_links.pop_back();--i;
+ }
+ }
+ }
+/* Fill edges */
+for(i=0;i<m_links.size();++i)
+ {
+ Link& l=m_links[i];
+ edges(int(l.m_n[0]-nbase),int(l.m_n[1]-nbase))=-1;
+ }
+for(i=0;i<m_faces.size();++i)
+ {
+ Face& f=m_faces[i];
+ edges(int(f.m_n[0]-nbase),int(f.m_n[1]-nbase))=-1;
+ edges(int(f.m_n[1]-nbase),int(f.m_n[2]-nbase))=-1;
+ edges(int(f.m_n[2]-nbase),int(f.m_n[0]-nbase))=-1;
+ }
+/* Intersect */
+for(i=0;i<ncount;++i)
+ {
+ for(j=i+1;j<ncount;++j)
+ {
+ if(edges(i,j)==-1)
+ {
+ Node& a=m_nodes[i];
+ Node& b=m_nodes[j];
+ const btScalar t=ImplicitSolve(ifn,a.m_x,b.m_x,accurary);
+ if(t>0)
+ {
+ const btVector3 x=Lerp(a.m_x,b.m_x,t);
+ const btVector3 v=Lerp(a.m_v,b.m_v,t);
+ btScalar m=0;
+ if(a.m_im>0)
+ {
+ if(b.m_im>0)
+ {
+ const btScalar ma=1/a.m_im;
+ const btScalar mb=1/b.m_im;
+ const btScalar mc=Lerp(ma,mb,t);
+ const btScalar f=(ma+mb)/(ma+mb+mc);
+ a.m_im=1/(ma*f);
+ b.m_im=1/(mb*f);
+ m=mc*f;
+ }
+ else
+ { a.m_im/=0.5;m=1/a.m_im; }
+ }
+ else
+ {
+ if(b.m_im>0)
+ { b.m_im/=0.5;m=1/b.m_im; }
+ else
+ m=0;
+ }
+ appendNode(x,m);
+ edges(i,j)=m_nodes.size()-1;
+ m_nodes[edges(i,j)].m_v=v;
+ ++newnodes;
+ }
+ }
+ }
+ }
+nbase=&m_nodes[0];
+/* Refine links */
+for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ Link& feat=m_links[i];
+ const int idx[]={ int(feat.m_n[0]-nbase),
+ int(feat.m_n[1]-nbase)};
+ if((idx[0]<ncount)&&(idx[1]<ncount))
+ {
+ const int ni=edges(idx[0],idx[1]);
+ if(ni>0)
+ {
+ appendLink(i);
+ Link* pft[]={ &m_links[i],
+ &m_links[m_links.size()-1]};
+ pft[0]->m_n[0]=&m_nodes[idx[0]];
+ pft[0]->m_n[1]=&m_nodes[ni];
+ pft[1]->m_n[0]=&m_nodes[ni];
+ pft[1]->m_n[1]=&m_nodes[idx[1]];
+ }
+ }
+ }
+/* Refine faces */
+for(i=0;i<m_faces.size();++i)
+ {
+ const Face& feat=m_faces[i];
+ const int idx[]={ int(feat.m_n[0]-nbase),
+ int(feat.m_n[1]-nbase),
+ int(feat.m_n[2]-nbase)};
+ for(j=2,k=0;k<3;j=k++)
+ {
+ if((idx[j]<ncount)&&(idx[k]<ncount))
+ {
+ const int ni=edges(idx[j],idx[k]);
+ if(ni>0)
+ {
+ appendFace(i);
+ const int l=(k+1)%3;
+ Face* pft[]={ &m_faces[i],
+ &m_faces[m_faces.size()-1]};
+ pft[0]->m_n[0]=&m_nodes[idx[l]];
+ pft[0]->m_n[1]=&m_nodes[idx[j]];
+ pft[0]->m_n[2]=&m_nodes[ni];
+ pft[1]->m_n[0]=&m_nodes[ni];
+ pft[1]->m_n[1]=&m_nodes[idx[k]];
+ pft[1]->m_n[2]=&m_nodes[idx[l]];
+ appendLink(ni,idx[l],pft[0]->m_material);
+ --i;break;
+ }
+ }
+ }
+ }
+/* Cut */
+if(cut)
+ {
+ btAlignedObjectArray<int> cnodes;
+ const int pcount=ncount;
+ int i;
+ ncount=m_nodes.size();
+ cnodes.resize(ncount,0);
+ /* Nodes */
+ for(i=0;i<ncount;++i)
+ {
+ const btVector3 x=m_nodes[i].m_x;
+ if((i>=pcount)||(btFabs(ifn->Eval(x))<accurary))
+ {
+ const btVector3 v=m_nodes[i].m_v;
+ btScalar m=getMass(i);
+ if(m>0) { m*=0.5;m_nodes[i].m_im/=0.5; }
+ appendNode(x,m);
+ cnodes[i]=m_nodes.size()-1;
+ m_nodes[cnodes[i]].m_v=v;
+ }
+ }
+ nbase=&m_nodes[0];
+ /* Links */
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ const int id[]={ int(m_links[i].m_n[0]-nbase),
+ int(m_links[i].m_n[1]-nbase)};
+ int todetach=0;
+ if(cnodes[id[0]]&&cnodes[id[1]])
+ {
+ appendLink(i);
+ todetach=m_links.size()-1;
+ }
+ else
+ {
+ if(( (ifn->Eval(m_nodes[id[0]].m_x)<accurary)&&
+ (ifn->Eval(m_nodes[id[1]].m_x)<accurary)))
+ todetach=i;
+ }
+ if(todetach)
+ {
+ Link& l=m_links[todetach];
+ for(int j=0;j<2;++j)
+ {
+ int cn=cnodes[int(l.m_n[j]-nbase)];
+ if(cn) l.m_n[j]=&m_nodes[cn];
+ }
+ }
+ }
+ /* Faces */
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ Node** n= m_faces[i].m_n;
+ if( (ifn->Eval(n[0]->m_x)<accurary)&&
+ (ifn->Eval(n[1]->m_x)<accurary)&&
+ (ifn->Eval(n[2]->m_x)<accurary))
+ {
+ for(int j=0;j<3;++j)
+ {
+ int cn=cnodes[int(n[j]-nbase)];
+ if(cn) n[j]=&m_nodes[cn];
+ }
+ }
+ }
+ /* Clean orphans */
+ int nnodes=m_nodes.size();
+ btAlignedObjectArray<int> ranks;
+ btAlignedObjectArray<int> todelete;
+ ranks.resize(nnodes,0);
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ for(int j=0;j<2;++j) ranks[int(m_links[i].m_n[j]-nbase)]++;
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ for(int j=0;j<3;++j) ranks[int(m_faces[i].m_n[j]-nbase)]++;
+ }
+ for(i=0;i<m_links.size();++i)
+ {
+ const int id[]={ int(m_links[i].m_n[0]-nbase),
+ int(m_links[i].m_n[1]-nbase)};
+ const bool sg[]={ ranks[id[0]]==1,
+ ranks[id[1]]==1};
+ if(sg[0]||sg[1])
+ {
+ --ranks[id[0]];
+ --ranks[id[1]];
+ btSwap(m_links[i],m_links[m_links.size()-1]);
+ m_links.pop_back();--i;
+ }
+ }
+ #if 0
+ for(i=nnodes-1;i>=0;--i)
+ {
+ if(!ranks[i]) todelete.push_back(i);
+ }
+ if(todelete.size())
+ {
+ btAlignedObjectArray<int>& map=ranks;
+ for(int i=0;i<nnodes;++i) map[i]=i;
+ PointersToIndices(this);
+ for(int i=0,ni=todelete.size();i<ni;++i)
+ {
+ int j=todelete[i];
+ int& a=map[j];
+ int& b=map[--nnodes];
+ m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
+ btSwap(m_nodes[a],m_nodes[b]);
+ j=a;a=b;b=j;
+ }
+ IndicesToPointers(this,&map[0]);
+ m_nodes.resize(nnodes);
+ }
+ #endif
+ }
+m_bUpdateRtCst=true;
+}
+
+//
+bool btSoftBody::cutLink(const Node* node0,const Node* node1,btScalar position)
+{
+return(cutLink(int(node0-&m_nodes[0]),int(node1-&m_nodes[0]),position));
+}
+
+//
+bool btSoftBody::cutLink(int node0,int node1,btScalar position)
+{
+bool done=false;
+int i,ni;
+const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
+const btVector3 x=Lerp(m_nodes[node0].m_x,m_nodes[node1].m_x,position);
+const btVector3 v=Lerp(m_nodes[node0].m_v,m_nodes[node1].m_v,position);
+const btScalar m=1;
+appendNode(x,m);
+appendNode(x,m);
+Node* pa=&m_nodes[node0];
+Node* pb=&m_nodes[node1];
+Node* pn[2]={ &m_nodes[m_nodes.size()-2],
+ &m_nodes[m_nodes.size()-1]};
+pn[0]->m_v=v;
+pn[1]->m_v=v;
+for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ const int mtch=MatchEdge(m_links[i].m_n[0],m_links[i].m_n[1],pa,pb);
+ if(mtch!=-1)
+ {
+ appendLink(i);
+ Link* pft[]={&m_links[i],&m_links[m_links.size()-1]};
+ pft[0]->m_n[1]=pn[mtch];
+ pft[1]->m_n[0]=pn[1-mtch];
+ done=true;
+ }
+ }
+for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ for(int k=2,l=0;l<3;k=l++)
+ {
+ const int mtch=MatchEdge(m_faces[i].m_n[k],m_faces[i].m_n[l],pa,pb);
+ if(mtch!=-1)
+ {
+ appendFace(i);
+ Face* pft[]={&m_faces[i],&m_faces[m_faces.size()-1]};
+ pft[0]->m_n[l]=pn[mtch];
+ pft[1]->m_n[k]=pn[1-mtch];
+ appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
+ appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true);
+ }
+ }
+ }
+if(!done)
+ {
+ m_ndbvt.remove(pn[0]->m_leaf);
+ m_ndbvt.remove(pn[1]->m_leaf);
+ m_nodes.pop_back();
+ m_nodes.pop_back();
+ }
+return(done);
+}
+
+//
+bool btSoftBody::rayCast(const btVector3& org,
+ const btVector3& dir,
+ sRayCast& results,
+ btScalar maxtime)
+{
+if(m_faces.size()&&m_fdbvt.empty()) initializeFaceTree();
+results.body = this;
+results.time = maxtime;
+results.feature = eFeature::None;
+results.index = -1;
+return(rayCast(org,dir,results.time,results.feature,results.index,false)!=0);
+}
+
+//
+void btSoftBody::setSolver(eSolverPresets::_ preset)
+{
+m_cfg.m_vsequence.clear();
+m_cfg.m_psequence.clear();
+m_cfg.m_dsequence.clear();
+switch(preset)
+ {
+ case eSolverPresets::Positions:
+ m_cfg.m_psequence.push_back(ePSolver::Anchors);
+ m_cfg.m_psequence.push_back(ePSolver::RContacts);
+ m_cfg.m_psequence.push_back(ePSolver::SContacts);
+ m_cfg.m_psequence.push_back(ePSolver::Linear);
+ break;
+ case eSolverPresets::Velocities:
+ m_cfg.m_vsequence.push_back(eVSolver::Linear);
+
+ m_cfg.m_psequence.push_back(ePSolver::Anchors);
+ m_cfg.m_psequence.push_back(ePSolver::RContacts);
+ m_cfg.m_psequence.push_back(ePSolver::SContacts);
+
+ m_cfg.m_dsequence.push_back(ePSolver::Linear);
+ break;
+ }
+}
+
+//
+void btSoftBody::predictMotion(btScalar dt)
+{
+ int i,ni;
+
+ /* Update */
+ if(m_bUpdateRtCst)
+ {
+ m_bUpdateRtCst=false;
+ updateConstants();
+ m_fdbvt.clear();
+ if(m_cfg.collisions&fCollision::VF_SS)
+ {
+ initializeFaceTree();
+ }
+ }
+
+ /* Prepare */
+ m_sst.sdt = dt*m_cfg.timescale;
+ m_sst.isdt = 1/m_sst.sdt;
+ m_sst.velmrg = m_sst.sdt*3;
+ m_sst.radmrg = getCollisionShape()->getMargin();
+ m_sst.updmrg = m_sst.radmrg*(btScalar)0.25;
+ /* Forces */
+ addVelocity(m_worldInfo->m_gravity*m_sst.sdt);
+ applyForces();
+ /* Integrate */
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_q = n.m_x;
+ n.m_v += n.m_f*n.m_im*m_sst.sdt;
+ n.m_x += n.m_v*m_sst.sdt;
+ n.m_f = btVector3(0,0,0);
+ }
+ /* Clusters */
+ updateClusters();
+ /* Bounds */
+ updateBounds();
+ /* Nodes */
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ m_ndbvt.update( n.m_leaf,
+ btDbvtVolume::FromCR(n.m_x,m_sst.radmrg),
+ n.m_v*m_sst.velmrg,
+ m_sst.updmrg);
+ }
+ /* Faces */
+ if(!m_fdbvt.empty())
+ {
+ for(int i=0;i<m_faces.size();++i)
+ {
+ Face& f=m_faces[i];
+ const btVector3 v=( f.m_n[0]->m_v+
+ f.m_n[1]->m_v+
+ f.m_n[2]->m_v)/3;
+ m_fdbvt.update( f.m_leaf,
+ VolumeOf(f,m_sst.radmrg),
+ v*m_sst.velmrg,
+ m_sst.updmrg);
+ }
+ }
+ /* Pose */
+ updatePose();
+ /* Match */
+ if(m_pose.m_bframe&&(m_cfg.kMT>0))
+ {
+ const btMatrix3x3 posetrs=m_pose.m_rot;
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ if(n.m_im>0)
+ {
+ const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com;
+ n.m_x=Lerp(n.m_x,x,m_cfg.kMT);
+ }
+ }
+ }
+ /* Clear contacts */
+ m_rcontacts.resize(0);
+ m_scontacts.resize(0);
+ /* Optimize dbvt's */
+ m_ndbvt.optimizeIncremental(1);
+ m_fdbvt.optimizeIncremental(1);
+ m_cdbvt.optimizeIncremental(1);
+}
+
+//
+void btSoftBody::solveConstraints()
+{
+/* Apply clusters */
+applyClusters(false);
+/* Prepare links */
+
+int i,ni;
+
+for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ Link& l=m_links[i];
+ l.m_c3 = l.m_n[1]->m_q-l.m_n[0]->m_q;
+ l.m_c2 = 1/(l.m_c3.length2()*l.m_c0);
+ }
+/* Prepare anchors */
+for(i=0,ni=m_anchors.size();i<ni;++i)
+ {
+ Anchor& a=m_anchors[i];
+ const btVector3 ra=a.m_body->getWorldTransform().getBasis()*a.m_local;
+ a.m_c0 = ImpulseMatrix( m_sst.sdt,
+ a.m_node->m_im,
+ a.m_body->getInvMass(),
+ a.m_body->getInvInertiaTensorWorld(),
+ ra);
+ a.m_c1 = ra;
+ a.m_c2 = m_sst.sdt*a.m_node->m_im;
+ a.m_body->activate();
+ }
+/* Solve velocities */
+if(m_cfg.viterations>0)
+ {
+ /* Solve */
+ for(int isolve=0;isolve<m_cfg.viterations;++isolve)
+ {
+ for(int iseq=0;iseq<m_cfg.m_vsequence.size();++iseq)
+ {
+ getSolver(m_cfg.m_vsequence[iseq])(this,1);
+ }
+ }
+ /* Update */
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_x = n.m_q+n.m_v*m_sst.sdt;
+ }
+ }
+/* Solve positions */
+if(m_cfg.piterations>0)
+ {
+ for(int isolve=0;isolve<m_cfg.piterations;++isolve)
+ {
+ const btScalar ti=isolve/(btScalar)m_cfg.piterations;
+ for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
+ {
+ getSolver(m_cfg.m_psequence[iseq])(this,1,ti);
+ }
+ }
+ const btScalar vc=m_sst.isdt*(1-m_cfg.kDP);
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_v = (n.m_x-n.m_q)*vc;
+ n.m_f = btVector3(0,0,0);
+ }
+ }
+/* Solve drift */
+if(m_cfg.diterations>0)
+ {
+ const btScalar vcf=m_cfg.kVCF*m_sst.isdt;
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_q = n.m_x;
+ }
+ for(int idrift=0;idrift<m_cfg.diterations;++idrift)
+ {
+ for(int iseq=0;iseq<m_cfg.m_dsequence.size();++iseq)
+ {
+ getSolver(m_cfg.m_dsequence[iseq])(this,1,0);
+ }
+ }
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ Node& n=m_nodes[i];
+ n.m_v += (n.m_x-n.m_q)*vcf;
+ }
+ }
+/* Apply clusters */
+dampClusters();
+applyClusters(true);
+}
+
+//
+void btSoftBody::staticSolve(int iterations)
+{
+for(int isolve=0;isolve<iterations;++isolve)
+ {
+ for(int iseq=0;iseq<m_cfg.m_psequence.size();++iseq)
+ {
+ getSolver(m_cfg.m_psequence[iseq])(this,1,0);
+ }
+ }
+}
+
+//
+void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/,int /*count*/,int /*iterations*/)
+{
+/// placeholder
+}
+
+//
+void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
+{
+const int nb=bodies.size();
+int iterations=0;
+int i;
+
+for(i=0;i<nb;++i)
+ {
+ iterations=btMax(iterations,bodies[i]->m_cfg.citerations);
+ }
+for(i=0;i<nb;++i)
+ {
+ bodies[i]->prepareClusters(iterations);
+ }
+for(i=0;i<iterations;++i)
+ {
+ const btScalar sor=1;
+ for(int j=0;j<nb;++j)
+ {
+ bodies[j]->solveClusters(sor);
+ }
+ }
+for(i=0;i<nb;++i)
+ {
+ bodies[i]->cleanupClusters();
+ }
+}
+
+//
+void btSoftBody::integrateMotion()
+{
+ /* Update */
+ updateNormals();
+}
+
+//
+ btSoftBody::RayCaster::RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt)
+{
+o = org;
+d = dir;
+mint = mxt;
+face = 0;
+tests = 0;
+}
+
+//
+void btSoftBody::RayCaster::Process(const btDbvtNode* leaf)
+{
+btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data;
+const btScalar t=rayTriangle( o,d,
+ f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x,
+ mint);
+if((t>0)&&(t<mint)) { mint=t;face=&f; }
+++tests;
+}
+
+//
+btScalar btSoftBody::RayCaster::rayTriangle( const btVector3& org,
+ const btVector3& dir,
+ const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btScalar maxt)
+{
+ static const btScalar ceps=-SIMD_EPSILON*10;
+ static const btScalar teps=SIMD_EPSILON*10;
+ const btVector3 n=cross(b-a,c-a);
+ const btScalar d=dot(a,n);
+ const btScalar den=dot(dir,n);
+ if(!btFuzzyZero(den))
+ {
+ const btScalar num=dot(org,n)-d;
+ const btScalar t=-num/den;
+ if((t>teps)&&(t<maxt))
+ {
+ const btVector3 hit=org+dir*t;
+ if( (dot(n,cross(a-hit,b-hit))>ceps) &&
+ (dot(n,cross(b-hit,c-hit))>ceps) &&
+ (dot(n,cross(c-hit,a-hit))>ceps))
+ {
+ return(t);
+ }
+ }
+ }
+ return(-1);
+}
+
+//
+void btSoftBody::pointersToIndices()
+{
+#define PTR2IDX(_p_,_b_) reinterpret_cast<btSoftBody::Node*>((_p_)-(_b_))
+ btSoftBody::Node* base=&m_nodes[0];
+ int i,ni;
+
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ if(m_nodes[i].m_leaf)
+ {
+ m_nodes[i].m_leaf->data=*(void**)&i;
+ }
+ }
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ m_links[i].m_n[0]=PTR2IDX(m_links[i].m_n[0],base);
+ m_links[i].m_n[1]=PTR2IDX(m_links[i].m_n[1],base);
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ m_faces[i].m_n[0]=PTR2IDX(m_faces[i].m_n[0],base);
+ m_faces[i].m_n[1]=PTR2IDX(m_faces[i].m_n[1],base);
+ m_faces[i].m_n[2]=PTR2IDX(m_faces[i].m_n[2],base);
+ if(m_faces[i].m_leaf)
+ {
+ m_faces[i].m_leaf->data=*(void**)&i;
+ }
+ }
+ for(i=0,ni=m_anchors.size();i<ni;++i)
+ {
+ m_anchors[i].m_node=PTR2IDX(m_anchors[i].m_node,base);
+ }
+ for(i=0,ni=m_notes.size();i<ni;++i)
+ {
+ for(int j=0;j<m_notes[i].m_rank;++j)
+ {
+ m_notes[i].m_nodes[j]=PTR2IDX(m_notes[i].m_nodes[j],base);
+ }
+ }
+#undef PTR2IDX
+}
+
+//
+void btSoftBody::indicesToPointers(const int* map)
+{
+#define IDX2PTR(_p_,_b_) map?(&(_b_)[map[(((char*)_p_)-(char*)0)]]): \
+ (&(_b_)[(((char*)_p_)-(char*)0)])
+ btSoftBody::Node* base=&m_nodes[0];
+ int i,ni;
+
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ if(m_nodes[i].m_leaf)
+ {
+ m_nodes[i].m_leaf->data=&m_nodes[i];
+ }
+ }
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ m_links[i].m_n[0]=IDX2PTR(m_links[i].m_n[0],base);
+ m_links[i].m_n[1]=IDX2PTR(m_links[i].m_n[1],base);
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ m_faces[i].m_n[0]=IDX2PTR(m_faces[i].m_n[0],base);
+ m_faces[i].m_n[1]=IDX2PTR(m_faces[i].m_n[1],base);
+ m_faces[i].m_n[2]=IDX2PTR(m_faces[i].m_n[2],base);
+ if(m_faces[i].m_leaf)
+ {
+ m_faces[i].m_leaf->data=&m_faces[i];
+ }
+ }
+ for(i=0,ni=m_anchors.size();i<ni;++i)
+ {
+ m_anchors[i].m_node=IDX2PTR(m_anchors[i].m_node,base);
+ }
+ for(i=0,ni=m_notes.size();i<ni;++i)
+ {
+ for(int j=0;j<m_notes[i].m_rank;++j)
+ {
+ m_notes[i].m_nodes[j]=IDX2PTR(m_notes[i].m_nodes[j],base);
+ }
+ }
+#undef IDX2PTR
+}
+
+//
+int btSoftBody::rayCast(const btVector3& org,const btVector3& dir,
+ btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const
+{
+ int cnt=0;
+ if(bcountonly||m_fdbvt.empty())
+ {/* Full search */
+ for(int i=0,ni=m_faces.size();i<ni;++i)
+ {
+ const btSoftBody::Face& f=m_faces[i];
+ const btScalar t=RayCaster::rayTriangle( org,dir,
+ f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x,
+ mint);
+ if(t>0)
+ {
+ ++cnt;
+ if(!bcountonly)
+ {
+ feature=btSoftBody::eFeature::Face;
+ index=i;
+ mint=t;
+ }
+ }
+ }
+ }
+ else
+ {/* Use dbvt */
+ RayCaster collider(org,dir,mint);
+ btDbvt::collideRAY(m_fdbvt.m_root,org,dir,collider);
+ if(collider.face)
+ {
+ mint=collider.mint;
+ feature=btSoftBody::eFeature::Face;
+ index=(int)(collider.face-&m_faces[0]);
+ cnt=1;
+ }
+ }
+ return(cnt);
+}
+
+//
+void btSoftBody::initializeFaceTree()
+{
+m_fdbvt.clear();
+for(int i=0;i<m_faces.size();++i)
+ {
+ Face& f=m_faces[i];
+ f.m_leaf=m_fdbvt.insert(VolumeOf(f,0),&f);
+ }
+}
+
+//
+btVector3 btSoftBody::evaluateCom() const
+{
+btVector3 com(0,0,0);
+if(m_pose.m_bframe)
+ {
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ com+=m_nodes[i].m_x*m_pose.m_wgh[i];
+ }
+ }
+ return(com);
+}
+
+//
+bool btSoftBody::checkContact( btRigidBody* prb,
+ const btVector3& x,
+ btScalar margin,
+ btSoftBody::sCti& cti) const
+{
+ btVector3 nrm;
+ btCollisionShape* shp=prb->getCollisionShape();
+ const btTransform& wtr=prb->getInterpolationWorldTransform();
+ btScalar dst=m_worldInfo->m_sparsesdf.Evaluate( wtr.invXform(x),
+ shp,
+ nrm,
+ margin);
+ if(dst<0)
+ {
+ cti.m_body = prb;
+ cti.m_normal = wtr.getBasis()*nrm;
+ cti.m_offset = -dot( cti.m_normal,
+ x-cti.m_normal*dst);
+ return(true);
+ }
+ return(false);
+}
+
+//
+void btSoftBody::updateNormals()
+{
+ const btVector3 zv(0,0,0);
+ int i,ni;
+
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ m_nodes[i].m_n=zv;
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ btSoftBody::Face& f=m_faces[i];
+ const btVector3 n=cross(f.m_n[1]->m_x-f.m_n[0]->m_x,
+ f.m_n[2]->m_x-f.m_n[0]->m_x);
+ f.m_normal=n.normalized();
+ f.m_n[0]->m_n+=n;
+ f.m_n[1]->m_n+=n;
+ f.m_n[2]->m_n+=n;
+ }
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ btScalar len = m_nodes[i].m_n.length();
+ if (len>SIMD_EPSILON)
+ m_nodes[i].m_n /= len;
+ }
+}
+
+//
+void btSoftBody::updateBounds()
+{
+ if(m_ndbvt.m_root)
+ {
+ const btVector3& mins=m_ndbvt.m_root->volume.Mins();
+ const btVector3& maxs=m_ndbvt.m_root->volume.Maxs();
+ const btScalar csm=getCollisionShape()->getMargin();
+ const btVector3 mrg=btVector3( csm,
+ csm,
+ csm)*1; // ??? to investigate...
+ m_bounds[0]=mins-mrg;
+ m_bounds[1]=maxs+mrg;
+ if(0!=getBroadphaseHandle())
+ {
+ m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(),
+ m_bounds[0],
+ m_bounds[1],
+ m_worldInfo->m_dispatcher);
+ }
+ }
+ else
+ {
+ m_bounds[0]=
+ m_bounds[1]=btVector3(0,0,0);
+ }
+}
+
+
+//
+void btSoftBody::updatePose()
+{
+ if(m_pose.m_bframe)
+ {
+ btSoftBody::Pose& pose=m_pose;
+ const btVector3 com=evaluateCom();
+ /* Com */
+ pose.m_com = com;
+ /* Rotation */
+ btMatrix3x3 Apq;
+ const btScalar eps=SIMD_EPSILON;
+ Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0);
+ Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3);
+ for(int i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ const btVector3 a=pose.m_wgh[i]*(m_nodes[i].m_x-com);
+ const btVector3& b=pose.m_pos[i];
+ Apq[0]+=a.x()*b;
+ Apq[1]+=a.y()*b;
+ Apq[2]+=a.z()*b;
+ }
+ btMatrix3x3 r,s;
+ PolarDecompose(Apq,r,s);
+ pose.m_rot=r;
+ pose.m_scl=pose.m_aqq*r.transpose()*Apq;
+ if(m_cfg.maxvolume>1)
+ {
+ const btScalar idet=Clamp<btScalar>( 1/pose.m_scl.determinant(),
+ 1,m_cfg.maxvolume);
+ pose.m_scl=Mul(pose.m_scl,idet);
+ }
+
+ }
+}
+
+//
+void btSoftBody::updateConstants()
+{
+ int i,ni;
+
+ /* Links */
+ for(i=0,ni=m_links.size();i<ni;++i)
+ {
+ Link& l=m_links[i];
+ Material& m=*l.m_material;
+ l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length();
+ l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST;
+ l.m_c1 = l.m_rl*l.m_rl;
+ }
+ /* Faces */
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ Face& f=m_faces[i];
+ f.m_ra = AreaOf(f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x);
+ }
+ /* Area's */
+ btAlignedObjectArray<int> counts;
+ counts.resize(m_nodes.size(),0);
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ m_nodes[i].m_area = 0;
+ }
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ btSoftBody::Face& f=m_faces[i];
+ for(int j=0;j<3;++j)
+ {
+ const int index=(int)(f.m_n[j]-&m_nodes[0]);
+ counts[index]++;
+ f.m_n[j]->m_area+=btFabs(f.m_ra);
+ }
+ }
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ if(counts[i]>0)
+ m_nodes[i].m_area/=(btScalar)counts[i];
+ else
+ m_nodes[i].m_area=0;
+ }
+}
+
+//
+void btSoftBody::initializeClusters()
+{
+ int i;
+
+for( i=0;i<m_clusters.size();++i)
+ {
+ Cluster& c=*m_clusters[i];
+ c.m_imass=0;
+ c.m_masses.resize(c.m_nodes.size());
+ for(int j=0;j<c.m_nodes.size();++j)
+ {
+ c.m_masses[j] = c.m_nodes[j]->m_im>0?1/c.m_nodes[j]->m_im:0;
+ c.m_imass += c.m_masses[j];
+ }
+ c.m_imass = 1/c.m_imass;
+ c.m_com = btSoftBody::clusterCom(&c);
+ c.m_lv = btVector3(0,0,0);
+ c.m_av = btVector3(0,0,0);
+ c.m_leaf = 0;
+ /* Inertia */
+ btMatrix3x3& ii=c.m_locii;
+ ii[0]=ii[1]=ii[2]=btVector3(0,0,0);
+ {
+ int i,ni;
+
+ for(i=0,ni=c.m_nodes.size();i<ni;++i)
+ {
+ const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
+ const btVector3 q=k*k;
+ const btScalar m=c.m_masses[i];
+ ii[0][0] += m*(q[1]+q[2]);
+ ii[1][1] += m*(q[0]+q[2]);
+ ii[2][2] += m*(q[0]+q[1]);
+ ii[0][1] -= m*k[0]*k[1];
+ ii[0][2] -= m*k[0]*k[2];
+ ii[1][2] -= m*k[1]*k[2];
+ }
+ }
+ ii[1][0]=ii[0][1];
+ ii[2][0]=ii[0][2];
+ ii[2][1]=ii[1][2];
+ ii=ii.inverse();
+ /* Frame */
+ c.m_framexform.setIdentity();
+ c.m_framexform.setOrigin(c.m_com);
+ c.m_framerefs.resize(c.m_nodes.size());
+ {
+ int i;
+ for(i=0;i<c.m_framerefs.size();++i)
+ {
+ c.m_framerefs[i]=c.m_nodes[i]->m_x-c.m_com;
+ }
+ }
+ }
+}
+
+//
+void btSoftBody::updateClusters()
+{
+BT_PROFILE("UpdateClusters");
+int i;
+
+for(i=0;i<m_clusters.size();++i)
+ {
+ btSoftBody::Cluster& c=*m_clusters[i];
+ const int n=c.m_nodes.size();
+ const btScalar invn=1/(btScalar)n;
+ if(n)
+ {
+ /* Frame */
+ const btScalar eps=btScalar(0.0001);
+ btMatrix3x3 m,r,s;
+ m[0]=m[1]=m[2]=btVector3(0,0,0);
+ m[0][0]=eps*1;
+ m[1][1]=eps*2;
+ m[2][2]=eps*3;
+ c.m_com=clusterCom(&c);
+ for(int i=0;i<c.m_nodes.size();++i)
+ {
+ const btVector3 a=c.m_nodes[i]->m_x-c.m_com;
+ const btVector3& b=c.m_framerefs[i];
+ m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b;
+ }
+ PolarDecompose(m,r,s);
+ c.m_framexform.setOrigin(c.m_com);
+ c.m_framexform.setBasis(r);
+ /* Inertia */
+ #if 1/* Constant */
+ c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose();
+ #else
+ #if 0/* Sphere */
+ const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
+ const btVector3 inertia(rk,rk,rk);
+ const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
+ btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
+ btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
+
+ c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
+ #else/* Actual */
+ c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0);
+ for(int i=0;i<n;++i)
+ {
+ const btVector3 k=c.m_nodes[i]->m_x-c.m_com;
+ const btVector3 q=k*k;
+ const btScalar m=1/c.m_nodes[i]->m_im;
+ c.m_invwi[0][0] += m*(q[1]+q[2]);
+ c.m_invwi[1][1] += m*(q[0]+q[2]);
+ c.m_invwi[2][2] += m*(q[0]+q[1]);
+ c.m_invwi[0][1] -= m*k[0]*k[1];
+ c.m_invwi[0][2] -= m*k[0]*k[2];
+ c.m_invwi[1][2] -= m*k[1]*k[2];
+ }
+ c.m_invwi[1][0]=c.m_invwi[0][1];
+ c.m_invwi[2][0]=c.m_invwi[0][2];
+ c.m_invwi[2][1]=c.m_invwi[1][2];
+ c.m_invwi=c.m_invwi.inverse();
+ #endif
+ #endif
+ /* Velocities */
+ c.m_lv=btVector3(0,0,0);
+ c.m_av=btVector3(0,0,0);
+ {
+ int i;
+
+ for(i=0;i<n;++i)
+ {
+ const btVector3 v=c.m_nodes[i]->m_v*c.m_masses[i];
+ c.m_lv += v;
+ c.m_av += cross(c.m_nodes[i]->m_x-c.m_com,v);
+ }
+ }
+ c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping);
+ c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping);
+ c.m_vimpulses[0] =
+ c.m_vimpulses[1] = btVector3(0,0,0);
+ c.m_dimpulses[0] =
+ c.m_dimpulses[1] = btVector3(0,0,0);
+ c.m_nvimpulses = 0;
+ c.m_ndimpulses = 0;
+ /* Matching */
+ if(c.m_matching>0)
+ {
+ for(int j=0;j<c.m_nodes.size();++j)
+ {
+ Node& n=*c.m_nodes[j];
+ const btVector3 x=c.m_framexform*c.m_framerefs[j];
+ n.m_x=Lerp(n.m_x,x,c.m_matching);
+ }
+ }
+ /* Dbvt */
+ if(c.m_collide)
+ {
+ btVector3 mi=c.m_nodes[0]->m_x;
+ btVector3 mx=mi;
+ for(int j=1;j<n;++j)
+ {
+ mi.setMin(c.m_nodes[j]->m_x);
+ mx.setMax(c.m_nodes[j]->m_x);
+ }
+ const btDbvtVolume bounds=btDbvtVolume::FromMM(mi,mx);
+ if(c.m_leaf)
+ m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg);
+ else
+ c.m_leaf=m_cdbvt.insert(bounds,&c);
+ }
+ }
+ }
+}
+
+//
+void btSoftBody::cleanupClusters()
+{
+for(int i=0;i<m_joints.size();++i)
+ {
+ m_joints[i]->Terminate(m_sst.sdt);
+ if(m_joints[i]->m_delete)
+ {
+ btAlignedFree(m_joints[i]);
+ m_joints.remove(m_joints[i--]);
+ }
+ }
+}
+
+//
+void btSoftBody::prepareClusters(int iterations)
+{
+for(int i=0;i<m_joints.size();++i)
+ {
+ m_joints[i]->Prepare(m_sst.sdt,iterations);
+ }
+}
+
+
+//
+void btSoftBody::solveClusters(btScalar sor)
+{
+for(int i=0,ni=m_joints.size();i<ni;++i)
+ {
+ m_joints[i]->Solve(m_sst.sdt,sor);
+ }
+}
+
+//
+void btSoftBody::applyClusters(bool drift)
+{
+BT_PROFILE("ApplyClusters");
+const btScalar f0=m_sst.sdt;
+const btScalar f1=f0/2;
+btAlignedObjectArray<btVector3> deltas;
+btAlignedObjectArray<btScalar> weights;
+deltas.resize(m_nodes.size(),btVector3(0,0,0));
+weights.resize(m_nodes.size(),0);
+int i;
+
+if(drift)
+ {
+ for(i=0;i<m_clusters.size();++i)
+ {
+ Cluster& c=*m_clusters[i];
+ if(c.m_ndimpulses)
+ {
+ c.m_dimpulses[0]/=(btScalar)c.m_ndimpulses;
+ c.m_dimpulses[1]/=(btScalar)c.m_ndimpulses;
+ }
+ }
+ }
+for(i=0;i<m_clusters.size();++i)
+ {
+ Cluster& c=*m_clusters[i];
+ if(0<(drift?c.m_ndimpulses:c.m_nvimpulses))
+ {
+ const btVector3 v=(drift?c.m_dimpulses[0]:c.m_vimpulses[0])*m_sst.sdt;
+ const btVector3 w=(drift?c.m_dimpulses[1]:c.m_vimpulses[1])*m_sst.sdt;
+ for(int j=0;j<c.m_nodes.size();++j)
+ {
+ const int idx=int(c.m_nodes[j]-&m_nodes[0]);
+ const btVector3& x=c.m_nodes[j]->m_x;
+ const btScalar q=c.m_masses[j];
+ deltas[idx] += (v+cross(w,x-c.m_com))*q;
+ weights[idx] += q;
+ }
+ }
+ }
+ for(i=0;i<deltas.size();++i)
+ {
+ if(weights[i]>0) m_nodes[i].m_x+=deltas[i]/weights[i];
+ }
+}
+
+//
+void btSoftBody::dampClusters()
+{
+ int i;
+
+for(i=0;i<m_clusters.size();++i)
+ {
+ Cluster& c=*m_clusters[i];
+ if(c.m_ndamping>0)
+ {
+ for(int j=0;j<c.m_nodes.size();++j)
+ {
+ Node& n=*c.m_nodes[j];
+ if(n.m_im>0)
+ {
+ const btVector3 vx=c.m_lv+cross(c.m_av,c.m_nodes[j]->m_q-c.m_com);
+ n.m_v += c.m_ndamping*(vx-n.m_v);
+ }
+ }
+ }
+ }
+}
+
+//
+void btSoftBody::Joint::Prepare(btScalar dt,int)
+{
+m_bodies[0].activate();
+m_bodies[1].activate();
+}
+
+//
+void btSoftBody::LJoint::Prepare(btScalar dt,int iterations)
+{
+static const btScalar maxdrift=4;
+Joint::Prepare(dt,iterations);
+m_rpos[0] = m_bodies[0].xform()*m_refs[0];
+m_rpos[1] = m_bodies[1].xform()*m_refs[1];
+m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt;
+m_rpos[0] -= m_bodies[0].xform().getOrigin();
+m_rpos[1] -= m_bodies[1].xform().getOrigin();
+m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0],
+ m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]);
+if(m_split>0)
+ {
+ m_sdrift = m_massmatrix*(m_drift*m_split);
+ m_drift *= 1-m_split;
+ }
+m_drift /=(btScalar)iterations;
+}
+
+//
+void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor)
+{
+const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
+const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
+const btVector3 vr=va-vb;
+btSoftBody::Impulse impulse;
+impulse.m_asVelocity = 1;
+impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor;
+m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
+m_bodies[1].applyImpulse( impulse,m_rpos[1]);
+}
+
+//
+void btSoftBody::LJoint::Terminate(btScalar dt)
+{
+if(m_split>0)
+ {
+ m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
+ m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
+ }
+}
+
+//
+void btSoftBody::AJoint::Prepare(btScalar dt,int iterations)
+{
+static const btScalar maxdrift=SIMD_PI/16;
+m_icontrol->Prepare(this);
+Joint::Prepare(dt,iterations);
+m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0];
+m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1];
+m_drift = NormalizeAny(cross(m_axis[1],m_axis[0]));
+m_drift *= btMin(maxdrift,btAcos(Clamp<btScalar>(dot(m_axis[0],m_axis[1]),-1,+1)));
+m_drift *= m_erp/dt;
+m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia());
+if(m_split>0)
+ {
+ m_sdrift = m_massmatrix*(m_drift*m_split);
+ m_drift *= 1-m_split;
+ }
+m_drift /=(btScalar)iterations;
+}
+
+//
+void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor)
+{
+const btVector3 va=m_bodies[0].angularVelocity();
+const btVector3 vb=m_bodies[1].angularVelocity();
+const btVector3 vr=va-vb;
+const btScalar sp=dot(vr,m_axis[0]);
+const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp);
+btSoftBody::Impulse impulse;
+impulse.m_asVelocity = 1;
+impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor;
+m_bodies[0].applyAImpulse(-impulse);
+m_bodies[1].applyAImpulse( impulse);
+}
+
+//
+void btSoftBody::AJoint::Terminate(btScalar dt)
+{
+if(m_split>0)
+ {
+ m_bodies[0].applyDAImpulse(-m_sdrift);
+ m_bodies[1].applyDAImpulse( m_sdrift);
+ }
+}
+
+//
+void btSoftBody::CJoint::Prepare(btScalar dt,int iterations)
+{
+Joint::Prepare(dt,iterations);
+const bool dodrift=(m_life==0);
+m_delete=(++m_life)>m_maxlife;
+if(dodrift)
+ {
+ m_drift=m_drift*m_erp/dt;
+ if(m_split>0)
+ {
+ m_sdrift = m_massmatrix*(m_drift*m_split);
+ m_drift *= 1-m_split;
+ }
+ m_drift/=(btScalar)iterations;
+ }
+ else
+ {
+ m_drift=m_sdrift=btVector3(0,0,0);
+ }
+}
+
+//
+void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor)
+{
+const btVector3 va=m_bodies[0].velocity(m_rpos[0]);
+const btVector3 vb=m_bodies[1].velocity(m_rpos[1]);
+const btVector3 vrel=va-vb;
+const btScalar rvac=dot(vrel,m_normal);
+btSoftBody::Impulse impulse;
+impulse.m_asVelocity = 1;
+impulse.m_velocity = m_drift;
+if(rvac<0)
+ {
+ const btVector3 iv=m_normal*rvac;
+ const btVector3 fv=vrel-iv;
+ impulse.m_velocity += iv+fv*m_friction;
+ }
+impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor;
+m_bodies[0].applyImpulse(-impulse,m_rpos[0]);
+m_bodies[1].applyImpulse( impulse,m_rpos[1]);
+}
+
+//
+void btSoftBody::CJoint::Terminate(btScalar dt)
+{
+if(m_split>0)
+ {
+ m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]);
+ m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]);
+ }
+}
+
+//
+void btSoftBody::applyForces()
+{
+ BT_PROFILE("SoftBody applyForces");
+ const btScalar dt=m_sst.sdt;
+ const btScalar kLF=m_cfg.kLF;
+ const btScalar kDG=m_cfg.kDG;
+ const btScalar kPR=m_cfg.kPR;
+ const btScalar kVC=m_cfg.kVC;
+ const bool as_lift=kLF>0;
+ const bool as_drag=kDG>0;
+ const bool as_pressure=kPR!=0;
+ const bool as_volume=kVC>0;
+ const bool as_aero= as_lift ||
+ as_drag ;
+ const bool as_vaero= as_aero &&
+ (m_cfg.aeromodel<btSoftBody::eAeroModel::F_TwoSided);
+ const bool as_faero= as_aero &&
+ (m_cfg.aeromodel>=btSoftBody::eAeroModel::F_TwoSided);
+ const bool use_medium= as_aero;
+ const bool use_volume= as_pressure ||
+ as_volume ;
+ btScalar volume=0;
+ btScalar ivolumetp=0;
+ btScalar dvolumetv=0;
+ btSoftBody::sMedium medium;
+ if(use_volume)
+ {
+ volume = getVolume();
+ ivolumetp = 1/btFabs(volume)*kPR;
+ dvolumetv = (m_pose.m_volume-volume)*kVC;
+ }
+ /* Per vertex forces */
+ int i,ni;
+
+ for(i=0,ni=m_nodes.size();i<ni;++i)
+ {
+ btSoftBody::Node& n=m_nodes[i];
+ if(n.m_im>0)
+ {
+ if(use_medium)
+ {
+ EvaluateMedium(m_worldInfo,n.m_x,medium);
+ /* Aerodynamics */
+ if(as_vaero)
+ {
+ const btVector3 rel_v=n.m_v-medium.m_velocity;
+ const btScalar rel_v2=rel_v.length2();
+ if(rel_v2>SIMD_EPSILON)
+ {
+ btVector3 nrm=n.m_n;
+ /* Setup normal */
+ switch(m_cfg.aeromodel)
+ {
+ case btSoftBody::eAeroModel::V_Point:
+ nrm=NormalizeAny(rel_v);break;
+ case btSoftBody::eAeroModel::V_TwoSided:
+ nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
+ }
+ const btScalar dvn=dot(rel_v,nrm);
+ /* Compute forces */
+ if(dvn>0)
+ {
+ btVector3 force(0,0,0);
+ const btScalar c0 = n.m_area*dvn*rel_v2/2;
+ const btScalar c1 = c0*medium.m_density;
+ force += nrm*(-c1*kLF);
+ force += rel_v.normalized()*(-c1*kDG);
+ ApplyClampedForce(n,force,dt);
+ }
+ }
+ }
+ }
+ /* Pressure */
+ if(as_pressure)
+ {
+ n.m_f += n.m_n*(n.m_area*ivolumetp);
+ }
+ /* Volume */
+ if(as_volume)
+ {
+ n.m_f += n.m_n*(n.m_area*dvolumetv);
+ }
+ }
+ }
+ /* Per face forces */
+ for(i=0,ni=m_faces.size();i<ni;++i)
+ {
+ btSoftBody::Face& f=m_faces[i];
+ if(as_faero)
+ {
+ const btVector3 v=(f.m_n[0]->m_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3;
+ const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3;
+ EvaluateMedium(m_worldInfo,x,medium);
+ const btVector3 rel_v=v-medium.m_velocity;
+ const btScalar rel_v2=rel_v.length2();
+ if(rel_v2>SIMD_EPSILON)
+ {
+ btVector3 nrm=f.m_normal;
+ /* Setup normal */
+ switch(m_cfg.aeromodel)
+ {
+ case btSoftBody::eAeroModel::F_TwoSided:
+ nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break;
+ }
+ const btScalar dvn=dot(rel_v,nrm);
+ /* Compute forces */
+ if(dvn>0)
+ {
+ btVector3 force(0,0,0);
+ const btScalar c0 = f.m_ra*dvn*rel_v2;
+ const btScalar c1 = c0*medium.m_density;
+ force += nrm*(-c1*kLF);
+ force += rel_v.normalized()*(-c1*kDG);
+ force /= 3;
+ for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt);
+ }
+ }
+ }
+ }
+}
+
+//
+void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti)
+{
+ const btScalar kAHR=psb->m_cfg.kAHR*kst;
+ const btScalar dt=psb->m_sst.sdt;
+ for(int i=0,ni=psb->m_anchors.size();i<ni;++i)
+ {
+ const Anchor& a=psb->m_anchors[i];
+ const btTransform& t=a.m_body->getInterpolationWorldTransform();
+ Node& n=*a.m_node;
+ const btVector3 wa=t*a.m_local;
+ const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt;
+ const btVector3 vb=n.m_x-n.m_q;
+ const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR;
+ const btVector3 impulse=a.m_c0*vr;
+ n.m_x+=impulse*a.m_c2;
+ a.m_body->applyImpulse(-impulse,a.m_c1);
+ }
+}
+
+//
+void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti)
+{
+ const btScalar dt=psb->m_sst.sdt;
+ const btScalar mrg=psb->getCollisionShape()->getMargin();
+ for(int i=0,ni=psb->m_rcontacts.size();i<ni;++i)
+ {
+ const RContact& c=psb->m_rcontacts[i];
+ const sCti& cti=c.m_cti;
+ const btVector3 va=cti.m_body->getVelocityInLocalPoint(c.m_c1)*dt;
+ const btVector3 vb=c.m_node->m_x-c.m_node->m_q;
+ const btVector3 vr=vb-va;
+ const btScalar dn=dot(vr,cti.m_normal);
+ if(dn<=SIMD_EPSILON)
+ {
+ const btScalar dp=btMin(dot(c.m_node->m_x,cti.m_normal)+cti.m_offset,mrg);
+ const btVector3 fv=vr-cti.m_normal*dn;
+ const btVector3 impulse=c.m_c0*((vr-fv*c.m_c3+cti.m_normal*(dp*c.m_c4))*kst);
+ c.m_node->m_x-=impulse*c.m_c2;
+ c.m_cti.m_body->applyImpulse(impulse,c.m_c1);
+ }
+ }
+}
+
+//
+void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti)
+{
+for(int i=0,ni=psb->m_scontacts.size();i<ni;++i)
+ {
+ const SContact& c=psb->m_scontacts[i];
+ const btVector3& nr=c.m_normal;
+ Node& n=*c.m_node;
+ Face& f=*c.m_face;
+ const btVector3 p=BaryEval( f.m_n[0]->m_x,
+ f.m_n[1]->m_x,
+ f.m_n[2]->m_x,
+ c.m_weights);
+ const btVector3 q=BaryEval( f.m_n[0]->m_q,
+ f.m_n[1]->m_q,
+ f.m_n[2]->m_q,
+ c.m_weights);
+ const btVector3 vr=(n.m_x-n.m_q)-(p-q);
+ btVector3 corr(0,0,0);
+ if(dot(vr,nr)<0)
+ {
+ const btScalar j=c.m_margin-(dot(nr,n.m_x)-dot(nr,p));
+ corr+=c.m_normal*j;
+ }
+ corr -= ProjectOnPlane(vr,nr)*c.m_friction;
+ n.m_x += corr*c.m_cfm[0];
+ f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x());
+ f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y());
+ f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z());
+ }
+}
+
+//
+void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti)
+{
+ for(int i=0,ni=psb->m_links.size();i<ni;++i)
+ {
+ Link& l=psb->m_links[i];
+ if(l.m_c0>0)
+ {
+ Node& a=*l.m_n[0];
+ Node& b=*l.m_n[1];
+ const btVector3 del=b.m_x-a.m_x;
+ const btScalar len=del.length2();
+ const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst;
+ const btScalar t=k*a.m_im;
+ a.m_x-=del*(k*a.m_im);
+ b.m_x+=del*(k*b.m_im);
+ }
+ }
+}
+
+//
+void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst)
+{
+for(int i=0,ni=psb->m_links.size();i<ni;++i)
+ {
+ Link& l=psb->m_links[i];
+ Node** n=l.m_n;
+ const btScalar j=-dot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst;
+ n[0]->m_v+= l.m_c3*(j*n[0]->m_im);
+ n[1]->m_v-= l.m_c3*(j*n[1]->m_im);
+ }
+}
+
+//
+btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
+{
+switch(solver)
+ {
+ case ePSolver::Anchors: return(&btSoftBody::PSolve_Anchors);
+ case ePSolver::Linear: return(&btSoftBody::PSolve_Links);
+ case ePSolver::RContacts: return(&btSoftBody::PSolve_RContacts);
+ case ePSolver::SContacts: return(&btSoftBody::PSolve_SContacts);
+ }
+return(0);
+}
+
+//
+btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
+{
+switch(solver)
+ {
+ case eVSolver::Linear: return(&btSoftBody::VSolve_Links);
+ }
+return(0);
+}
+
+//
+void btSoftBody::defaultCollisionHandler(btCollisionObject* pco)
+{
+switch(m_cfg.collisions&fCollision::RVSmask)
+ {
+ case fCollision::SDF_RS:
+ {
+ btSoftColliders::CollideSDF_RS docollide;
+ btRigidBody* prb=btRigidBody::upcast(pco);
+ const btTransform wtr=prb->getInterpolationWorldTransform();
+ const btTransform ctr=prb->getWorldTransform();
+ const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length();
+ const btScalar basemargin=getCollisionShape()->getMargin();
+ btVector3 mins;
+ btVector3 maxs;
+ btDbvtVolume volume;
+ pco->getCollisionShape()->getAabb( pco->getInterpolationWorldTransform(),
+ mins,
+ maxs);
+ volume=btDbvtVolume::FromMM(mins,maxs);
+ volume.Expand(btVector3(basemargin,basemargin,basemargin));
+ docollide.psb = this;
+ docollide.prb = prb;
+ docollide.dynmargin = basemargin+timemargin;
+ docollide.stamargin = basemargin;
+ btDbvt::collideTV(m_ndbvt.m_root,volume,docollide);
+ }
+ break;
+ case fCollision::CL_RS:
+ {
+ btSoftColliders::CollideCL_RS collider;
+ collider.Process(this,btRigidBody::upcast(pco));
+ }
+ break;
+ }
+}
+
+//
+void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
+{
+const int cf=m_cfg.collisions&psb->m_cfg.collisions;
+switch(cf&fCollision::SVSmask)
+ {
+ case fCollision::CL_SS:
+ {
+ btSoftColliders::CollideCL_SS docollide;
+ docollide.Process(this,psb);
+ }
+ break;
+ case fCollision::VF_SS:
+ {
+ btSoftColliders::CollideVF_SS docollide;
+ /* common */
+ docollide.mrg= getCollisionShape()->getMargin()+
+ psb->getCollisionShape()->getMargin();
+ /* psb0 nodes vs psb1 faces */
+ docollide.psb[0]=this;
+ docollide.psb[1]=psb;
+ btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
+ docollide.psb[1]->m_fdbvt.m_root,
+ docollide);
+ /* psb1 nodes vs psb0 faces */
+ docollide.psb[0]=psb;
+ docollide.psb[1]=this;
+ btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root,
+ docollide.psb[1]->m_fdbvt.m_root,
+ docollide);
+ }
+ break;
+ }
+}
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.h b/extern/bullet2/src/BulletSoftBody/btSoftBody.h
new file mode 100644
index 00000000000..834199c668a
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.h
@@ -0,0 +1,810 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btSoftBody implementation by Nathanael Presson
+
+#ifndef _BT_SOFT_BODY_H
+#define _BT_SOFT_BODY_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btPoint3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+#include "BulletCollision/CollisionShapes/btConcaveShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "btSparseSDF.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+
+class btBroadphaseInterface;
+class btCollisionDispatcher;
+
+/* btSoftBodyWorldInfo */
+struct btSoftBodyWorldInfo
+{
+ btScalar air_density;
+ btScalar water_density;
+ btScalar water_offset;
+ btVector3 water_normal;
+ btBroadphaseInterface* m_broadphase;
+ btCollisionDispatcher* m_dispatcher;
+ btVector3 m_gravity;
+ btSparseSdf<3> m_sparsesdf;
+};
+
+
+/// btSoftBody is work-in-progress
+class btSoftBody : public btCollisionObject
+{
+public:
+ //
+ // Enumerations
+ //
+
+ ///eAeroModel
+ struct eAeroModel { enum _ {
+ V_Point, ///Vertex normals are oriented toward velocity
+ V_TwoSided, ///Vertex normals are fliped to match velocity
+ V_OneSided, ///Vertex normals are taken as it is
+ F_TwoSided, ///Face normals are fliped to match velocity
+ F_OneSided, ///Face normals are taken as it is
+ END
+ };};
+
+ ///eVSolver : velocities solvers
+ struct eVSolver { enum _ {
+ Linear, ///Linear solver
+ END
+ };};
+
+ ///ePSolver : positions solvers
+ struct ePSolver { enum _ {
+ Linear, ///Linear solver
+ Anchors, ///Anchor solver
+ RContacts, ///Rigid contacts solver
+ SContacts, ///Soft contacts solver
+ END
+ };};
+
+ ///eSolverPresets
+ struct eSolverPresets { enum _ {
+ Positions,
+ Velocities,
+ Default = Positions,
+ END
+ };};
+
+ ///eFeature
+ struct eFeature { enum _ {
+ None,
+ Node,
+ Link,
+ Face,
+ END
+ };};
+
+ typedef btAlignedObjectArray<eVSolver::_> tVSolverArray;
+ typedef btAlignedObjectArray<ePSolver::_> tPSolverArray;
+
+ //
+ // Flags
+ //
+
+ ///fCollision
+ struct fCollision { enum _ {
+ RVSmask = 0x000f, ///Rigid versus soft mask
+ SDF_RS = 0x0001, ///SDF based rigid vs soft
+ CL_RS = 0x0002, ///Cluster vs convex rigid vs soft
+
+ SVSmask = 0x00f0, ///Rigid versus soft mask
+ VF_SS = 0x0010, ///Vertex vs face soft vs soft handling
+ CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling
+ /* presets */
+ Default = SDF_RS,
+ END
+ };};
+
+ ///fMaterial
+ struct fMaterial { enum _ {
+ DebugDraw = 0x0001, /// Enable debug draw
+ /* presets */
+ Default = DebugDraw,
+ END
+ };};
+
+ //
+ // API Types
+ //
+
+ /* sRayCast */
+ struct sRayCast
+ {
+ btSoftBody* body; /// soft body
+ eFeature::_ feature; /// feature type
+ int index; /// feature index
+ btScalar time; /// time of impact (rayorg+raydir*time)
+ };
+
+ /* ImplicitFn */
+ struct ImplicitFn
+ {
+ virtual btScalar Eval(const btVector3& x)=0;
+ };
+
+ //
+ // Internal types
+ //
+
+ typedef btAlignedObjectArray<btScalar> tScalarArray;
+ typedef btAlignedObjectArray<btVector3> tVector3Array;
+
+ /* sCti is Softbody contact info */
+ struct sCti
+ {
+ btRigidBody* m_body; /* Rigid body */
+ btVector3 m_normal; /* Outward normal */
+ btScalar m_offset; /* Offset from origin */
+ };
+
+ /* sMedium */
+ struct sMedium
+ {
+ btVector3 m_velocity; /* Velocity */
+ btScalar m_pressure; /* Pressure */
+ btScalar m_density; /* Density */
+ };
+
+ /* Base type */
+ struct Element
+ {
+ void* m_tag; // User data
+ Element() : m_tag(0) {}
+ };
+ /* Material */
+ struct Material : Element
+ {
+ btScalar m_kLST; // Linear stiffness coefficient [0,1]
+ btScalar m_kAST; // Area/Angular stiffness coefficient [0,1]
+ btScalar m_kVST; // Volume stiffness coefficient [0,1]
+ int m_flags; // Flags
+ };
+
+ /* Feature */
+ struct Feature : Element
+ {
+ Material* m_material; // Material
+ };
+ /* Node */
+ struct Node : Feature
+ {
+ btVector3 m_x; // Position
+ btVector3 m_q; // Previous step position
+ btVector3 m_v; // Velocity
+ btVector3 m_f; // Force accumulator
+ btVector3 m_n; // Normal
+ btScalar m_im; // 1/mass
+ btScalar m_area; // Area
+ btDbvtNode* m_leaf; // Leaf data
+ int m_battach:1; // Attached
+ };
+ /* Link */
+ struct Link : Feature
+ {
+ Node* m_n[2]; // Node pointers
+ btScalar m_rl; // Rest length
+ int m_bbending:1; // Bending link
+ btScalar m_c0; // (ima+imb)*kLST
+ btScalar m_c1; // rl^2
+ btScalar m_c2; // |gradient|^2/c0
+ btVector3 m_c3; // gradient
+ };
+ /* Face */
+ struct Face : Feature
+ {
+ Node* m_n[3]; // Node pointers
+ btVector3 m_normal; // Normal
+ btScalar m_ra; // Rest area
+ btDbvtNode* m_leaf; // Leaf data
+ };
+ /* RContact */
+ struct RContact
+ {
+ sCti m_cti; // Contact infos
+ Node* m_node; // Owner node
+ btMatrix3x3 m_c0; // Impulse matrix
+ btVector3 m_c1; // Relative anchor
+ btScalar m_c2; // ima*dt
+ btScalar m_c3; // Friction
+ btScalar m_c4; // Hardness
+ };
+ /* SContact */
+ struct SContact
+ {
+ Node* m_node; // Node
+ Face* m_face; // Face
+ btVector3 m_weights; // Weigths
+ btVector3 m_normal; // Normal
+ btScalar m_margin; // Margin
+ btScalar m_friction; // Friction
+ btScalar m_cfm[2]; // Constraint force mixing
+ };
+ /* Anchor */
+ struct Anchor
+ {
+ Node* m_node; // Node pointer
+ btVector3 m_local; // Anchor position in body space
+ btRigidBody* m_body; // Body
+ btMatrix3x3 m_c0; // Impulse matrix
+ btVector3 m_c1; // Relative anchor
+ btScalar m_c2; // ima*dt
+ };
+ /* Note */
+ struct Note : Element
+ {
+ const char* m_text; // Text
+ btVector3 m_offset; // Offset
+ int m_rank; // Rank
+ Node* m_nodes[4]; // Nodes
+ btScalar m_coords[4]; // Coordinates
+ };
+ /* Pose */
+ struct Pose
+ {
+ bool m_bvolume; // Is valid
+ bool m_bframe; // Is frame
+ btScalar m_volume; // Rest volume
+ tVector3Array m_pos; // Reference positions
+ tScalarArray m_wgh; // Weights
+ btVector3 m_com; // COM
+ btMatrix3x3 m_rot; // Rotation
+ btMatrix3x3 m_scl; // Scale
+ btMatrix3x3 m_aqq; // Base scaling
+ };
+ /* Cluster */
+ struct Cluster
+ {
+ btAlignedObjectArray<Node*> m_nodes;
+ tScalarArray m_masses;
+ tVector3Array m_framerefs;
+ btTransform m_framexform;
+ btScalar m_idmass;
+ btScalar m_imass;
+ btMatrix3x3 m_locii;
+ btMatrix3x3 m_invwi;
+ btVector3 m_com;
+ btVector3 m_vimpulses[2];
+ btVector3 m_dimpulses[2];
+ int m_nvimpulses;
+ int m_ndimpulses;
+ btVector3 m_lv;
+ btVector3 m_av;
+ btDbvtNode* m_leaf;
+ btScalar m_ndamping;
+ btScalar m_ldamping;
+ btScalar m_adamping;
+ btScalar m_matching;
+ bool m_collide;
+ Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0) {}
+ };
+ /* Impulse */
+ struct Impulse
+ {
+ btVector3 m_velocity;
+ btVector3 m_drift;
+ int m_asVelocity:1;
+ int m_asDrift:1;
+ Impulse() : m_velocity(0,0,0),m_drift(0,0,0),m_asVelocity(0),m_asDrift(0) {}
+ Impulse operator -() const
+ {
+ Impulse i=*this;
+ i.m_velocity=-i.m_velocity;
+ i.m_drift=-i.m_drift;
+ return(i);
+ }
+ Impulse operator*(btScalar x) const
+ {
+ Impulse i=*this;
+ i.m_velocity*=x;
+ i.m_drift*=x;
+ return(i);
+ }
+ };
+ /* Body */
+ struct Body
+ {
+ Cluster* m_soft;
+ btRigidBody* m_rigid;
+ Body() : m_soft(0),m_rigid(0) {}
+ Body(Cluster* p) : m_soft(p),m_rigid(0) {}
+ Body(btRigidBody* p) : m_soft(0),m_rigid(p) {}
+ void activate() const
+ {
+ if(m_rigid) m_rigid->activate();
+ }
+ const btMatrix3x3& invWorldInertia() const
+ {
+ static const btMatrix3x3 iwi(0,0,0,0,0,0,0,0,0);
+ if(m_rigid) return(m_rigid->getInvInertiaTensorWorld());
+ if(m_soft) return(m_soft->m_invwi);
+ return(iwi);
+ }
+ btScalar invMass() const
+ {
+ if(m_rigid) return(m_rigid->getInvMass());
+ if(m_soft) return(m_soft->m_imass);
+ return(0);
+ }
+ const btTransform& xform() const
+ {
+ static const btTransform identity=btTransform::getIdentity();
+ if(m_rigid) return(m_rigid->getInterpolationWorldTransform());
+ if(m_soft) return(m_soft->m_framexform);
+ return(identity);
+ }
+ btVector3 linearVelocity() const
+ {
+ if(m_rigid) return(m_rigid->getLinearVelocity());
+ if(m_soft) return(m_soft->m_lv);
+ return(btVector3(0,0,0));
+ }
+ btVector3 angularVelocity(const btVector3& rpos) const
+ {
+ if(m_rigid) return(cross(m_rigid->getAngularVelocity(),rpos));
+ if(m_soft) return(cross(m_soft->m_av,rpos));
+ return(btVector3(0,0,0));
+ }
+ btVector3 angularVelocity() const
+ {
+ if(m_rigid) return(m_rigid->getAngularVelocity());
+ if(m_soft) return(m_soft->m_av);
+ return(btVector3(0,0,0));
+ }
+ btVector3 velocity(const btVector3& rpos) const
+ {
+ return(linearVelocity()+angularVelocity(rpos));
+ }
+ void applyVImpulse(const btVector3& impulse,const btVector3& rpos) const
+ {
+ if(m_rigid) m_rigid->applyImpulse(impulse,rpos);
+ if(m_soft) btSoftBody::clusterVImpulse(m_soft,rpos,impulse);
+ }
+ void applyDImpulse(const btVector3& impulse,const btVector3& rpos) const
+ {
+ if(m_rigid) m_rigid->applyImpulse(impulse,rpos);
+ if(m_soft) btSoftBody::clusterDImpulse(m_soft,rpos,impulse);
+ }
+ void applyImpulse(const Impulse& impulse,const btVector3& rpos) const
+ {
+ if(impulse.m_asVelocity) applyVImpulse(impulse.m_velocity,rpos);
+ if(impulse.m_asDrift) applyDImpulse(impulse.m_drift,rpos);
+ }
+ void applyVAImpulse(const btVector3& impulse) const
+ {
+ if(m_rigid) m_rigid->applyTorqueImpulse(impulse);
+ if(m_soft) btSoftBody::clusterVAImpulse(m_soft,impulse);
+ }
+ void applyDAImpulse(const btVector3& impulse) const
+ {
+ if(m_rigid) m_rigid->applyTorqueImpulse(impulse);
+ if(m_soft) btSoftBody::clusterDAImpulse(m_soft,impulse);
+ }
+ void applyAImpulse(const Impulse& impulse) const
+ {
+ if(impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity);
+ if(impulse.m_asDrift) applyDAImpulse(impulse.m_drift);
+ }
+ void applyDCImpulse(const btVector3& impulse) const
+ {
+ if(m_rigid) m_rigid->applyCentralImpulse(impulse);
+ if(m_soft) btSoftBody::clusterDCImpulse(m_soft,impulse);
+ }
+ };
+ /* Joint */
+ struct Joint
+ {
+ struct eType { enum _ {
+ Linear,
+ Angular,
+ Contact,
+ };};
+ struct Specs
+ {
+ Specs() : erp(1),cfm(1),split(1) {}
+ btScalar erp;
+ btScalar cfm;
+ btScalar split;
+ };
+ Body m_bodies[2];
+ btVector3 m_refs[2];
+ btScalar m_cfm;
+ btScalar m_erp;
+ btScalar m_split;
+ btVector3 m_drift;
+ btVector3 m_sdrift;
+ btMatrix3x3 m_massmatrix;
+ bool m_delete;
+ virtual ~Joint() {}
+ Joint() : m_delete(false) {}
+ virtual void Prepare(btScalar dt,int iterations);
+ virtual void Solve(btScalar dt,btScalar sor)=0;
+ virtual void Terminate(btScalar dt)=0;
+ virtual eType::_ Type() const=0;
+ };
+ /* LJoint */
+ struct LJoint : Joint
+ {
+ struct Specs : Joint::Specs
+ {
+ btVector3 position;
+ };
+ btVector3 m_rpos[2];
+ void Prepare(btScalar dt,int iterations);
+ void Solve(btScalar dt,btScalar sor);
+ void Terminate(btScalar dt);
+ eType::_ Type() const { return(eType::Linear); }
+ };
+ /* AJoint */
+ struct AJoint : Joint
+ {
+ struct IControl
+ {
+ virtual void Prepare(AJoint*) {}
+ virtual btScalar Speed(AJoint*,btScalar current) { return(current); }
+ static IControl* Default() { static IControl def;return(&def); }
+ };
+ struct Specs : Joint::Specs
+ {
+ Specs() : icontrol(IControl::Default()) {}
+ btVector3 axis;
+ IControl* icontrol;
+ };
+ btVector3 m_axis[2];
+ IControl* m_icontrol;
+ void Prepare(btScalar dt,int iterations);
+ void Solve(btScalar dt,btScalar sor);
+ void Terminate(btScalar dt);
+ eType::_ Type() const { return(eType::Angular); }
+ };
+ /* CJoint */
+ struct CJoint : Joint
+ {
+ int m_life;
+ int m_maxlife;
+ btVector3 m_rpos[2];
+ btVector3 m_normal;
+ btScalar m_friction;
+ void Prepare(btScalar dt,int iterations);
+ void Solve(btScalar dt,btScalar sor);
+ void Terminate(btScalar dt);
+ eType::_ Type() const { return(eType::Contact); }
+ };
+ /* Config */
+ struct Config
+ {
+ eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
+ btScalar kVCF; // Velocities correction factor (Baumgarte)
+ btScalar kDP; // Damping coefficient [0,1]
+ btScalar kDG; // Drag coefficient [0,+inf]
+ btScalar kLF; // Lift coefficient [0,+inf]
+ btScalar kPR; // Pressure coefficient [-inf,+inf]
+ btScalar kVC; // Volume conversation coefficient [0,+inf]
+ btScalar kDF; // Dynamic friction coefficient [0,1]
+ btScalar kMT; // Pose matching coefficient [0,1]
+ btScalar kCHR; // Rigid contacts hardness [0,1]
+ btScalar kKHR; // Kinetic contacts hardness [0,1]
+ btScalar kSHR; // Soft contacts hardness [0,1]
+ btScalar kAHR; // Anchors hardness [0,1]
+ btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only)
+ btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only)
+ btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only)
+ btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
+ btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
+ btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
+ btScalar maxvolume; // Maximum volume ratio for pose
+ btScalar timescale; // Time scale
+ int viterations; // Velocities solver iterations
+ int piterations; // Positions solver iterations
+ int diterations; // Drift solver iterations
+ int citerations; // Cluster solver iterations
+ int collisions; // Collisions flags
+ tVSolverArray m_vsequence; // Velocity solvers sequence
+ tPSolverArray m_psequence; // Position solvers sequence
+ tPSolverArray m_dsequence; // Drift solvers sequence
+ };
+ /* SolverState */
+ struct SolverState
+ {
+ btScalar sdt; // dt*timescale
+ btScalar isdt; // 1/sdt
+ btScalar velmrg; // velocity margin
+ btScalar radmrg; // radial margin
+ btScalar updmrg; // Update margin
+ };
+ /* RayCaster */
+ struct RayCaster : btDbvt::ICollide
+ {
+ btVector3 o;
+ btVector3 d;
+ btScalar mint;
+ Face* face;
+ int tests;
+ RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt);
+ void Process(const btDbvtNode* leaf);
+ static inline btScalar rayTriangle(const btVector3& org,
+ const btVector3& dir,
+ const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btScalar maxt=SIMD_INFINITY);
+ };
+
+ //
+ // Typedef's
+ //
+
+ typedef void (*psolver_t)(btSoftBody*,btScalar,btScalar);
+ typedef void (*vsolver_t)(btSoftBody*,btScalar);
+ typedef btAlignedObjectArray<Cluster*> tClusterArray;
+ typedef btAlignedObjectArray<Note> tNoteArray;
+ typedef btAlignedObjectArray<Node> tNodeArray;
+ typedef btAlignedObjectArray<btDbvtNode*> tLeafArray;
+ typedef btAlignedObjectArray<Link> tLinkArray;
+ typedef btAlignedObjectArray<Face> tFaceArray;
+ typedef btAlignedObjectArray<Anchor> tAnchorArray;
+ typedef btAlignedObjectArray<RContact> tRContactArray;
+ typedef btAlignedObjectArray<SContact> tSContactArray;
+ typedef btAlignedObjectArray<Material*> tMaterialArray;
+ typedef btAlignedObjectArray<Joint*> tJointArray;
+ typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
+
+ //
+ // Fields
+ //
+
+ Config m_cfg; // Configuration
+ SolverState m_sst; // Solver state
+ Pose m_pose; // Pose
+ void* m_tag; // User data
+ btSoftBodyWorldInfo* m_worldInfo; // World info
+ tNoteArray m_notes; // Notes
+ tNodeArray m_nodes; // Nodes
+ tLinkArray m_links; // Links
+ tFaceArray m_faces; // Faces
+ tAnchorArray m_anchors; // Anchors
+ tRContactArray m_rcontacts; // Rigid contacts
+ tSContactArray m_scontacts; // Soft contacts
+ tJointArray m_joints; // Joints
+ tMaterialArray m_materials; // Materials
+ btScalar m_timeacc; // Time accumulator
+ btVector3 m_bounds[2]; // Spatial bounds
+ bool m_bUpdateRtCst; // Update runtime constants
+ btDbvt m_ndbvt; // Nodes tree
+ btDbvt m_fdbvt; // Faces tree
+ btDbvt m_cdbvt; // Clusters tree
+ tClusterArray m_clusters; // Clusters
+
+ //
+ // Api
+ //
+
+ /* ctor */
+ btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count,
+ const btVector3* x,
+ const btScalar* m);
+ /* dtor */
+ virtual ~btSoftBody();
+ /* Check for existing link */
+ bool checkLink( int node0,
+ int node1) const;
+ bool checkLink( const Node* node0,
+ const Node* node1) const;
+ /* Check for existring face */
+ bool checkFace( int node0,
+ int node1,
+ int node2) const;
+ /* Append material */
+ Material* appendMaterial();
+ /* Append note */
+ void appendNote( const char* text,
+ const btVector3& o,
+ const btVector4& c=btVector4(1,0,0,0),
+ Node* n0=0,
+ Node* n1=0,
+ Node* n2=0,
+ Node* n3=0);
+ void appendNote( const char* text,
+ const btVector3& o,
+ Node* feature);
+ void appendNote( const char* text,
+ const btVector3& o,
+ Link* feature);
+ void appendNote( const char* text,
+ const btVector3& o,
+ Face* feature);
+ /* Append node */
+ void appendNode( const btVector3& x,btScalar m);
+ /* Append link */
+ void appendLink(int model=-1,Material* mat=0);
+ void appendLink( int node0,
+ int node1,
+ Material* mat=0,
+ bool bcheckexist=false);
+ void appendLink( Node* node0,
+ Node* node1,
+ Material* mat=0,
+ bool bcheckexist=false);
+ /* Append face */
+ void appendFace(int model=-1,Material* mat=0);
+ void appendFace( int node0,
+ int node1,
+ int node2,
+ Material* mat=0);
+ /* Append anchor */
+ void appendAnchor( int node,
+ btRigidBody* body);
+ /* Append linear joint */
+ void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1);
+ void appendLinearJoint(const LJoint::Specs& specs,Body body=Body());
+ void appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body);
+ /* Append linear joint */
+ void appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1);
+ void appendAngularJoint(const AJoint::Specs& specs,Body body=Body());
+ void appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body);
+ /* Add force (or gravity) to the entire body */
+ void addForce( const btVector3& force);
+ /* Add force (or gravity) to a node of the body */
+ void addForce( const btVector3& force,
+ int node);
+ /* Add velocity to the entire body */
+ void addVelocity( const btVector3& velocity);
+ /* Add velocity to a node of the body */
+ void addVelocity( const btVector3& velocity,
+ int node);
+ /* Set mass */
+ void setMass( int node,
+ btScalar mass);
+ /* Get mass */
+ btScalar getMass( int node) const;
+ /* Get total mass */
+ btScalar getTotalMass() const;
+ /* Set total mass (weighted by previous masses) */
+ void setTotalMass( btScalar mass,
+ bool fromfaces=false);
+ /* Set total density */
+ void setTotalDensity(btScalar density);
+ /* Transform */
+ void transform( const btTransform& trs);
+ /* Translate */
+ void translate( const btVector3& trs);
+ /* Rotate */
+ void rotate( const btQuaternion& rot);
+ /* Scale */
+ void scale( const btVector3& scl);
+ /* Set current state as pose */
+ void setPose( bool bvolume,
+ bool bframe);
+ /* Return the volume */
+ btScalar getVolume() const;
+ /* Cluster count */
+ int clusterCount() const;
+ /* Cluster center of mass */
+ static btVector3 clusterCom(const Cluster* cluster);
+ btVector3 clusterCom(int cluster) const;
+ /* Cluster velocity at rpos */
+ static btVector3 clusterVelocity(const Cluster* cluster,const btVector3& rpos);
+ /* Cluster impulse */
+ static void clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse);
+ static void clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse);
+ static void clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse);
+ static void clusterVAImpulse(Cluster* cluster,const btVector3& impulse);
+ static void clusterDAImpulse(Cluster* cluster,const btVector3& impulse);
+ static void clusterAImpulse(Cluster* cluster,const Impulse& impulse);
+ static void clusterDCImpulse(Cluster* cluster,const btVector3& impulse);
+ /* Generate bending constraints based on distance in the adjency graph */
+ int generateBendingConstraints( int distance,
+ Material* mat=0);
+ /* Randomize constraints to reduce solver bias */
+ void randomizeConstraints();
+ /* Generate clusters (K-mean) */
+ int generateClusters(int k,int maxiterations=8192);
+ /* Refine */
+ void refine(ImplicitFn* ifn,btScalar accurary,bool cut);
+ /* CutLink */
+ bool cutLink(int node0,int node1,btScalar position);
+ bool cutLink(const Node* node0,const Node* node1,btScalar position);
+ /* Ray casting */
+ bool rayCast(const btVector3& org,
+ const btVector3& dir,
+ sRayCast& results,
+ btScalar maxtime=SIMD_INFINITY);
+ /* Solver presets */
+ void setSolver(eSolverPresets::_ preset);
+ /* predictMotion */
+ void predictMotion(btScalar dt);
+ /* solveConstraints */
+ void solveConstraints();
+ /* staticSolve */
+ void staticSolve(int iterations);
+ /* solveCommonConstraints */
+ static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations);
+ /* solveClusters */
+ static void solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies);
+ /* integrateMotion */
+ void integrateMotion();
+ /* defaultCollisionHandlers */
+ void defaultCollisionHandler(btCollisionObject* pco);
+ void defaultCollisionHandler(btSoftBody* psb);
+
+ //
+ // Cast
+ //
+
+ static const btSoftBody* upcast(const btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()==CO_SOFT_BODY)
+ return (const btSoftBody*)colObj;
+ return 0;
+ }
+ static btSoftBody* upcast(btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()==CO_SOFT_BODY)
+ return (btSoftBody*)colObj;
+ return 0;
+ }
+
+ //
+ // ::btCollisionObject
+ //
+
+ virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ aabbMin = m_bounds[0];
+ aabbMax = m_bounds[1];
+ }
+ //
+ // Private
+ //
+ void pointersToIndices();
+ void indicesToPointers(const int* map=0);
+ int rayCast(const btVector3& org,const btVector3& dir,
+ btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const;
+ void initializeFaceTree();
+ btVector3 evaluateCom() const;
+ bool checkContact(btRigidBody* prb,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const;
+ void updateNormals();
+ void updateBounds();
+ void updatePose();
+ void updateConstants();
+ void initializeClusters();
+ void updateClusters();
+ void cleanupClusters();
+ void prepareClusters(int iterations);
+ void solveClusters(btScalar sor);
+ void applyClusters(bool drift);
+ void dampClusters();
+ void applyForces();
+ static void PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti);
+ static void PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti);
+ static void PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti);
+ static void PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti);
+ static void VSolve_Links(btSoftBody* psb,btScalar kst);
+ static psolver_t getSolver(ePSolver::_ solver);
+ static vsolver_t getSolver(eVSolver::_ solver);
+
+};
+
+
+
+#endif //_BT_SOFT_BODY_H
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
new file mode 100644
index 00000000000..5e3211ed73b
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
@@ -0,0 +1,410 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btSoftBodyConcaveCollisionAlgorithm.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 "BulletCollision/CollisionShapes/btTetrahedronShape.h"
+#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
+
+
+
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletSoftBody/btSoftBody.h"
+
+#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.3)
+
+btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
+: btCollisionAlgorithm(ci),
+m_isSwapped(isSwapped),
+m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
+{
+}
+
+
+
+btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm()
+{
+}
+
+
+
+btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
+ m_dispatcher(dispatcher),
+ m_dispatchInfoPtr(0)
+{
+ m_softBody = (btSoftBody*) (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();
+}
+
+btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback()
+{
+ clearCache();
+// m_dispatcher->releaseManifold( m_manifoldPtr );
+
+}
+
+
+void btSoftBodyTriangleCallback::clearCache()
+{
+ //m_dispatcher->clearManifold(m_manifoldPtr);
+};
+
+
+static const int maxParts = 1;
+static const int maxTriangleIndex = 100*100;
+
+btCollisionShape* shapeCache[maxParts][maxTriangleIndex];
+
+
+void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
+{
+ static bool hackedFirst = true;
+ if (hackedFirst)
+ {
+ hackedFirst = false;
+ int i,j;
+ for (i=0;i<maxParts;i++)
+ {
+ for (j=0;j<maxTriangleIndex;j++)
+ {
+ shapeCache[i][j]=0;
+ }
+ }
+ }
+
+ //just for debugging purposes
+ //printf("triangle %d",m_triangleCount++);
+btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
+ btCollisionAlgorithmConstructionInfo ci;
+ ci.m_dispatcher1 = m_dispatcher;
+
+ ///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);
+
+ }
+
+ if (shapeCache[partId][triangleIndex])
+ {
+ btCollisionShape* tm = shapeCache[partId][triangleIndex];
+
+ //copy over user pointers to temporary shape
+ tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
+
+ btCollisionShape* tmpShape = ob->getCollisionShape();
+ ob->internalSetTemporaryCollisionShape( tm );
+
+
+ btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr);
+
+ colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
+ colAlgo->~btCollisionAlgorithm();
+ ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
+ ob->internalSetTemporaryCollisionShape( tmpShape);
+ return;
+ }
+
+ //aabb filter is already applied!
+
+
+
+
+
+
+
+
+ //btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);
+
+// if (m_softBody->getCollisionShape()->getShapeType()==
+ {
+// btVector3 other;
+ btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
+ normal.normalize();
+ normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION;
+// other=(triangle[0]+triangle[1]+triangle[2])*0.333333f;
+// other+=normal*22.f;
+ btVector3 pts[6] = {triangle[0]+normal,
+ triangle[1]+normal,
+ triangle[2]+normal,
+ triangle[0]-normal,
+ triangle[1]-normal,
+ triangle[2]-normal};
+
+ btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6);
+
+
+// btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other);
+
+ //btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
+ // tm.setMargin(m_collisionMarginTriangle);
+
+ //copy over user pointers to temporary shape
+ tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer());
+
+ btCollisionShape* tmpShape = ob->getCollisionShape();
+ ob->internalSetTemporaryCollisionShape( tm );
+
+
+ btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//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_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
+ colAlgo->~btCollisionAlgorithm();
+ ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
+ ob->internalSetTemporaryCollisionShape( tmpShape );
+// delete tm;
+
+ shapeCache[partId][triangleIndex] = tm;
+
+ }
+
+
+
+}
+
+
+
+void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ m_dispatchInfoPtr = &dispatchInfo;
+ m_collisionMarginTriangle = collisionMarginTriangle;
+ m_resultOut = resultOut;
+
+ //recalc aabbs
+// btTransform softbodyInTriangleSpace;
+// softbodyInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_softBody->getWorldTransform();
+// btCollisionShape* convexShape = static_cast<btCollisionShape*>(m_convexBody->getCollisionShape());
+ //CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
+ btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax;
+ m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax);
+
+ btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5);
+ btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5);
+
+ btTransform triInverse = m_triBody->getWorldTransform().inverse();
+
+ btMatrix3x3 abs_b = triInverse.getBasis().absolute();
+ btPoint3 center = softBodyCenter + triInverse.getOrigin();
+
+ btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
+ abs_b[1].dot(halfExtents),
+ abs_b[2].dot(halfExtents));
+// extent += btVector3(getMargin(),getMargin(),getMargin());
+
+ m_aabbMin = center - extent;
+ m_aabbMax = center + extent;
+
+ btScalar extraMargin = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
+ btVector3 extra(extraMargin,extraMargin,extraMargin);
+
+ m_aabbMax += extra;
+ m_aabbMin -= extra;
+
+/* btVector3 extra(2,2,2);
+ m_aabbMin = aabbWorldSpaceMin-extra;
+ m_aabbMax = aabbWorldSpaceMax+extra;
+*/
+
+}
+
+void btSoftBodyConcaveCollisionAlgorithm::clearCache()
+{
+ m_btSoftBodyTriangleCallback.clearCache();
+
+}
+
+void btSoftBodyConcaveCollisionAlgorithm::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<btConcaveShape*>( triOb->getCollisionShape());
+
+ // if (convexBody->getCollisionShape()->isConvex())
+ {
+ btScalar collisionMarginTriangle = concaveShape->getMargin();
+
+// resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
+ m_btSoftBodyTriangleCallback.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_btSoftBodyTriangleCallback.m_manifoldPtr);
+
+// m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody);
+
+
+ concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax());
+
+ // resultOut->refreshContactPoints();
+
+ }
+
+ }
+
+}
+
+
+btScalar btSoftBodyConcaveCollisionAlgorithm::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/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
new file mode 100644
index 00000000000..adb91329a4c
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
@@ -0,0 +1,118 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
+#define SOFT_BODY_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 "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btSoftBody;
+
+///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called.
+class btSoftBodyTriangleCallback : public btTriangleCallback
+{
+ btSoftBody* m_softBody;
+ 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;
+
+ btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+
+ void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual ~btSoftBodyTriangleCallback();
+
+ 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;
+ }
+
+};
+
+
+
+
+/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes.
+class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm
+{
+
+ bool m_isSwapped;
+
+ btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback;
+
+public:
+
+ btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+
+ virtual ~btSoftBodyConcaveCollisionAlgorithm();
+
+ virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ //we don't add any manifolds
+ }
+
+ void clearCache();
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
+ return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,false);
+ }
+ };
+
+ struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
+ return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,true);
+ }
+ };
+
+};
+
+#endif //SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp
new file mode 100644
index 00000000000..e9ec81f4d2c
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp
@@ -0,0 +1,656 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btSoftBodyHelpers.cpp by Nathanael Presson
+
+#include "btSoftBodyInternals.h"
+#include <stdio.h>
+#include <string.h>
+#include "btSoftBodyHelpers.h"
+#include "LinearMath/btConvexHull.h"
+
+//
+static void drawVertex( btIDebugDraw* idraw,
+ const btVector3& x,btScalar s,const btVector3& c)
+ {
+ idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c);
+ idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c);
+ idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c);
+ }
+
+//
+static void drawBox( btIDebugDraw* idraw,
+ const btVector3& mins,
+ const btVector3& maxs,
+ const btVector3& color)
+{
+const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()),
+ btVector3(maxs.x(),mins.y(),mins.z()),
+ btVector3(maxs.x(),maxs.y(),mins.z()),
+ btVector3(mins.x(),maxs.y(),mins.z()),
+ btVector3(mins.x(),mins.y(),maxs.z()),
+ btVector3(maxs.x(),mins.y(),maxs.z()),
+ btVector3(maxs.x(),maxs.y(),maxs.z()),
+ btVector3(mins.x(),maxs.y(),maxs.z())};
+idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color);
+idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color);
+idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color);
+idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color);
+idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color);
+idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color);
+}
+
+//
+static void drawTree( btIDebugDraw* idraw,
+ const btDbvtNode* node,
+ int depth,
+ const btVector3& ncolor,
+ const btVector3& lcolor,
+ int mindepth,
+ int maxdepth)
+{
+if(node)
+ {
+ if(node->isinternal()&&((depth<maxdepth)||(maxdepth<0)))
+ {
+ drawTree(idraw,node->childs[0],depth+1,ncolor,lcolor,mindepth,maxdepth);
+ drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth);
+ }
+ if(depth>=mindepth)
+ {
+ const btScalar scl=(btScalar)(node->isinternal()?1:1);
+ const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl;
+ const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl;
+ drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor);
+ }
+ }
+}
+
+//
+template <typename T>
+static inline T sum(const btAlignedObjectArray<T>& items)
+{
+T v;
+if(items.size())
+ {
+ v=items[0];
+ for(int i=1,ni=items.size();i<ni;++i)
+ {
+ v+=items[i];
+ }
+ }
+return(v);
+}
+
+//
+template <typename T,typename Q>
+static inline void add(btAlignedObjectArray<T>& items,const Q& value)
+{
+for(int i=0,ni=items.size();i<ni;++i)
+ {
+ items[i]+=value;
+ }
+}
+
+//
+template <typename T,typename Q>
+static inline void mul(btAlignedObjectArray<T>& items,const Q& value)
+{
+for(int i=0,ni=items.size();i<ni;++i)
+ {
+ items[i]*=value;
+ }
+}
+
+//
+template <typename T>
+static inline T average(const btAlignedObjectArray<T>& items)
+{
+const btScalar n=(btScalar)(items.size()>0?items.size():1);
+return(sum(items)/n);
+}
+
+//
+static inline btScalar tetravolume(const btVector3& x0,
+ const btVector3& x1,
+ const btVector3& x2,
+ const btVector3& x3)
+{
+ const btVector3 a=x1-x0;
+ const btVector3 b=x2-x0;
+ const btVector3 c=x3-x0;
+ return(dot(a,cross(b,c)));
+}
+
+//
+#if 0
+static btVector3 stresscolor(btScalar stress)
+ {
+ static const btVector3 spectrum[]= { btVector3(1,0,1),
+ btVector3(0,0,1),
+ btVector3(0,1,1),
+ btVector3(0,1,0),
+ btVector3(1,1,0),
+ btVector3(1,0,0),
+ btVector3(1,0,0)};
+ static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1;
+ static const btScalar one=1;
+ stress=btMax<btScalar>(0,btMin<btScalar>(1,stress))*ncolors;
+ const int sel=(int)stress;
+ const btScalar frc=stress-sel;
+ return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
+ }
+#endif
+
+//
+void btSoftBodyHelpers::Draw( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int drawflags)
+{
+ const btScalar scl=(btScalar)0.1;
+ const btScalar nscl=scl*5;
+ const btVector3 lcolor=btVector3(0,0,0);
+ const btVector3 ncolor=btVector3(1,1,1);
+ const btVector3 ccolor=btVector3(1,0,0);
+ int i,j,nj;
+
+ /* Nodes */
+ if(0!=(drawflags&fDrawFlags::Nodes))
+ {
+ for(i=0;i<psb->m_nodes.size();++i)
+ {
+ const btSoftBody::Node& n=psb->m_nodes[i];
+ if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
+ idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0));
+ idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0));
+ idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1));
+ }
+ }
+ /* Links */
+ if(0!=(drawflags&fDrawFlags::Links))
+ {
+ for(i=0;i<psb->m_links.size();++i)
+ {
+ const btSoftBody::Link& l=psb->m_links[i];
+ if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
+ idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor);
+ }
+ }
+ /* Normals */
+ if(0!=(drawflags&fDrawFlags::Normals))
+ {
+ for(i=0;i<psb->m_nodes.size();++i)
+ {
+ const btSoftBody::Node& n=psb->m_nodes[i];
+ if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
+ const btVector3 d=n.m_n*nscl;
+ idraw->drawLine(n.m_x,n.m_x+d,ncolor);
+ idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5);
+ }
+ }
+ /* Contacts */
+ if(0!=(drawflags&fDrawFlags::Contacts))
+ {
+ static const btVector3 axis[]={btVector3(1,0,0),
+ btVector3(0,1,0),
+ btVector3(0,0,1)};
+ for(i=0;i<psb->m_rcontacts.size();++i)
+ {
+ const btSoftBody::RContact& c=psb->m_rcontacts[i];
+ const btVector3 o= c.m_node->m_x-c.m_cti.m_normal*
+ (dot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset);
+ const btVector3 x=cross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized();
+ const btVector3 y=cross(x,c.m_cti.m_normal).normalized();
+ idraw->drawLine(o-x*nscl,o+x*nscl,ccolor);
+ idraw->drawLine(o-y*nscl,o+y*nscl,ccolor);
+ idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0));
+ }
+ }
+ /* Anchors */
+ if(0!=(drawflags&fDrawFlags::Anchors))
+ {
+ for(i=0;i<psb->m_anchors.size();++i)
+ {
+ const btSoftBody::Anchor& a=psb->m_anchors[i];
+ const btVector3 q=a.m_body->getWorldTransform()*a.m_local;
+ drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0));
+ drawVertex(idraw,q,0.25,btVector3(0,1,0));
+ idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1));
+ }
+ for(i=0;i<psb->m_nodes.size();++i)
+ {
+ const btSoftBody::Node& n=psb->m_nodes[i];
+ if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
+ if(n.m_im<=0)
+ {
+ drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0));
+ }
+ }
+ }
+ /* Faces */
+ if(0!=(drawflags&fDrawFlags::Faces))
+ {
+ const btScalar scl=(btScalar)0.8;
+ const btScalar alp=(btScalar)1;
+ const btVector3 col(0,(btScalar)0.7,0);
+ for(i=0;i<psb->m_faces.size();++i)
+ {
+ const btSoftBody::Face& f=psb->m_faces[i];
+ if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue;
+ const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x};
+ const btVector3 c=(x[0]+x[1]+x[2])/3;
+ idraw->drawTriangle((x[0]-c)*scl+c,
+ (x[1]-c)*scl+c,
+ (x[2]-c)*scl+c,
+ col,alp);
+ }
+ }
+ /* Clusters */
+ if(0!=(drawflags&fDrawFlags::Clusters))
+ {
+ srand(1806);
+ for(i=0;i<psb->m_clusters.size();++i)
+ {
+ if(psb->m_clusters[i]->m_collide)
+ {
+ btVector3 color( rand()/(btScalar)RAND_MAX,
+ rand()/(btScalar)RAND_MAX,
+ rand()/(btScalar)RAND_MAX);
+ color=color.normalized()*0.75;
+ btAlignedObjectArray<btVector3> vertices;
+ vertices.resize(psb->m_clusters[i]->m_nodes.size());
+ for(j=0,nj=vertices.size();j<nj;++j)
+ {
+ vertices[j]=psb->m_clusters[i]->m_nodes[j]->m_x;
+ }
+ HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]);
+ HullResult hres;
+ HullLibrary hlib;
+ hdsc.mMaxVertices=vertices.size();
+ hlib.CreateConvexHull(hdsc,hres);
+ const btVector3 center=average(hres.m_OutputVertices);
+ add(hres.m_OutputVertices,-center);
+ mul(hres.m_OutputVertices,(btScalar)1);
+ add(hres.m_OutputVertices,center);
+ for(j=0;j<(int)hres.mNumFaces;++j)
+ {
+ const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]};
+ idraw->drawTriangle(hres.m_OutputVertices[idx[0]],
+ hres.m_OutputVertices[idx[1]],
+ hres.m_OutputVertices[idx[2]],
+ color,1);
+ }
+ hlib.ReleaseResult(hres);
+ }
+ /* Velocities */
+ #if 0
+ for(int j=0;j<psb->m_clusters[i].m_nodes.size();++j)
+ {
+ const btSoftBody::Cluster& c=psb->m_clusters[i];
+ const btVector3 r=c.m_nodes[j]->m_x-c.m_com;
+ const btVector3 v=c.m_lv+cross(c.m_av,r);
+ idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0));
+ }
+ #endif
+ /* Frame */
+ btSoftBody::Cluster& c=*psb->m_clusters[i];
+ idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0));
+ idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0));
+ idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1));
+ }
+ }
+ /* Notes */
+ if(0!=(drawflags&fDrawFlags::Notes))
+ {
+ for(i=0;i<psb->m_notes.size();++i)
+ {
+ const btSoftBody::Note& n=psb->m_notes[i];
+ btVector3 p=n.m_offset;
+ for(int j=0;j<n.m_rank;++j)
+ {
+ p+=n.m_nodes[j]->m_x*n.m_coords[j];
+ }
+ idraw->draw3dText(p,n.m_text);
+ }
+ }
+ /* Node tree */
+ if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw);
+ /* Face tree */
+ if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw);
+ /* Cluster tree */
+ if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw);
+ /* Joints */
+ if(0!=(drawflags&fDrawFlags::Joints))
+ {
+ for(i=0;i<psb->m_joints.size();++i)
+ {
+ const btSoftBody::Joint* pj=psb->m_joints[i];
+ switch(pj->Type())
+ {
+ case btSoftBody::Joint::eType::Linear:
+ {
+ const btSoftBody::LJoint* pjl=(const btSoftBody::LJoint*)pj;
+ const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0];
+ const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1];
+ idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0));
+ idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1));
+ drawVertex(idraw,a0,0.25,btVector3(1,1,0));
+ drawVertex(idraw,a1,0.25,btVector3(0,1,1));
+ }
+ break;
+ case btSoftBody::Joint::eType::Angular:
+ {
+ const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj;
+ const btVector3 o0=pj->m_bodies[0].xform().getOrigin();
+ const btVector3 o1=pj->m_bodies[1].xform().getOrigin();
+ const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0];
+ const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1];
+ idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0));
+ idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0));
+ idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1));
+ idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1));
+ }
+ }
+ }
+ }
+}
+
+//
+void btSoftBodyHelpers::DrawInfos( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ bool masses,
+ bool areas,
+ bool /*stress*/)
+{
+ /*
+ for(int i=0;i<psb->m_nodes.size();++i)
+ {
+ const btSoftBody::Node& n=psb->m_nodes[i];
+ char text[2048]={0};
+ char buff[1024];
+ if(masses)
+ {
+ sprintf(buff," M(%.2f)",1/n.m_im);
+ strcat(text,buff);
+ }
+ if(areas)
+ {
+ sprintf(buff," A(%.2f)",n.m_area);
+ strcat(text,buff);
+ }
+ if(text[0]) idraw->draw3dText(n.m_x,text);
+ }
+ */
+
+}
+
+//
+void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth,
+ int maxdepth)
+{
+drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth);
+}
+
+//
+void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth,
+ int maxdepth)
+{
+drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth);
+}
+
+//
+void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth,
+ int maxdepth)
+{
+drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth);
+}
+
+//
+void btSoftBodyHelpers::DrawFrame( btSoftBody* psb,
+ btIDebugDraw* idraw)
+{
+ if(psb->m_pose.m_bframe)
+ {
+ static const btScalar ascl=10;
+ static const btScalar nscl=(btScalar)0.1;
+ const btVector3 com=psb->m_pose.m_com;
+ const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl;
+ const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized();
+ const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized();
+ const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized();
+ idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0));
+ idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0));
+ idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1));
+ for(int i=0;i<psb->m_pose.m_pos.size();++i)
+ {
+ const btVector3 x=com+trs*psb->m_pose.m_pos[i];
+ drawVertex(idraw,x,nscl,btVector3(1,0,1));
+ }
+ }
+}
+
+//
+btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from,
+ const btVector3& to,
+ int res,
+ int fixeds)
+{
+ /* Create nodes */
+ const int r=res+2;
+ btVector3* x=new btVector3[r];
+ btScalar* m=new btScalar[r];
+ int i;
+
+ for(i=0;i<r;++i)
+ {
+ const btScalar t=i/(btScalar)(r-1);
+ x[i]=lerp(from,to,t);
+ m[i]=1;
+ }
+ btSoftBody* psb= new btSoftBody(&worldInfo,r,x,m);
+ if(fixeds&1) psb->setMass(0,0);
+ if(fixeds&2) psb->setMass(r-1,0);
+ delete[] x;
+ delete[] m;
+ /* Create links */
+ for(i=1;i<r;++i)
+ {
+ psb->appendLink(i-1,i);
+ }
+ /* Finished */
+ return(psb);
+}
+
+//
+btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00,
+ const btVector3& corner10,
+ const btVector3& corner01,
+ const btVector3& corner11,
+ int resx,
+ int resy,
+ int fixeds,
+ bool gendiags)
+{
+#define IDX(_x_,_y_) ((_y_)*rx+(_x_))
+ /* Create nodes */
+ if((resx<2)||(resy<2)) return(0);
+ const int rx=resx;
+ const int ry=resy;
+ const int tot=rx*ry;
+ btVector3* x=new btVector3[tot];
+ btScalar* m=new btScalar[tot];
+ int iy;
+
+ for(iy=0;iy<ry;++iy)
+ {
+ const btScalar ty=iy/(btScalar)(ry-1);
+ const btVector3 py0=lerp(corner00,corner01,ty);
+ const btVector3 py1=lerp(corner10,corner11,ty);
+ for(int ix=0;ix<rx;++ix)
+ {
+ const btScalar tx=ix/(btScalar)(rx-1);
+ x[IDX(ix,iy)]=lerp(py0,py1,tx);
+ m[IDX(ix,iy)]=1;
+ }
+ }
+ btSoftBody* psb=new btSoftBody(&worldInfo,tot,x,m);
+ if(fixeds&1) psb->setMass(IDX(0,0),0);
+ if(fixeds&2) psb->setMass(IDX(rx-1,0),0);
+ if(fixeds&4) psb->setMass(IDX(0,ry-1),0);
+ if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0);
+ delete[] x;
+ delete[] m;
+ /* Create links and faces */
+ for(iy=0;iy<ry;++iy)
+ {
+ for(int ix=0;ix<rx;++ix)
+ {
+ const int idx=IDX(ix,iy);
+ const bool mdx=(ix+1)<rx;
+ const bool mdy=(iy+1)<ry;
+ if(mdx) psb->appendLink(idx,IDX(ix+1,iy));
+ if(mdy) psb->appendLink(idx,IDX(ix,iy+1));
+ if(mdx&&mdy)
+ {
+ if((ix+iy)&1)
+ {
+ psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1));
+ psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1));
+ if(gendiags)
+ {
+ psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1));
+ }
+ }
+ else
+ {
+ psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy));
+ psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1));
+ if(gendiags)
+ {
+ psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1));
+ }
+ }
+ }
+ }
+ }
+ /* Finished */
+#undef IDX
+ return(psb);
+}
+
+//
+btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center,
+ const btVector3& radius,
+ int res)
+{
+ struct Hammersley
+ {
+ static void Generate(btVector3* x,int n)
+ {
+ for(int i=0;i<n;i++)
+ {
+ btScalar p=0.5,t=0;
+ for(int j=i;j;p*=0.5,j>>=1) if(j&1) t+=p;
+ btScalar w=2*t-1;
+ btScalar a=(SIMD_PI+2*i*SIMD_PI)/n;
+ btScalar s=btSqrt(1-w*w);
+ *x++=btVector3(s*btCos(a),s*btSin(a),w);
+ }
+ }
+ };
+ btAlignedObjectArray<btVector3> vtx;
+ vtx.resize(3+res);
+ Hammersley::Generate(&vtx[0],vtx.size());
+ for(int i=0;i<vtx.size();++i)
+ {
+ vtx[i]=vtx[i]*radius+center;
+ }
+ return(CreateFromConvexHull(worldInfo,&vtx[0],vtx.size()));
+}
+
+
+
+//
+btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo,const btScalar* vertices,
+ const int* triangles,
+ int ntriangles)
+{
+ int maxidx=0;
+ int i,j,ni;
+
+ for(i=0,ni=ntriangles*3;i<ni;++i)
+ {
+ maxidx=btMax(triangles[i],maxidx);
+ }
+ ++maxidx;
+ btAlignedObjectArray<bool> chks;
+ btAlignedObjectArray<btVector3> vtx;
+ chks.resize(maxidx*maxidx,false);
+ vtx.resize(maxidx);
+ for(i=0,j=0,ni=maxidx*3;i<ni;++j,i+=3)
+ {
+ vtx[j]=btVector3(vertices[i],vertices[i+1],vertices[i+2]);
+ }
+ btSoftBody* psb=new btSoftBody(&worldInfo,vtx.size(),&vtx[0],0);
+ for( i=0,ni=ntriangles*3;i<ni;i+=3)
+ {
+ const int idx[]={triangles[i],triangles[i+1],triangles[i+2]};
+#define IDX(_x_,_y_) ((_y_)*maxidx+(_x_))
+ for(int j=2,k=0;k<3;j=k++)
+ {
+ if(!chks[IDX(idx[j],idx[k])])
+ {
+ chks[IDX(idx[j],idx[k])]=true;
+ chks[IDX(idx[k],idx[k])]=true;
+ psb->appendLink(idx[j],idx[k]);
+ }
+ }
+#undef IDX
+ psb->appendFace(idx[0],idx[1],idx[2]);
+ }
+ psb->randomizeConstraints();
+ return(psb);
+}
+
+//
+btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
+ int nvertices)
+{
+ HullDesc hdsc(QF_TRIANGLES,nvertices,vertices);
+ HullResult hres;
+ HullLibrary hlib;/*??*/
+ hdsc.mMaxVertices=nvertices;
+ hlib.CreateConvexHull(hdsc,hres);
+ btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices,
+ &hres.m_OutputVertices[0],0);
+ for(int i=0;i<(int)hres.mNumFaces;++i)
+ {
+ const int idx[]={ hres.m_Indices[i*3+0],
+ hres.m_Indices[i*3+1],
+ hres.m_Indices[i*3+2]};
+ if(idx[0]<idx[1]) psb->appendLink( idx[0],idx[1]);
+ if(idx[1]<idx[2]) psb->appendLink( idx[1],idx[2]);
+ if(idx[2]<idx[0]) psb->appendLink( idx[2],idx[0]);
+ psb->appendFace(idx[0],idx[1],idx[2]);
+ }
+ hlib.ReleaseResult(hres);
+ psb->randomizeConstraints();
+ return(psb);
+}
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h
new file mode 100644
index 00000000000..e9c6cb20657
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 SOFT_BODY_HELPERS_H
+#define SOFT_BODY_HELPERS_H
+
+#include "btSoftBody.h"
+
+//
+// Helpers
+//
+
+/* fDrawFlags */
+struct fDrawFlags { enum _ {
+ Nodes = 0x0001,
+ Links = 0x0002,
+ Faces = 0x0004,
+ Tetras = 0x0008,
+ Normals = 0x0010,
+ Contacts = 0x0020,
+ Anchors = 0x0040,
+ Notes = 0x0080,
+ Clusters = 0x0100,
+ NodeTree = 0x0200,
+ FaceTree = 0x0400,
+ ClusterTree = 0x0800,
+ Joints = 0x1000,
+ /* presets */
+ Std = Links+Faces+Tetras+Anchors+Notes+Joints,
+ StdTetra = Std-Faces+Tetras,
+};};
+
+struct btSoftBodyHelpers
+{
+ /* Draw body */
+ static void Draw( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int drawflags=fDrawFlags::Std);
+ /* Draw body infos */
+ static void DrawInfos( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ bool masses,
+ bool areas,
+ bool stress);
+ /* Draw node tree */
+ static void DrawNodeTree( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth=0,
+ int maxdepth=-1);
+ /* Draw face tree */
+ static void DrawFaceTree( btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth=0,
+ int maxdepth=-1);
+ /* Draw cluster tree */
+ static void DrawClusterTree(btSoftBody* psb,
+ btIDebugDraw* idraw,
+ int mindepth=0,
+ int maxdepth=-1);
+ /* Draw rigid frame */
+ static void DrawFrame( btSoftBody* psb,
+ btIDebugDraw* idraw);
+ /* Create a rope */
+ static btSoftBody* CreateRope( btSoftBodyWorldInfo& worldInfo,
+ const btVector3& from,
+ const btVector3& to,
+ int res,
+ int fixeds);
+ /* Create a patch */
+ static btSoftBody* CreatePatch(btSoftBodyWorldInfo& worldInfo,
+ const btVector3& corner00,
+ const btVector3& corner10,
+ const btVector3& corner01,
+ const btVector3& corner11,
+ int resx,
+ int resy,
+ int fixeds,
+ bool gendiags);
+ /* Create an ellipsoid */
+ static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,
+ const btVector3& center,
+ const btVector3& radius,
+ int res);
+ /* Create from trimesh */
+ static btSoftBody* CreateFromTriMesh( btSoftBodyWorldInfo& worldInfo,
+ const btScalar* vertices,
+ const int* triangles,
+ int ntriangles);
+ /* Create from convex-hull */
+ static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo,
+ const btVector3* vertices,
+ int nvertices);
+};
+
+#endif //SOFT_BODY_HELPERS_H
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h
new file mode 100644
index 00000000000..0c87770d714
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h
@@ -0,0 +1,895 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btSoftBody implementation by Nathanael Presson
+
+#ifndef _BT_SOFT_BODY_INTERNALS_H
+#define _BT_SOFT_BODY_INTERNALS_H
+
+#include "btSoftBody.h"
+
+#include "LinearMath/btQuickprof.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+
+//
+// btSymMatrix
+//
+template <typename T>
+struct btSymMatrix
+{
+ btSymMatrix() : dim(0) {}
+ btSymMatrix(int n,const T& init=T()) { resize(n,init); }
+void resize(int n,const T& init=T()) { dim=n;store.resize((n*(n+1))/2,init); }
+int index(int c,int r) const { if(c>r) btSwap(c,r);btAssert(r<dim);return((r*(r+1))/2+c); }
+T& operator()(int c,int r) { return(store[index(c,r)]); }
+const T& operator()(int c,int r) const { return(store[index(c,r)]); }
+btAlignedObjectArray<T> store;
+int dim;
+};
+
+//
+// btSoftBodyCollisionShape
+//
+class btSoftBodyCollisionShape : public btConcaveShape
+{
+public:
+ btSoftBody* m_body;
+
+ btSoftBodyCollisionShape(btSoftBody* backptr)
+ {
+ m_body=backptr;
+ }
+
+ virtual ~btSoftBodyCollisionShape()
+ {
+
+ }
+
+ void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const
+ {
+ //not yet
+ btAssert(0);
+ }
+
+ ///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
+ {
+ /* t should be identity, but better be safe than...fast? */
+ const btVector3 mins=m_body->m_bounds[0];
+ const btVector3 maxs=m_body->m_bounds[1];
+ const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()),
+ t*btVector3(maxs.x(),mins.y(),mins.z()),
+ t*btVector3(maxs.x(),maxs.y(),mins.z()),
+ t*btVector3(mins.x(),maxs.y(),mins.z()),
+ t*btVector3(mins.x(),mins.y(),maxs.z()),
+ t*btVector3(maxs.x(),mins.y(),maxs.z()),
+ t*btVector3(maxs.x(),maxs.y(),maxs.z()),
+ t*btVector3(mins.x(),maxs.y(),maxs.z())};
+ aabbMin=aabbMax=crns[0];
+ for(int i=1;i<8;++i)
+ {
+ aabbMin.setMin(crns[i]);
+ aabbMax.setMax(crns[i]);
+ }
+ }
+
+ virtual int getShapeType() const
+ {
+ return SOFTBODY_SHAPE_PROXYTYPE;
+ }
+ virtual void setLocalScaling(const btVector3& /*scaling*/)
+ {
+ ///na
+ btAssert(0);
+ }
+ virtual const btVector3& getLocalScaling() const
+ {
+ static const btVector3 dummy(1,1,1);
+ return dummy;
+ }
+ virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const
+ {
+ ///not yet
+ btAssert(0);
+ }
+ virtual const char* getName()const
+ {
+ return "SoftBody";
+ }
+
+};
+
+//
+// btSoftClusterCollisionShape
+//
+class btSoftClusterCollisionShape : public btConvexInternalShape
+{
+public:
+ const btSoftBody::Cluster* m_cluster;
+
+ btSoftClusterCollisionShape (const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); }
+
+
+ virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
+ {
+ btSoftBody::Node* const * n=&m_cluster->m_nodes[0];
+ btScalar d=dot(vec,n[0]->m_x);
+ int j=0;
+ for(int i=1,ni=m_cluster->m_nodes.size();i<ni;++i)
+ {
+ const btScalar k=dot(vec,n[i]->m_x);
+ if(k>d) { d=k;j=i; }
+ }
+ return(n[j]->m_x);
+ }
+ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+ {
+ return(localGetSupportingVertex(vec));
+ }
+ //notice that the vectors should be unit length
+ virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+ {}
+
+
+ virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const
+ {}
+
+ virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+ {}
+
+ virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; }
+
+ //debugging
+ virtual const char* getName()const {return "SOFTCLUSTER";}
+
+ virtual void setMargin(btScalar margin)
+ {
+ btConvexInternalShape::setMargin(margin);
+ }
+ virtual btScalar getMargin() const
+ {
+ return getMargin();
+ }
+};
+
+//
+// Inline's
+//
+
+//
+template <typename T>
+static inline void ZeroInitialize(T& value)
+{
+static const T zerodummy;
+value=zerodummy;
+}
+//
+template <typename T>
+static inline bool CompLess(const T& a,const T& b)
+{ return(a<b); }
+//
+template <typename T>
+static inline bool CompGreater(const T& a,const T& b)
+{ return(a>b); }
+//
+template <typename T>
+static inline T Lerp(const T& a,const T& b,btScalar t)
+{ return(a+(b-a)*t); }
+//
+template <typename T>
+static inline T InvLerp(const T& a,const T& b,btScalar t)
+{ return((b+a*t-b*t)/(a*b)); }
+//
+static inline btMatrix3x3 Lerp( const btMatrix3x3& a,
+ const btMatrix3x3& b,
+ btScalar t)
+{
+btMatrix3x3 r;
+r[0]=Lerp(a[0],b[0],t);
+r[1]=Lerp(a[1],b[1],t);
+r[2]=Lerp(a[2],b[2],t);
+return(r);
+}
+//
+static inline btVector3 Clamp(const btVector3& v,btScalar maxlength)
+{
+const btScalar sql=v.length2();
+if(sql>(maxlength*maxlength))
+ return((v*maxlength)/btSqrt(sql));
+ else
+ return(v);
+}
+//
+template <typename T>
+static inline T Clamp(const T& x,const T& l,const T& h)
+{ return(x<l?l:x>h?h:x); }
+//
+template <typename T>
+static inline T Sq(const T& x)
+{ return(x*x); }
+//
+template <typename T>
+static inline T Cube(const T& x)
+{ return(x*x*x); }
+//
+template <typename T>
+static inline T Sign(const T& x)
+{ return((T)(x<0?-1:+1)); }
+//
+template <typename T>
+static inline bool SameSign(const T& x,const T& y)
+{ return((x*y)>0); }
+//
+static inline btScalar ClusterMetric(const btVector3& x,const btVector3& y)
+{
+const btVector3 d=x-y;
+return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2]));
+}
+//
+static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s)
+{
+ const btScalar xx=a.x()*a.x();
+ const btScalar yy=a.y()*a.y();
+ const btScalar zz=a.z()*a.z();
+ const btScalar xy=a.x()*a.y();
+ const btScalar yz=a.y()*a.z();
+ const btScalar zx=a.z()*a.x();
+ btMatrix3x3 m;
+ m[0]=btVector3(1-xx+xx*s,xy*s-xy,zx*s-zx);
+ m[1]=btVector3(xy*s-xy,1-yy+yy*s,yz*s-yz);
+ m[2]=btVector3(zx*s-zx,yz*s-yz,1-zz+zz*s);
+ return(m);
+}
+//
+static inline btMatrix3x3 Cross(const btVector3& v)
+{
+ btMatrix3x3 m;
+ m[0]=btVector3(0,-v.z(),+v.y());
+ m[1]=btVector3(+v.z(),0,-v.x());
+ m[2]=btVector3(-v.y(),+v.x(),0);
+ return(m);
+}
+//
+static inline btMatrix3x3 Diagonal(btScalar x)
+{
+ btMatrix3x3 m;
+ m[0]=btVector3(x,0,0);
+ m[1]=btVector3(0,x,0);
+ m[2]=btVector3(0,0,x);
+ return(m);
+}
+//
+static inline btMatrix3x3 Add(const btMatrix3x3& a,
+ const btMatrix3x3& b)
+{
+ btMatrix3x3 r;
+ for(int i=0;i<3;++i) r[i]=a[i]+b[i];
+ return(r);
+}
+//
+static inline btMatrix3x3 Sub(const btMatrix3x3& a,
+ const btMatrix3x3& b)
+{
+ btMatrix3x3 r;
+ for(int i=0;i<3;++i) r[i]=a[i]-b[i];
+ return(r);
+}
+//
+static inline btMatrix3x3 Mul(const btMatrix3x3& a,
+ btScalar b)
+{
+ btMatrix3x3 r;
+ for(int i=0;i<3;++i) r[i]=a[i]*b;
+ return(r);
+}
+//
+static inline void Orthogonalize(btMatrix3x3& m)
+{
+m[2]=cross(m[0],m[1]).normalized();
+m[1]=cross(m[2],m[0]).normalized();
+m[0]=cross(m[1],m[2]).normalized();
+}
+//
+static inline btMatrix3x3 MassMatrix(btScalar im,const btMatrix3x3& iwi,const btVector3& r)
+{
+ const btMatrix3x3 cr=Cross(r);
+ return(Sub(Diagonal(im),cr*iwi*cr));
+}
+
+//
+static inline btMatrix3x3 ImpulseMatrix( btScalar dt,
+ btScalar ima,
+ btScalar imb,
+ const btMatrix3x3& iwi,
+ const btVector3& r)
+{
+ return(Diagonal(1/dt)*Add(Diagonal(ima),MassMatrix(imb,iwi,r)).inverse());
+}
+
+//
+static inline btMatrix3x3 ImpulseMatrix( btScalar ima,const btMatrix3x3& iia,const btVector3& ra,
+ btScalar imb,const btMatrix3x3& iib,const btVector3& rb)
+{
+return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse());
+}
+
+//
+static inline btMatrix3x3 AngularImpulseMatrix( const btMatrix3x3& iia,
+ const btMatrix3x3& iib)
+{
+return(Add(iia,iib).inverse());
+}
+
+//
+static inline btVector3 ProjectOnAxis( const btVector3& v,
+ const btVector3& a)
+{
+ return(a*dot(v,a));
+}
+//
+static inline btVector3 ProjectOnPlane( const btVector3& v,
+ const btVector3& a)
+{
+ return(v-ProjectOnAxis(v,a));
+}
+
+//
+static inline void ProjectOrigin( const btVector3& a,
+ const btVector3& b,
+ btVector3& prj,
+ btScalar& sqd)
+{
+const btVector3 d=b-a;
+const btScalar m2=d.length2();
+if(m2>SIMD_EPSILON)
+ {
+ const btScalar t=Clamp<btScalar>(-dot(a,d)/m2,0,1);
+ const btVector3 p=a+d*t;
+ const btScalar l2=p.length2();
+ if(l2<sqd)
+ {
+ prj=p;
+ sqd=l2;
+ }
+ }
+}
+//
+static inline void ProjectOrigin( const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ btVector3& prj,
+ btScalar& sqd)
+{
+const btVector3& q=cross(b-a,c-a);
+const btScalar m2=q.length2();
+if(m2>SIMD_EPSILON)
+ {
+ const btVector3 n=q/btSqrt(m2);
+ const btScalar k=dot(a,n);
+ const btScalar k2=k*k;
+ if(k2<sqd)
+ {
+ const btVector3 p=n*k;
+ if( (dot(cross(a-p,b-p),q)>0)&&
+ (dot(cross(b-p,c-p),q)>0)&&
+ (dot(cross(c-p,a-p),q)>0))
+ {
+ prj=p;
+ sqd=k2;
+ }
+ else
+ {
+ ProjectOrigin(a,b,prj,sqd);
+ ProjectOrigin(b,c,prj,sqd);
+ ProjectOrigin(c,a,prj,sqd);
+ }
+ }
+ }
+}
+
+//
+template <typename T>
+static inline T BaryEval( const T& a,
+ const T& b,
+ const T& c,
+ const btVector3& coord)
+{
+ return(a*coord.x()+b*coord.y()+c*coord.z());
+}
+//
+static inline btVector3 BaryCoord( const btVector3& a,
+ const btVector3& b,
+ const btVector3& c,
+ const btVector3& p)
+{
+const btScalar w[]={ cross(a-p,b-p).length(),
+ cross(b-p,c-p).length(),
+ cross(c-p,a-p).length()};
+const btScalar isum=1/(w[0]+w[1]+w[2]);
+return(btVector3(w[1]*isum,w[2]*isum,w[0]*isum));
+}
+
+//
+static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn,
+ const btVector3& a,
+ const btVector3& b,
+ const btScalar accuracy,
+ const int maxiterations=256)
+{
+btScalar span[2]={0,1};
+btScalar values[2]={fn->Eval(a),fn->Eval(b)};
+if(values[0]>values[1])
+ {
+ btSwap(span[0],span[1]);
+ btSwap(values[0],values[1]);
+ }
+if(values[0]>-accuracy) return(-1);
+if(values[1]<+accuracy) return(-1);
+for(int i=0;i<maxiterations;++i)
+ {
+ const btScalar t=Lerp(span[0],span[1],values[0]/(values[0]-values[1]));
+ const btScalar v=fn->Eval(Lerp(a,b,t));
+ if((t<=0)||(t>=1)) break;
+ if(btFabs(v)<accuracy) return(t);
+ if(v<0)
+ { span[0]=t;values[0]=v; }
+ else
+ { span[1]=t;values[1]=v; }
+ }
+return(-1);
+}
+
+//
+static inline btVector3 NormalizeAny(const btVector3& v)
+{
+ const btScalar l=v.length();
+ if(l>SIMD_EPSILON)
+ return(v/l);
+ else
+ return(btVector3(0,0,0));
+}
+
+//
+static inline btDbvtVolume VolumeOf( const btSoftBody::Face& f,
+ btScalar margin)
+{
+const btVector3* pts[]={ &f.m_n[0]->m_x,
+ &f.m_n[1]->m_x,
+ &f.m_n[2]->m_x};
+btDbvtVolume vol=btDbvtVolume::FromPoints(pts,3);
+vol.Expand(btVector3(margin,margin,margin));
+return(vol);
+}
+
+//
+static inline btVector3 CenterOf( const btSoftBody::Face& f)
+{
+return((f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3);
+}
+
+//
+static inline btScalar AreaOf( const btVector3& x0,
+ const btVector3& x1,
+ const btVector3& x2)
+{
+ const btVector3 a=x1-x0;
+ const btVector3 b=x2-x0;
+ const btVector3 cr=cross(a,b);
+ const btScalar area=cr.length();
+ return(area);
+}
+
+//
+static inline btScalar VolumeOf( const btVector3& x0,
+ const btVector3& x1,
+ const btVector3& x2,
+ const btVector3& x3)
+{
+ const btVector3 a=x1-x0;
+ const btVector3 b=x2-x0;
+ const btVector3 c=x3-x0;
+ return(dot(a,cross(b,c)));
+}
+
+//
+static void EvaluateMedium( const btSoftBodyWorldInfo* wfi,
+ const btVector3& x,
+ btSoftBody::sMedium& medium)
+{
+ medium.m_velocity = btVector3(0,0,0);
+ medium.m_pressure = 0;
+ medium.m_density = wfi->air_density;
+ if(wfi->water_density>0)
+ {
+ const btScalar depth=-(dot(x,wfi->water_normal)+wfi->water_offset);
+ if(depth>0)
+ {
+ medium.m_density = wfi->water_density;
+ medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length();
+ }
+ }
+}
+
+//
+static inline void ApplyClampedForce( btSoftBody::Node& n,
+ const btVector3& f,
+ btScalar dt)
+{
+ const btScalar dtim=dt*n.m_im;
+ if((f*dtim).length2()>n.m_v.length2())
+ {/* Clamp */
+ n.m_f-=ProjectOnAxis(n.m_v,f.normalized())/dtim;
+ }
+ else
+ {/* Apply */
+ n.m_f+=f;
+ }
+}
+
+//
+static inline int MatchEdge( const btSoftBody::Node* a,
+ const btSoftBody::Node* b,
+ const btSoftBody::Node* ma,
+ const btSoftBody::Node* mb)
+{
+if((a==ma)&&(b==mb)) return(0);
+if((a==mb)&&(b==ma)) return(1);
+return(-1);
+}
+
+//
+// btEigen : Extract eigen system,
+// straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html
+// outputs are NOT sorted.
+//
+struct btEigen
+{
+static int system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0)
+ {
+ static const int maxiterations=16;
+ static const btScalar accuracy=(btScalar)0.0001;
+ btMatrix3x3& v=*vectors;
+ int iterations=0;
+ vectors->setIdentity();
+ do {
+ int p=0,q=1;
+ if(btFabs(a[p][q])<btFabs(a[0][2])) { p=0;q=2; }
+ if(btFabs(a[p][q])<btFabs(a[1][2])) { p=1;q=2; }
+ if(btFabs(a[p][q])>accuracy)
+ {
+ const btScalar w=(a[q][q]-a[p][p])/(2*a[p][q]);
+ const btScalar z=btFabs(w);
+ const btScalar t=w/(z*(btSqrt(1+w*w)+z));
+ if(t==t)/* [WARNING] let hope that one does not get thrown aways by some compilers... */
+ {
+ const btScalar c=1/btSqrt(t*t+1);
+ const btScalar s=c*t;
+ mulPQ(a,c,s,p,q);
+ mulTPQ(a,c,s,p,q);
+ mulPQ(v,c,s,p,q);
+ } else break;
+ } else break;
+ } while((++iterations)<maxiterations);
+ if(values)
+ {
+ *values=btVector3(a[0][0],a[1][1],a[2][2]);
+ }
+ return(iterations);
+ }
+private:
+static inline void mulTPQ(btMatrix3x3& a,btScalar c,btScalar s,int p,int q)
+ {
+ const btScalar m[2][3]={ {a[p][0],a[p][1],a[p][2]},
+ {a[q][0],a[q][1],a[q][2]}};
+ int i;
+
+ for(i=0;i<3;++i) a[p][i]=c*m[0][i]-s*m[1][i];
+ for(i=0;i<3;++i) a[q][i]=c*m[1][i]+s*m[0][i];
+ }
+static inline void mulPQ(btMatrix3x3& a,btScalar c,btScalar s,int p,int q)
+ {
+ const btScalar m[2][3]={ {a[0][p],a[1][p],a[2][p]},
+ {a[0][q],a[1][q],a[2][q]}};
+ int i;
+
+ for(i=0;i<3;++i) a[i][p]=c*m[0][i]-s*m[1][i];
+ for(i=0;i<3;++i) a[i][q]=c*m[1][i]+s*m[0][i];
+ }
+};
+
+//
+// Polar decomposition,
+// "Computing the Polar Decomposition with Applications", Nicholas J. Higham, 1986.
+//
+static inline int PolarDecompose( const btMatrix3x3& m,btMatrix3x3& q,btMatrix3x3& s)
+{
+ static const btScalar half=(btScalar)0.5;
+ static const btScalar accuracy=(btScalar)0.0001;
+ static const int maxiterations=16;
+ int i=0;
+ btScalar det=0;
+ q = Mul(m,1/btVector3(m[0][0],m[1][1],m[2][2]).length());
+ det = q.determinant();
+ if(!btFuzzyZero(det))
+ {
+ for(;i<maxiterations;++i)
+ {
+ q=Mul(Add(q,Mul(q.adjoint(),1/det).transpose()),half);
+ const btScalar ndet=q.determinant();
+ if(Sq(ndet-det)>accuracy) det=ndet; else break;
+ }
+ /* Final orthogonalization */
+ Orthogonalize(q);
+ /* Compute 'S' */
+ s=q.transpose()*m;
+ }
+ else
+ {
+ q.setIdentity();
+ s.setIdentity();
+ }
+return(i);
+}
+
+//
+// btSoftColliders
+//
+struct btSoftColliders
+{
+ //
+ // ClusterBase
+ //
+ struct ClusterBase : btDbvt::ICollide
+ {
+ btScalar erp;
+ btScalar idt;
+ btScalar margin;
+ btScalar friction;
+ btScalar threshold;
+ ClusterBase()
+ {
+ erp =(btScalar)1;
+ idt =0;
+ margin =0;
+ friction =0;
+ threshold =(btScalar)0;
+ }
+ bool SolveContact( const btGjkEpaSolver2::sResults& res,
+ btSoftBody::Body ba,btSoftBody::Body bb,
+ btSoftBody::CJoint& joint)
+ {
+ if(res.distance<margin)
+ {
+ const btVector3 ra=res.witnesses[0]-ba.xform().getOrigin();
+ const btVector3 rb=res.witnesses[1]-bb.xform().getOrigin();
+ const btVector3 va=ba.velocity(ra);
+ const btVector3 vb=bb.velocity(rb);
+ const btVector3 vrel=va-vb;
+ const btScalar rvac=dot(vrel,res.normal);
+ const btScalar depth=res.distance-margin;
+ const btVector3 iv=res.normal*rvac;
+ const btVector3 fv=vrel-iv;
+ joint.m_bodies[0] = ba;
+ joint.m_bodies[1] = bb;
+ joint.m_refs[0] = ra*ba.xform().getBasis();
+ joint.m_refs[1] = rb*bb.xform().getBasis();
+ joint.m_rpos[0] = ra;
+ joint.m_rpos[1] = rb;
+ joint.m_cfm = 1;
+ joint.m_erp = 1;
+ joint.m_life = 0;
+ joint.m_maxlife = 0;
+ joint.m_split = 1;
+ joint.m_drift = depth*res.normal;
+ joint.m_normal = res.normal;
+ joint.m_delete = false;
+ joint.m_friction = fv.length2()<(-rvac*friction)?1:friction;
+ joint.m_massmatrix = ImpulseMatrix( ba.invMass(),ba.invWorldInertia(),joint.m_rpos[0],
+ bb.invMass(),bb.invWorldInertia(),joint.m_rpos[1]);
+ return(true);
+ }
+ return(false);
+ }
+ };
+ //
+ // CollideCL_RS
+ //
+ struct CollideCL_RS : ClusterBase
+ {
+ btSoftBody* psb;
+ btRigidBody* prb;
+ void Process(const btDbvtNode* leaf)
+ {
+ btSoftBody::Cluster* cluster=(btSoftBody::Cluster*)leaf->data;
+ btSoftClusterCollisionShape cshape(cluster);
+ const btConvexShape* rshape=(const btConvexShape*)prb->getCollisionShape();
+ btGjkEpaSolver2::sResults res;
+ if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(),
+ rshape,prb->getInterpolationWorldTransform(),
+ btVector3(1,0,0),res))
+ {
+ btSoftBody::CJoint joint;
+ if(SolveContact(res,cluster,prb,joint))
+ {
+ btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
+ *pj=joint;psb->m_joints.push_back(pj);
+ if(prb->isStaticOrKinematicObject())
+ {
+ pj->m_erp *= psb->m_cfg.kSKHR_CL;
+ pj->m_split *= psb->m_cfg.kSK_SPLT_CL;
+ }
+ else
+ {
+ pj->m_erp *= psb->m_cfg.kSRHR_CL;
+ pj->m_split *= psb->m_cfg.kSR_SPLT_CL;
+ }
+ }
+ }
+ }
+ void Process(btSoftBody* ps,btRigidBody* pr)
+ {
+ psb = ps;
+ prb = pr;
+ idt = ps->m_sst.isdt;
+ margin = ps->getCollisionShape()->getMargin()+
+ pr->getCollisionShape()->getMargin();
+ friction = btMin(psb->m_cfg.kDF,prb->getFriction());
+ btVector3 mins;
+ btVector3 maxs;
+ btDbvtVolume volume;
+ pr->getCollisionShape()->getAabb(pr->getInterpolationWorldTransform(),mins,maxs);
+ volume=btDbvtVolume::FromMM(mins,maxs);
+ volume.Expand(btVector3(1,1,1)*margin);
+ btDbvt::collideTV(ps->m_cdbvt.m_root,volume,*this);
+ }
+ };
+ //
+ // CollideCL_SS
+ //
+ struct CollideCL_SS : ClusterBase
+ {
+ btSoftBody* bodies[2];
+ void Process(const btDbvtNode* la,const btDbvtNode* lb)
+ {
+ btSoftBody::Cluster* cla=(btSoftBody::Cluster*)la->data;
+ btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data;
+ btSoftClusterCollisionShape csa(cla);
+ btSoftClusterCollisionShape csb(clb);
+ btGjkEpaSolver2::sResults res;
+ if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(),
+ &csb,btTransform::getIdentity(),
+ cla->m_com-clb->m_com,res))
+ {
+ btSoftBody::CJoint joint;
+ if(SolveContact(res,cla,clb,joint))
+ {
+ btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint();
+ *pj=joint;bodies[0]->m_joints.push_back(pj);
+ pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL);
+ pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2;
+ }
+ }
+ }
+ void Process(btSoftBody* psa,btSoftBody* psb)
+ {
+ idt = psa->m_sst.isdt;
+ margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2;
+ friction = btMin(psa->m_cfg.kDF,psb->m_cfg.kDF);
+ bodies[0] = psa;
+ bodies[1] = psb;
+ btDbvt::collideTT(psa->m_cdbvt.m_root,psb->m_cdbvt.m_root,*this);
+ }
+ };
+ //
+ // CollideSDF_RS
+ //
+ struct CollideSDF_RS : btDbvt::ICollide
+ {
+ void Process(const btDbvtNode* leaf)
+ {
+ btSoftBody::Node* node=(btSoftBody::Node*)leaf->data;
+ DoNode(*node);
+ }
+ void DoNode(btSoftBody::Node& n) const
+ {
+ const btScalar m=n.m_im>0?dynmargin:stamargin;
+ btSoftBody::RContact c;
+ if( (!n.m_battach)&&
+ psb->checkContact(prb,n.m_x,m,c.m_cti))
+ {
+ const btScalar ima=n.m_im;
+ const btScalar imb=prb->getInvMass();
+ const btScalar ms=ima+imb;
+ if(ms>0)
+ {
+ const btTransform& wtr=prb->getInterpolationWorldTransform();
+ const btMatrix3x3& iwi=prb->getInvInertiaTensorWorld();
+ const btVector3 ra=n.m_x-wtr.getOrigin();
+ const btVector3 va=prb->getVelocityInLocalPoint(ra)*psb->m_sst.sdt;
+ const btVector3 vb=n.m_x-n.m_q;
+ const btVector3 vr=vb-va;
+ const btScalar dn=dot(vr,c.m_cti.m_normal);
+ const btVector3 fv=vr-c.m_cti.m_normal*dn;
+ const btScalar fc=psb->m_cfg.kDF*prb->getFriction();
+ c.m_node = &n;
+ c.m_c0 = ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra);
+ c.m_c1 = ra;
+ c.m_c2 = ima*psb->m_sst.sdt;
+ c.m_c3 = fv.length2()<(btFabs(dn)*fc)?0:1-fc;
+ c.m_c4 = prb->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR;
+ psb->m_rcontacts.push_back(c);
+ prb->activate();
+ }
+ }
+ }
+ btSoftBody* psb;
+ btRigidBody* prb;
+ btScalar dynmargin;
+ btScalar stamargin;
+ };
+ //
+ // CollideVF_SS
+ //
+ struct CollideVF_SS : btDbvt::ICollide
+ {
+ void Process(const btDbvtNode* lnode,
+ const btDbvtNode* lface)
+ {
+ btSoftBody::Node* node=(btSoftBody::Node*)lnode->data;
+ btSoftBody::Face* face=(btSoftBody::Face*)lface->data;
+ btVector3 o=node->m_x;
+ btVector3 p;
+ btScalar d=SIMD_INFINITY;
+ ProjectOrigin( face->m_n[0]->m_x-o,
+ face->m_n[1]->m_x-o,
+ face->m_n[2]->m_x-o,
+ p,d);
+ const btScalar m=mrg+(o-node->m_q).length()*2;
+ if(d<(m*m))
+ {
+ const btSoftBody::Node* n[]={face->m_n[0],face->m_n[1],face->m_n[2]};
+ const btVector3 w=BaryCoord(n[0]->m_x,n[1]->m_x,n[2]->m_x,p+o);
+ const btScalar ma=node->m_im;
+ btScalar mb=BaryEval(n[0]->m_im,n[1]->m_im,n[2]->m_im,w);
+ if( (n[0]->m_im<=0)||
+ (n[1]->m_im<=0)||
+ (n[2]->m_im<=0))
+ {
+ mb=0;
+ }
+ const btScalar ms=ma+mb;
+ if(ms>0)
+ {
+ btSoftBody::SContact c;
+ c.m_normal = p/-btSqrt(d);
+ c.m_margin = m;
+ c.m_node = node;
+ c.m_face = face;
+ c.m_weights = w;
+ c.m_friction = btMax(psb[0]->m_cfg.kDF,psb[1]->m_cfg.kDF);
+ c.m_cfm[0] = ma/ms*psb[0]->m_cfg.kSHR;
+ c.m_cfm[1] = mb/ms*psb[1]->m_cfg.kSHR;
+ psb[0]->m_scontacts.push_back(c);
+ }
+ }
+ }
+ btSoftBody* psb[2];
+ btScalar mrg;
+ };
+};
+
+#endif //_BT_SOFT_BODY_INTERNALS_H
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp
new file mode 100644
index 00000000000..e62f35567b0
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp
@@ -0,0 +1,108 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btSoftBodyRigidBodyCollisionConfiguration.h"
+#include "btSoftRigidCollisionAlgorithm.h"
+#include "btSoftBodyConcaveCollisionAlgorithm.h"
+#include "btSoftSoftCollisionAlgorithm.h"
+
+#define ENABLE_SOFTBODY_CONCAVE_COLLISIONS 1
+
+btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
+:btDefaultCollisionConfiguration(constructionInfo)
+{
+ void* mem;
+
+ mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc),16);
+ m_softSoftCreateFunc = new(mem) btSoftSoftCollisionAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16);
+ m_softRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16);
+ m_swappedSoftRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc;
+ m_swappedSoftRigidConvexCreateFunc->m_swapped=true;
+
+#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
+ mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16);
+ m_softRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::CreateFunc;
+
+ mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16);
+ m_swappedSoftRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::SwappedCreateFunc;
+ m_swappedSoftRigidConcaveCreateFunc->m_swapped=true;
+#endif
+
+}
+
+btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration()
+{
+ m_softSoftCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_softSoftCreateFunc);
+
+ m_softRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_softRigidConvexCreateFunc);
+
+ m_swappedSoftRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_swappedSoftRigidConvexCreateFunc);
+
+#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
+ m_softRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_softRigidConcaveCreateFunc);
+
+ m_swappedSoftRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+ btAlignedFree( m_swappedSoftRigidConcaveCreateFunc);
+#endif
+}
+
+///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation
+btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
+{
+
+ ///try to handle the softbody interactions first
+
+ if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE ) && (proxyType1==SOFTBODY_SHAPE_PROXYTYPE))
+ {
+ return m_softSoftCreateFunc;
+ }
+
+ ///softbody versus convex
+ if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConvex(proxyType1))
+ {
+ return m_softRigidConvexCreateFunc;
+ }
+
+ ///convex versus soft body
+ if (btBroadphaseProxy::isConvex(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE )
+ {
+ return m_swappedSoftRigidConvexCreateFunc;
+ }
+
+#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
+ ///softbody versus convex
+ if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConcave(proxyType1))
+ {
+ return m_softRigidConcaveCreateFunc;
+ }
+
+ ///convex versus soft body
+ if (btBroadphaseProxy::isConcave(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE )
+ {
+ return m_swappedSoftRigidConcaveCreateFunc;
+ }
+#endif
+
+ ///fallback to the regular rigid collision shape
+ return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1);
+}
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h
new file mode 100644
index 00000000000..41c3af96939
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.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 BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
+#define BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
+
+#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
+
+class btVoronoiSimplexSolver;
+class btGjkEpaPenetrationDepthSolver;
+
+
+///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration
+class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration
+{
+
+ //default CreationFunctions, filling the m_doubleDispatch table
+ btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_softRigidConvexCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc;
+ btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc;
+
+public:
+
+ btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
+
+ virtual ~btSoftBodyRigidBodyCollisionConfiguration();
+
+ ///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation
+ virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
+
+};
+
+#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
+
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
new file mode 100644
index 00000000000..835a03b8e3c
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
@@ -0,0 +1,79 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btSoftRigidCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "btSoftBody.h"
+///TODO: include all the shapes that the softbody can collide with
+///alternatively, implement special case collision algorithms (just like for rigid collision shapes)
+
+//#include <stdio.h>
+
+btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*col0*/,btCollisionObject* /*col1*/, bool isSwapped)
+: btCollisionAlgorithm(ci),
+//m_ownManifold(false),
+//m_manifoldPtr(mf),
+m_isSwapped(isSwapped)
+{
+}
+
+
+btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm()
+{
+
+ //m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject);
+
+ /*if (m_ownManifold)
+ {
+ if (m_manifoldPtr)
+ m_dispatcher->releaseManifold(m_manifoldPtr);
+ }
+ */
+
+}
+
+
+#include <stdio.h>
+
+void btSoftRigidCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+ (void)dispatchInfo;
+ (void)resultOut;
+ //printf("btSoftRigidCollisionAlgorithm\n");
+
+ btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1 : (btSoftBody*)body0;
+ btCollisionObject* rigidCollisionObject = m_isSwapped? body0 : body1;
+
+ softBody->defaultCollisionHandler(rigidCollisionObject);
+
+
+}
+
+btScalar btSoftRigidCollisionAlgorithm::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/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
new file mode 100644
index 00000000000..74327e6c635
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.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 SOFT_RIGID_COLLISION_ALGORITHM_H
+#define SOFT_RIGID_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+
+#include "LinearMath/btVector3.h"
+class btSoftBody;
+
+/// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody
+class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm
+{
+// bool m_ownManifold;
+// btPersistentManifold* m_manifoldPtr;
+
+ btSoftBody* m_softBody;
+ btCollisionObject* m_rigidCollisionObject;
+
+ ///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean
+ bool m_isSwapped;
+
+public:
+
+ btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
+
+ virtual ~btSoftRigidCollisionAlgorithm();
+
+ 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 void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ //we don't add any manifolds
+ }
+
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ {
+ void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm));
+ if (!m_swapped)
+ {
+ return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,false);
+ } else
+ {
+ return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,true);
+ }
+ }
+ };
+
+};
+
+#endif //SOFT_RIGID_COLLISION_ALGORITHM_H
+
+
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
new file mode 100644
index 00000000000..01b9fc0fd35
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
@@ -0,0 +1,126 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "btSoftRigidDynamicsWorld.h"
+#include "LinearMath/btQuickprof.h"
+
+//softbody & helpers
+#include "btSoftBody.h"
+#include "btSoftBodyHelpers.h"
+
+btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
+:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
+{
+m_drawFlags = fDrawFlags::Std;
+m_drawNodeTree = true;
+m_drawFaceTree = false;
+m_drawClusterTree = false;
+}
+
+btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld()
+{
+
+}
+
+void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+ btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep);
+
+ for ( int i=0;i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb= m_softBodies[i];
+
+ psb->predictMotion(timeStep);
+ }
+}
+
+void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep)
+{
+ btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep );
+
+ ///solve soft bodies constraints
+ solveSoftBodiesConstraints();
+
+ ///update soft bodies
+ updateSoftBodies();
+
+}
+
+void btSoftRigidDynamicsWorld::updateSoftBodies()
+{
+ BT_PROFILE("updateSoftBodies");
+
+ for ( int i=0;i<m_softBodies.size();i++)
+ {
+ btSoftBody* psb=(btSoftBody*)m_softBodies[i];
+ psb->integrateMotion();
+ }
+}
+
+void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints()
+{
+ BT_PROFILE("solveSoftConstraints");
+
+ if(m_softBodies.size())
+ {
+ btSoftBody::solveClusters(m_softBodies);
+ }
+
+ for(int i=0;i<m_softBodies.size();++i)
+ {
+ btSoftBody* psb=(btSoftBody*)m_softBodies[i];
+ psb->solveConstraints();
+ }
+}
+
+void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body)
+{
+ m_softBodies.push_back(body);
+
+ btCollisionWorld::addCollisionObject(body,
+ btBroadphaseProxy::DefaultFilter,
+ btBroadphaseProxy::AllFilter);
+
+}
+
+void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body)
+{
+ m_softBodies.remove(body);
+
+ btCollisionWorld::removeCollisionObject(body);
+}
+
+void btSoftRigidDynamicsWorld::debugDrawWorld()
+{
+ btDiscreteDynamicsWorld::debugDrawWorld();
+
+ if (getDebugDrawer())
+ {
+ int i;
+ for ( i=0;i<this->m_softBodies.size();i++)
+ {
+ btSoftBody* psb=(btSoftBody*)this->m_softBodies[i];
+ btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer);
+ btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags);
+ if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+ {
+ if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer);
+ if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer);
+ if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer);
+ }
+ }
+ }
+}
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h
new file mode 100644
index 00000000000..d0010b65aad
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+
+#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H
+#define BT_SOFT_RIGID_DYNAMICS_WORLD_H
+
+class btSoftBody;
+typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
+
+class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld
+{
+
+ btSoftBodyArray m_softBodies;
+ int m_drawFlags;
+ bool m_drawNodeTree;
+ bool m_drawFaceTree;
+ bool m_drawClusterTree;
+
+protected:
+
+ virtual void predictUnconstraintMotion(btScalar timeStep);
+
+ virtual void internalSingleStepSimulation( btScalar timeStep);
+
+ void updateSoftBodies();
+
+ void solveSoftBodiesConstraints();
+
+
+
+public:
+
+ btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+
+ virtual ~btSoftRigidDynamicsWorld();
+
+ virtual void debugDrawWorld();
+
+ void addSoftBody(btSoftBody* body);
+
+ void removeSoftBody(btSoftBody* body);
+
+ int getDrawFlags() const { return(m_drawFlags); }
+ void setDrawFlags(int f) { m_drawFlags=f; }
+
+
+ btSoftBodyArray& getSoftBodyArray()
+ {
+ return m_softBodies;
+ }
+
+ const btSoftBodyArray& getSoftBodyArray() const
+ {
+ return m_softBodies;
+ }
+
+};
+
+#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
new file mode 100644
index 00000000000..85a727944e0
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
@@ -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.
+*/
+
+#include "btSoftSoftCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "btSoftBody.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*obj0*/,btCollisionObject* /*obj1*/)
+: btCollisionAlgorithm(ci)
+//m_ownManifold(false),
+//m_manifoldPtr(mf)
+{
+}
+
+btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm()
+{
+}
+
+void btSoftSoftCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+ btSoftBody* soft0 = (btSoftBody*)body0;
+ btSoftBody* soft1 = (btSoftBody*)body1;
+ soft0->defaultCollisionHandler(soft1);
+}
+
+btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+ //not yet
+ return 1.f;
+}
diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
new file mode 100644
index 00000000000..7ca9c3415c9
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as 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 SOFT_SOFT_COLLISION_ALGORITHM_H
+#define SOFT_SOFT_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+class btSoftBody;
+
+///collision detection between two btSoftBody shapes
+class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm
+{
+ bool m_ownManifold;
+ btPersistentManifold* m_manifoldPtr;
+
+ btSoftBody* m_softBody0;
+ btSoftBody* m_softBody1;
+
+
+public:
+ btSoftSoftCollisionAlgorithm(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 void getAllContactManifolds(btManifoldArray& manifoldArray)
+ {
+ if (m_manifoldPtr && m_ownManifold)
+ manifoldArray.push_back(m_manifoldPtr);
+ }
+
+ btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+ virtual ~btSoftSoftCollisionAlgorithm();
+
+ struct CreateFunc :public btCollisionAlgorithmCreateFunc
+ {
+ virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+ {
+ int bbsize = sizeof(btSoftSoftCollisionAlgorithm);
+ void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+ return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0,body1);
+ }
+ };
+
+};
+
+#endif //SOFT_SOFT_COLLISION_ALGORITHM_H
+
+
diff --git a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h
new file mode 100644
index 00000000000..eafe74be1ae
--- /dev/null
+++ b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h
@@ -0,0 +1,306 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btSparseSdf implementation by Nathanael Presson
+
+#ifndef _14F9D17F_EAE8_4aba_B41C_292DB2AA70F3_
+#define _14F9D17F_EAE8_4aba_B41C_292DB2AA70F3_
+
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+
+// Modified Paul Hsieh hash
+template <const int DWORDLEN>
+unsigned int HsiehHash(const void* pdata)
+ {
+ const unsigned short* data=(const unsigned short*)pdata;
+ unsigned hash=DWORDLEN<<2,tmp;
+ for(int i=0;i<DWORDLEN;++i)
+ {
+ hash += data[0];
+ tmp = (data[1]<<11)^hash;
+ hash = (hash<<16)^tmp;
+ data += 2;
+ hash += hash>>11;
+ }
+ hash^=hash<<3;hash+=hash>>5;
+ hash^=hash<<4;hash+=hash>>17;
+ hash^=hash<<25;hash+=hash>>6;
+ return(hash);
+ }
+
+template <const int CELLSIZE>
+struct btSparseSdf
+ {
+ //
+ // Inner types
+ //
+ struct IntFrac
+ {
+ int b;
+ int i;
+ btScalar f;
+ };
+ struct Cell
+ {
+ btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1];
+ int c[3];
+ int puid;
+ unsigned hash;
+ btCollisionShape* pclient;
+ Cell* next;
+ };
+ //
+ // Fields
+ //
+
+ btAlignedObjectArray<Cell*> cells;
+ btScalar voxelsz;
+ int puid;
+ int ncells;
+ int nprobes;
+ int nqueries;
+
+ //
+ // Methods
+ //
+
+ //
+ void Initialize(int hashsize=2383)
+ {
+ cells.resize(hashsize,0);
+ Reset();
+ }
+ //
+ void Reset()
+ {
+ for(int i=0,ni=cells.size();i<ni;++i)
+ {
+ Cell* pc=cells[i];
+ cells[i]=0;
+ while(pc)
+ {
+ Cell* pn=pc->next;
+ delete pc;
+ pc=pn;
+ }
+ }
+ voxelsz =0.25;
+ puid =0;
+ ncells =0;
+ nprobes =1;
+ nqueries =1;
+ }
+ //
+ void GarbageCollect(int lifetime=256)
+ {
+ const int life=puid-lifetime;
+ for(int i=0;i<cells.size();++i)
+ {
+ Cell*& root=cells[i];
+ Cell* pp=0;
+ Cell* pc=root;
+ while(pc)
+ {
+ Cell* pn=pc->next;
+ if(pc->puid<life)
+ {
+ if(pp) pp->next=pn; else root=pn;
+ delete pc;pc=pp;--ncells;
+ }
+ pp=pc;pc=pn;
+ }
+ }
+ //printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries);
+ nqueries=1;
+ nprobes=1;
+ ++puid; /* TODO: Reset puid's when int range limit is reached */
+ /* else setup a priority list... */
+ }
+ //
+ int RemoveReferences(btCollisionShape* pcs)
+ {
+ int refcount=0;
+ for(int i=0;i<cells.size();++i)
+ {
+ Cell*& root=cells[i];
+ Cell* pp=0;
+ Cell* pc=root;
+ while(pc)
+ {
+ Cell* pn=pc->next;
+ if(pc->pclient==pcs)
+ {
+ if(pp) pp->next=pn; else root=pn;
+ delete pc;pc=pp;++refcount;
+ }
+ pp=pc;pc=pn;
+ }
+ }
+ return(refcount);
+ }
+ //
+ btScalar Evaluate( const btVector3& x,
+ btCollisionShape* shape,
+ btVector3& normal,
+ btScalar margin)
+ {
+ /* Lookup cell */
+ const btVector3 scx=x/voxelsz;
+ const IntFrac ix=Decompose(scx.x());
+ const IntFrac iy=Decompose(scx.y());
+ const IntFrac iz=Decompose(scx.z());
+ const unsigned h=Hash(ix.b,iy.b,iz.b,shape);
+ Cell*& root=cells[static_cast<int>(h%cells.size())];
+ Cell* c=root;
+ ++nqueries;
+ while(c)
+ {
+ ++nprobes;
+ if( (c->hash==h) &&
+ (c->c[0]==ix.b) &&
+ (c->c[1]==iy.b) &&
+ (c->c[2]==iz.b) &&
+ (c->pclient==shape))
+ { break; }
+ else
+ { c=c->next; }
+ }
+ if(!c)
+ {
+ ++nprobes;
+ ++ncells;
+ c=new Cell();
+ c->next=root;root=c;
+ c->pclient=shape;
+ c->hash=h;
+ c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b;
+ BuildCell(*c);
+ }
+ c->puid=puid;
+ /* Extract infos */
+ const int o[]={ ix.i,iy.i,iz.i};
+ const btScalar d[]={ c->d[o[0]+0][o[1]+0][o[2]+0],
+ c->d[o[0]+1][o[1]+0][o[2]+0],
+ c->d[o[0]+1][o[1]+1][o[2]+0],
+ c->d[o[0]+0][o[1]+1][o[2]+0],
+ c->d[o[0]+0][o[1]+0][o[2]+1],
+ c->d[o[0]+1][o[1]+0][o[2]+1],
+ c->d[o[0]+1][o[1]+1][o[2]+1],
+ c->d[o[0]+0][o[1]+1][o[2]+1]};
+ /* Normal */
+ #if 1
+ const btScalar gx[]={ d[1]-d[0],d[2]-d[3],
+ d[5]-d[4],d[6]-d[7]};
+ const btScalar gy[]={ d[3]-d[0],d[2]-d[1],
+ d[7]-d[4],d[6]-d[5]};
+ const btScalar gz[]={ d[4]-d[0],d[5]-d[1],
+ d[7]-d[3],d[6]-d[2]};
+ normal.setX(Lerp( Lerp(gx[0],gx[1],iy.f),
+ Lerp(gx[2],gx[3],iy.f),iz.f));
+ normal.setY(Lerp( Lerp(gy[0],gy[1],ix.f),
+ Lerp(gy[2],gy[3],ix.f),iz.f));
+ normal.setZ(Lerp( Lerp(gz[0],gz[1],ix.f),
+ Lerp(gz[2],gz[3],ix.f),iy.f));
+ normal = normal.normalized();
+ #else
+ normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized();
+ #endif
+ /* Distance */
+ const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f),
+ Lerp(d[3],d[2],ix.f),iy.f);
+ const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f),
+ Lerp(d[7],d[6],ix.f),iy.f);
+ return(Lerp(d0,d1,iz.f)-margin);
+ }
+ //
+ void BuildCell(Cell& c)
+ {
+ const btVector3 org=btVector3( (btScalar)c.c[0],
+ (btScalar)c.c[1],
+ (btScalar)c.c[2]) *
+ CELLSIZE*voxelsz;
+ for(int k=0;k<=CELLSIZE;++k)
+ {
+ const btScalar z=voxelsz*k+org.z();
+ for(int j=0;j<=CELLSIZE;++j)
+ {
+ const btScalar y=voxelsz*j+org.y();
+ for(int i=0;i<=CELLSIZE;++i)
+ {
+ const btScalar x=voxelsz*i+org.x();
+ c.d[i][j][k]=DistanceToShape( btVector3(x,y,z),
+ c.pclient);
+ }
+ }
+ }
+ }
+ //
+ static inline btScalar DistanceToShape(const btVector3& x,
+ btCollisionShape* shape)
+ {
+ btTransform unit;
+ unit.setIdentity();
+ if(shape->isConvex())
+ {
+ btGjkEpaSolver2::sResults res;
+ btConvexShape* csh=static_cast<btConvexShape*>(shape);
+ return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res));
+ }
+ return(0);
+ }
+ //
+ static inline IntFrac Decompose(btScalar x)
+ {
+ /* That one need a lot of improvements... */
+ /* Remove test, faster floor... */
+ IntFrac r;
+ x/=CELLSIZE;
+ const int o=x<0?(int)(-x+1):0;
+ x+=o;r.b=(int)x;
+ const btScalar k=(x-r.b)*CELLSIZE;
+ r.i=(int)k;r.f=k-r.i;r.b-=o;
+ return(r);
+ }
+ //
+ static inline btScalar Lerp(btScalar a,btScalar b,btScalar t)
+ {
+ return(a+(b-a)*t);
+ }
+
+
+
+ //
+ static inline unsigned int Hash(int x,int y,int z,btCollisionShape* shape)
+ {
+ struct btS
+ {
+ int x,y,z;
+ void* p;
+ };
+
+ btS myset;
+
+ myset.x=x;myset.y=y;myset.z=z;myset.p=shape;
+ const void* ptr = &myset;
+
+ unsigned int result = HsiehHash<sizeof(btS)/4> (ptr);
+
+
+ return result;
+ }
+};
+
+
+#endif
diff --git a/extern/bullet2/src/LinearMath/btAabbUtil2.h b/extern/bullet2/src/LinearMath/btAabbUtil2.h
index 429163c8138..8bb6b3af7c3 100644
--- a/extern/bullet2/src/LinearMath/btAabbUtil2.h
+++ b/extern/bullet2/src/LinearMath/btAabbUtil2.h
@@ -18,11 +18,16 @@ 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))
+SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin,
+ btVector3& aabbMax,
+ const btVector3& expansionMin,
+ const btVector3& expansionMax)
+{
+ aabbMin = aabbMin + expansionMin;
+ aabbMax = aabbMax + expansionMax;
+}
/// conservative test for overlap between two aabbs
@@ -67,6 +72,41 @@ SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent)
}
+SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
+ const btVector3& rayInvDirection,
+ const unsigned int raySign[3],
+ const btVector3 bounds[2],
+ btScalar& tmin,
+ btScalar lambda_min,
+ btScalar lambda_max)
+{
+ btScalar tmax, tymin, tymax, tzmin, tzmax;
+ tmin = (bounds[raySign[0]][0] - rayFrom[0]) * rayInvDirection[0];
+ tmax = (bounds[1-raySign[0]][0] - rayFrom[0]) * rayInvDirection[0];
+ tymin = (bounds[raySign[1]][1] - rayFrom[1]) * rayInvDirection[1];
+ tymax = (bounds[1-raySign[1]][1] - rayFrom[1]) * rayInvDirection[1];
+
+ if ( (tmin > tymax) || (tymin > tmax) )
+ return false;
+
+ if (tymin > tmin)
+ tmin = tymin;
+
+ if (tymax < tmax)
+ tmax = tymax;
+
+ tzmin = (bounds[raySign[2]][2] - rayFrom[2]) * rayInvDirection[2];
+ tzmax = (bounds[1-raySign[2]][2] - rayFrom[2]) * rayInvDirection[2];
+
+ if ( (tmin > tzmax) || (tzmin > tmax) )
+ return false;
+ if (tzmin > tmin)
+ tmin = tzmin;
+ if (tzmax < tmax)
+ tmax = tzmax;
+ return ( (tmin < lambda_max) && (tmax > lambda_min) );
+}
+
SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
const btVector3& rayTo,
const btVector3& aabbMin,
@@ -125,3 +165,4 @@ SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
#endif
+
diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp
index 1f5877fa37e..e120289e061 100644
--- a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp
+++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp
@@ -15,56 +15,187 @@ 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)
-
+#if defined (BT_HAS_ALIGNED_ALLOCATOR)
#include <malloc.h>
-void* btAlignedAlloc (int size, int alignment)
+static void *btAlignedAllocDefault(size_t size, int alignment)
{
- return _aligned_malloc(size,alignment);
+ return _aligned_malloc(size, (size_t)alignment);
}
-void btAlignedFree (void* ptr)
+static void btAlignedFreeDefault(void *ptr)
{
_aligned_free(ptr);
}
+#elif defined(__CELLOS_LV2__)
+#include <stdlib.h>
-#else
+static inline void *btAlignedAllocDefault(size_t size, int alignment)
+{
+ return memalign(alignment, size);
+}
-#ifdef __CELLOS_LV2__
+static inline void btAlignedFreeDefault(void *ptr)
+{
+ free(ptr);
+}
+#else
+static inline void *btAlignedAllocDefault(size_t size, int alignment)
+{
+ void *ret;
+ char *real;
+ unsigned long offset;
+
+ 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);
+}
-#include <stdlib.h>
+static inline void btAlignedFreeDefault(void *ptr)
+{
+ void* real;
-int numAllocs = 0;
-int numFree = 0;
+ if (ptr) {
+ real = *((void **)(ptr)-1);
+ free(real);
+ }
+}
+#endif
-void* btAlignedAlloc (int size, int alignment)
+static void *btAllocDefault(size_t size)
{
- numAllocs++;
- return memalign(alignment, size);
+ return malloc(size);
}
-void btAlignedFree (void* ptr)
+static void btFreeDefault(void *ptr)
{
- numFree++;
free(ptr);
}
-#else
-///todo
-///will add some multi-platform version that works without _aligned_malloc/_aligned_free
+static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault;
+static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault;
+static btAllocFunc *sAllocFunc = btAllocDefault;
+static btFreeFunc *sFreeFunc = btFreeDefault;
-void* btAlignedAlloc (int size, int alignment)
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc)
{
- return new char[size];
+ sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
+ sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
}
-void btAlignedFree (void* ptr)
+void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc)
{
- delete [] (char*) ptr;
+ sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
+ sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
}
-#endif //
-#endif
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+//this generic allocator provides the total allocated number of bytes
+#include <stdio.h>
+
+void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename)
+{
+ void *ret;
+ char *real;
+ unsigned long offset;
+
+ gTotalBytesAlignedAllocs += size;
+ gNumAlignedAllocs++;
+
+
+ real = (char *)sAllocFunc(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);//??
+ }
+
+ printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size);
+
+ int* ptr = (int*)ret;
+ *ptr = 12;
+ return (ret);
+}
+
+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 at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size);
+
+ sFreeFunc(real);
+ } else
+ {
+ printf("NULL ptr\n");
+ }
+}
+
+#else //BT_DEBUG_MEMORY_ALLOCATIONS
+
+void* btAlignedAllocInternal (size_t size, int alignment)
+{
+ gNumAlignedAllocs++;
+ void* ptr;
+#if defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__)
+ ptr = sAlignedAllocFunc(size, alignment);
+#else
+ char *real;
+ unsigned long offset;
+
+ real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1));
+ if (real) {
+ offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1);
+ ptr = (void *)((real + sizeof(void *)) + offset);
+ *((void **)(ptr)-1) = (void *)(real);
+ } else {
+ ptr = (void *)(real);
+ }
+#endif // defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__)
+// printf("btAlignedAllocInternal %d, %x\n",size,ptr);
+ return ptr;
+}
+
+void btAlignedFreeInternal (void* ptr)
+{
+ if (!ptr)
+ {
+ return;
+ }
+
+ gNumAlignedFree++;
+// printf("btAlignedFreeInternal %x\n",ptr);
+#if defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__)
+ sAlignedFreeFunc(ptr);
+#else
+ void* real;
+
+ if (ptr) {
+ real = *((void **)(ptr)-1);
+ sFreeFunc(real);
+ }
+#endif // defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__)
+}
+#endif //BT_DEBUG_MEMORY_ALLOCATIONS
diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.h b/extern/bullet2/src/LinearMath/btAlignedAllocator.h
index 07585717f45..a252f324d77 100644
--- a/extern/bullet2/src/LinearMath/btAlignedAllocator.h
+++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.h
@@ -21,15 +21,39 @@ 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;
+typedef void *(btAlignedAllocFunc)(size_t size, int alignment);
+typedef void (btAlignedFreeFunc)(void *memblock);
+typedef void *(btAllocFunc)(size_t size);
+typedef void (btFreeFunc)(void *memblock);
+
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc);
+void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc);
+///The btAlignedAllocator is a portable class for aligned memory allocations.
+///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned.
template < typename T , unsigned Alignment >
class btAlignedAllocator {
diff --git a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h
index 8bef5eb5d06..5598f0d7236 100644
--- a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h
+++ b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h
@@ -39,8 +39,8 @@ subject to the following restrictions:
#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
+///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods
+///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
template <typename T>
//template <class T>
class btAlignedObjectArray
@@ -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;
@@ -242,6 +253,46 @@ class btAlignedObjectArray
}
};
+ template <typename L>
+ void quickSortInternal(L CompareFunc,int lo, int hi)
+ {
+ // lo is the lower index, hi is the upper index
+ // of the region of array a that is to be sorted
+ int i=lo, j=hi;
+ T x=m_data[(lo+hi)/2];
+
+ // partition
+ do
+ {
+ while (CompareFunc(m_data[i],x))
+ i++;
+ while (CompareFunc(x,m_data[j]))
+ j--;
+ if (i<=j)
+ {
+ swap(i,j);
+ i++; j--;
+ }
+ } while (i<=j);
+
+ // recursion
+ if (lo<j)
+ quickSortInternal( CompareFunc, lo, j);
+ if (i<hi)
+ quickSortInternal( CompareFunc, i, hi);
+ }
+
+
+ template <typename L>
+ void quickSort(L CompareFunc)
+ {
+ //don't sort 0 or 1 elements
+ if (size()>1)
+ {
+ quickSortInternal(CompareFunc,0,size()-1);
+ }
+ }
+
///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
template <typename L>
@@ -360,8 +411,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/btDefaultMotionState.h b/extern/bullet2/src/LinearMath/btDefaultMotionState.h
index d4ec8e8879c..d758f77ed81 100644
--- a/extern/bullet2/src/LinearMath/btDefaultMotionState.h
+++ b/extern/bullet2/src/LinearMath/btDefaultMotionState.h
@@ -1,7 +1,7 @@
#ifndef DEFAULT_MOTION_STATE_H
#define DEFAULT_MOTION_STATE_H
-///btDefaultMotionState provides a common implementation to synchronize world transforms with offsets
+///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets.
struct btDefaultMotionState : public btMotionState
{
btTransform m_graphicsWorldTrans;
diff --git a/extern/bullet2/src/LinearMath/btGeometryUtil.cpp b/extern/bullet2/src/LinearMath/btGeometryUtil.cpp
index 3d0fb122a6b..5ac230f712f 100644
--- a/extern/bullet2/src/LinearMath/btGeometryUtil.cpp
+++ b/extern/bullet2/src/LinearMath/btGeometryUtil.cpp
@@ -22,7 +22,12 @@ subject to the following restrictions:
can be used by probes that are checking whether the
library is actually installed.
*/
-extern "C" void btBulletMathProbe () {}
+extern "C"
+{
+ void btBulletMathProbe ();
+
+ void btBulletMathProbe () {}
+}
bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin)
@@ -57,6 +62,8 @@ bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const
return true;
}
+bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations);
+
bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations)
{
int numbrushes = planeEquations.size();
diff --git a/extern/bullet2/src/LinearMath/btGeometryUtil.h b/extern/bullet2/src/LinearMath/btGeometryUtil.h
index 766cd75c383..a4b13b45609 100644
--- a/extern/bullet2/src/LinearMath/btGeometryUtil.h
+++ b/extern/bullet2/src/LinearMath/btGeometryUtil.h
@@ -19,6 +19,7 @@ subject to the following restrictions:
#include "btVector3.h"
#include "btAlignedObjectArray.h"
+///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices.
class btGeometryUtil
{
public:
diff --git a/extern/bullet2/src/LinearMath/btIDebugDraw.h b/extern/bullet2/src/LinearMath/btIDebugDraw.h
index 5f40ca39157..563615a9a32 100644
--- a/extern/bullet2/src/LinearMath/btIDebugDraw.h
+++ b/extern/bullet2/src/LinearMath/btIDebugDraw.h
@@ -31,6 +31,9 @@ DEALINGS IN THE SOFTWARE.
#include "btVector3.h"
+///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
+///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld.
+///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum.
class btIDebugDraw
{
public:
@@ -55,11 +58,24 @@ class btIDebugDraw
virtual ~btIDebugDraw() {};
virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0;
+
+ virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha)
+ {
+ drawTriangle(v0,v1,v2,color,alpha);
+ }
+ virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/)
+ {
+ drawLine(v0,v1,color);
+ drawLine(v1,v2,color);
+ drawLine(v2,v0,color);
+ }
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;
diff --git a/extern/bullet2/src/LinearMath/btMatrix3x3.h b/extern/bullet2/src/LinearMath/btMatrix3x3.h
index 94f53c3c0a5..ca1a801402f 100644
--- a/extern/bullet2/src/LinearMath/btMatrix3x3.h
+++ b/extern/bullet2/src/LinearMath/btMatrix3x3.h
@@ -22,6 +22,9 @@ subject to the following restrictions:
#include "btQuaternion.h"
+
+///The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3.
+///Make sure to only include a pure orthogonal matrix without scaling.
class btMatrix3x3 {
public:
btMatrix3x3 () {}
@@ -356,7 +359,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
@@ -406,5 +409,11 @@ class btMatrix3x3 {
}
*/
+SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+ return ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
+ m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == 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
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 <class T>
-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 <class T>
-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 <class T>
@@ -36,7 +36,7 @@ SIMD_FORCE_INLINE const T& GEN_clamped(const T& a, const T& lb, const T& ub)
}
template <class T>
-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 <class T>
-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/btMotionState.h b/extern/bullet2/src/LinearMath/btMotionState.h
index 1975e5ff900..94318140902 100644
--- a/extern/bullet2/src/LinearMath/btMotionState.h
+++ b/extern/bullet2/src/LinearMath/btMotionState.h
@@ -18,7 +18,7 @@ subject to the following restrictions:
#include "btTransform.h"
-///btMotionState allows the dynamics world to synchronize the updated world transforms with graphics
+///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics
///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation)
class btMotionState
{
diff --git a/extern/bullet2/src/LinearMath/btQuadWord.h b/extern/bullet2/src/LinearMath/btQuadWord.h
index 961ac484d20..2e80fc2ca47 100644
--- a/extern/bullet2/src/LinearMath/btQuadWord.h
+++ b/extern/bullet2/src/LinearMath/btQuadWord.h
@@ -17,19 +17,31 @@ subject to the following restrictions:
#define SIMD_QUADWORD_H
#include "btScalar.h"
+#include "btMinMax.h"
+#include <math.h>
+///The btQuadWordStorage class is base class for btVector3 and btQuaternion.
+///Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword. todo: look into this
+///ATTRIBUTE_ALIGNED16(class) btQuadWordStorage
+class btQuadWordStorage
+{
+protected:
+
+ btScalar m_x;
+ btScalar m_y;
+ btScalar m_z;
+ btScalar m_unusedW;
+
+public:
+
+};
+
///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 +73,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 +103,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..264751b33e7 100644
--- a/extern/bullet2/src/LinearMath/btQuaternion.h
+++ b/extern/bullet2/src/LinearMath/btQuaternion.h
@@ -19,6 +19,7 @@ subject to the following restrictions:
#include "btVector3.h"
+///The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform.
class btQuaternion : public btQuadWord {
public:
btQuaternion() {}
@@ -158,7 +159,7 @@ public:
btQuaternion inverse() const
{
- return btQuaternion(m_x, m_y, m_z, -m_unusedW);
+ return btQuaternion(-m_x, -m_y, -m_z, m_unusedW);
}
SIMD_FORCE_INLINE btQuaternion
@@ -285,7 +286,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 +294,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 +309,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();
@@ -319,3 +320,4 @@ shortestArcQuatNormalize(btVector3& v0,btVector3& v1)
+
diff --git a/extern/bullet2/src/LinearMath/btQuickprof.cpp b/extern/bullet2/src/LinearMath/btQuickprof.cpp
index 37a0c8c3be5..e5b1196149b 100644
--- a/extern/bullet2/src/LinearMath/btQuickprof.cpp
+++ b/extern/bullet2/src/LinearMath/btQuickprof.cpp
@@ -1,38 +1,282 @@
/*
-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:
+/***************************************************************************************************
+**
+** profile.cpp
+**
+** Real-Time Hierarchical Profiling for Game Programming Gems 3
+**
+** by Greg Hjelstrom & Byon Garrabrant
+**
+***************************************************************************************************/
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
+// Credits: The Clock class was inspired by the Timer classes in
+// Ogre (www.ogre3d.org).
-*/
+#include "LinearMath/btQuickprof.h"
-// Please visit the project website (http://quickprof.sourceforge.net)
-// for usage instructions.
+#ifdef USE_BT_CLOCK
-// Credits: The Clock class was inspired by the Timer classes in
-// Ogre (www.ogre3d.org).
+static btClock gProfileClock;
-#include "LinearMath/btQuickprof.h"
+inline void Profile_Get_Ticks(unsigned long int * ticks)
+{
+ *ticks = gProfileClock.getTimeMicroseconds();
+}
+
+inline float Profile_Get_Tick_Rate(void)
+{
+// return 1000000.f;
+ return 1000.f;
+
+}
+
+
+
+/***************************************************************************************************
+**
+** CProfileNode
+**
+***************************************************************************************************/
+
+/***********************************************************************************************
+ * INPUT: *
+ * name - pointer to a static string which is the name of this profile node *
+ * parent - parent pointer *
+ * *
+ * WARNINGS: *
+ * The name is assumed to be a static pointer, only the pointer is stored and compared for *
+ * efficiency reasons. *
+ *=============================================================================================*/
+CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
+ Name( name ),
+ TotalCalls( 0 ),
+ TotalTime( 0 ),
+ StartTime( 0 ),
+ RecursionCounter( 0 ),
+ Parent( parent ),
+ Child( NULL ),
+ Sibling( NULL )
+{
+ Reset();
+}
+
+
+void CProfileNode::CleanupMemory()
+{
+ delete ( Child);
+ Child = NULL;
+ delete ( Sibling);
+ Sibling = NULL;
+}
+
+CProfileNode::~CProfileNode( void )
+{
+ delete ( Child);
+ delete ( Sibling);
+}
+
+
+/***********************************************************************************************
+ * INPUT: *
+ * name - static string pointer to the name of the node we are searching for *
+ * *
+ * WARNINGS: *
+ * All profile names are assumed to be static strings so this function uses pointer compares *
+ * to find the named node. *
+ *=============================================================================================*/
+CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
+{
+ // Try to find this sub node
+ CProfileNode * child = Child;
+ while ( child ) {
+ if ( child->Name == name ) {
+ return child;
+ }
+ child = child->Sibling;
+ }
+
+ // We didn't find it, so add it
+
+ CProfileNode * node = new CProfileNode( name, this );
+ node->Sibling = Child;
+ Child = node;
+ return node;
+}
+
+
+void CProfileNode::Reset( void )
+{
+ TotalCalls = 0;
+ TotalTime = 0.0f;
+ gProfileClock.reset();
+
+ if ( Child ) {
+ Child->Reset();
+ }
+ if ( Sibling ) {
+ Sibling->Reset();
+ }
+}
+
+
+void CProfileNode::Call( void )
+{
+ TotalCalls++;
+ if (RecursionCounter++ == 0) {
+ Profile_Get_Ticks(&StartTime);
+ }
+}
+
+
+bool CProfileNode::Return( void )
+{
+ if ( --RecursionCounter == 0 && TotalCalls != 0 ) {
+ unsigned long int time;
+ Profile_Get_Ticks(&time);
+ time-=StartTime;
+ TotalTime += (float)time / Profile_Get_Tick_Rate();
+ }
+ return ( RecursionCounter == 0 );
+}
+
+
+/***************************************************************************************************
+**
+** CProfileIterator
+**
+***************************************************************************************************/
+CProfileIterator::CProfileIterator( CProfileNode * start )
+{
+ CurrentParent = start;
+ CurrentChild = CurrentParent->Get_Child();
+}
+
+
+void CProfileIterator::First(void)
+{
+ CurrentChild = CurrentParent->Get_Child();
+}
+
+
+void CProfileIterator::Next(void)
+{
+ CurrentChild = CurrentChild->Get_Sibling();
+}
+
+
+bool CProfileIterator::Is_Done(void)
+{
+ return CurrentChild == NULL;
+}
+
+
+void CProfileIterator::Enter_Child( int index )
+{
+ CurrentChild = CurrentParent->Get_Child();
+ while ( (CurrentChild != NULL) && (index != 0) ) {
+ index--;
+ CurrentChild = CurrentChild->Get_Sibling();
+ }
+
+ if ( CurrentChild != NULL ) {
+ CurrentParent = CurrentChild;
+ CurrentChild = CurrentParent->Get_Child();
+ }
+}
+
+
+void CProfileIterator::Enter_Parent( void )
+{
+ if ( CurrentParent->Get_Parent() != NULL ) {
+ CurrentParent = CurrentParent->Get_Parent();
+ }
+ CurrentChild = CurrentParent->Get_Child();
+}
+
+
+/***************************************************************************************************
+**
+** CProfileManager
+**
+***************************************************************************************************/
+
+CProfileNode CProfileManager::Root( "Root", NULL );
+CProfileNode * CProfileManager::CurrentNode = &CProfileManager::Root;
+int CProfileManager::FrameCounter = 0;
+unsigned long int CProfileManager::ResetTime = 0;
+
+
+/***********************************************************************************************
+ * CProfileManager::Start_Profile -- Begin a named profile *
+ * *
+ * Steps one level deeper into the tree, if a child already exists with the specified name *
+ * then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
+ * *
+ * INPUT: *
+ * name - name of this profiling record *
+ * *
+ * WARNINGS: *
+ * The string used is assumed to be a static string; pointer compares are used throughout *
+ * the profiling code for efficiency. *
+ *=============================================================================================*/
+void CProfileManager::Start_Profile( const char * name )
+{
+ if (name != CurrentNode->Get_Name()) {
+ CurrentNode = CurrentNode->Get_Sub_Node( name );
+ }
+
+ CurrentNode->Call();
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Stop_Profile -- Stop timing and record the results. *
+ *=============================================================================================*/
+void CProfileManager::Stop_Profile( void )
+{
+ // Return will indicate whether we should back up to our parent (we may
+ // be profiling a recursive function)
+ if (CurrentNode->Return()) {
+ CurrentNode = CurrentNode->Get_Parent();
+ }
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Reset -- Reset the contents of the profiling system *
+ * *
+ * This resets everything except for the tree structure. All of the timing data is reset. *
+ *=============================================================================================*/
+void CProfileManager::Reset( void )
+{
+ Root.Reset();
+ Root.Call();
+ FrameCounter = 0;
+ Profile_Get_Ticks(&ResetTime);
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Increment_Frame_Counter -- Increment the frame counter *
+ *=============================================================================================*/
+void CProfileManager::Increment_Frame_Counter( void )
+{
+ FrameCounter++;
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
+ *=============================================================================================*/
+float CProfileManager::Get_Time_Since_Reset( void )
+{
+ unsigned long int time;
+ Profile_Get_Ticks(&time);
+ time -= ResetTime;
+ return (float)time / Profile_Get_Tick_Rate();
+}
+
+#endif //USE_BT_CLOCK
-#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<std::string, hidden::ProfileBlock*> 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
index a885967c5fa..b033940ca5c 100644
--- a/extern/bullet2/src/LinearMath/btQuickprof.h
+++ b/extern/bullet2/src/LinearMath/btQuickprof.h
@@ -1,20 +1,11 @@
-/*
-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.
+/***************************************************************************************************
+**
+** Real-Time Hierarchical Profiling for Game Programming Gems 3
+**
+** by Greg Hjelstrom & Byon Garrabrant
+**
+***************************************************************************************************/
// Credits: The Clock class was inspired by the Timer classes in
// Ogre (www.ogre3d.org).
@@ -23,9 +14,10 @@ subject to the following restrictions:
#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.
+#include "LinearMath/btAlignedAllocator.h"
+#include <new>
+//To disable built-in profiling, please comment out next line
+//#define BT_NO_PROFILE 1
//if you don't need btClock, you can comment next line
@@ -34,678 +26,332 @@ subject to the following restrictions:
#ifdef USE_BT_CLOCK
#ifdef __CELLOS_LV2__
#include <sys/sys_time.h>
+#include <sys/time_util.h>
#include <stdio.h>
-typedef uint64_t __int64;
#endif
#if defined (SUNOS) || defined (__SUNOS__)
- #include <stdio.h>
+#include <stdio.h>
#endif
#if defined(WIN32) || defined(_WIN32)
- #define USE_WINDOWS_TIMERS
- #define WIN32_LEAN_AND_MEAN
- #define NOWINRES
- #define NOMCX
- #define NOIME
+#define USE_WINDOWS_TIMERS
+#define WIN32_LEAN_AND_MEAN
+#define NOWINRES
+#define NOMCX
+#define NOIME
#ifdef _XBOX
- #include <Xtl.h>
+#include <Xtl.h>
#else
- #include <windows.h>
+#include <windows.h>
#endif
- #include <time.h>
+#include <time.h>
#else
- #include <sys/time.h>
+#include <sys/time.h>
#endif
#define mymin(a,b) (a > b ? a : b)
-/// basic clock
+///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
class btClock
+{
+public:
+ btClock()
{
- public:
- btClock()
- {
#ifdef USE_WINDOWS_TIMERS
- QueryPerformanceFrequency(&mClockFrequency);
+ QueryPerformanceFrequency(&mClockFrequency);
#endif
- reset();
- }
+ reset();
+ }
- ~btClock()
- {
- }
+ ~btClock()
+ {
+ }
- /// Resets the initial reference time.
- void reset()
- {
+ /// Resets the initial reference time.
+ void reset()
+ {
#ifdef USE_WINDOWS_TIMERS
- QueryPerformanceCounter(&mStartTime);
- mStartTick = GetTickCount();
- mPrevElapsedTime = 0;
+ 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;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+ SYS_TIMEBASE_GET( newTime );
+ mStartTime = newTime;
#else
- gettimeofday(&mStartTime, 0);
+ 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()
- {
+ /// 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(&currentTime);
- LONGLONG elapsedTime = currentTime.QuadPart -
- mStartTime.QuadPart;
-
- // Compute the number of millisecond ticks elapsed.
- unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
+ LARGE_INTEGER currentTime;
+ QueryPerformanceCounter(&currentTime);
+ 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);
+ }
- // 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;
+ // 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;
+ uint64_t freq=sys_time_get_timebase_frequency();
+ double dFreq=((double) freq) / 1000.0;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ SYS_TIMEBASE_GET( newTime );
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+
+ return (unsigned long int)((double(newTime-mStartTime)) / dFreq);
#else
- struct timeval currentTime;
- gettimeofday(&currentTime, 0);
- return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 +
- (currentTime.tv_usec - mStartTime.tv_usec) / 1000;
+ struct timeval currentTime;
+ gettimeofday(&currentTime, 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()
- {
+ /// 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(&currentTime);
- LONGLONG elapsedTime = currentTime.QuadPart -
- mStartTime.QuadPart;
+ LARGE_INTEGER currentTime;
+ QueryPerformanceCounter(&currentTime);
+ 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;
+ }
- // Compute the number of millisecond ticks elapsed.
- unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
- mClockFrequency.QuadPart);
+ // Store the current elapsed time for adjustments next time.
+ mPrevElapsedTime = elapsedTime;
- // 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);
+ // Convert to microseconds.
+ unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime /
+ mClockFrequency.QuadPart);
- return usecTicks;
+ 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;
+ uint64_t freq=sys_time_get_timebase_frequency();
+ double dFreq=((double) freq)/ 1000000.0;
+ typedef uint64_t ClockSize;
+ ClockSize newTime;
+ //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+ SYS_TIMEBASE_GET( newTime );
+
+ return (unsigned long int)((double(newTime-mStartTime)) / dFreq);
#else
- struct timeval currentTime;
- gettimeofday(&currentTime, 0);
- return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 +
- (currentTime.tv_usec - mStartTime.tv_usec);
+ struct timeval currentTime;
+ gettimeofday(&currentTime, 0);
+ return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 +
+ (currentTime.tv_usec - mStartTime.tv_usec);
#endif//__CELLOS_LV2__
#endif
- }
+ }
- private:
+private:
#ifdef USE_WINDOWS_TIMERS
- LARGE_INTEGER mClockFrequency;
- DWORD mStartTick;
- LONGLONG mPrevElapsedTime;
- LARGE_INTEGER mStartTime;
+ LARGE_INTEGER mClockFrequency;
+ DWORD mStartTick;
+ LONGLONG mPrevElapsedTime;
+ LARGE_INTEGER mStartTime;
#else
#ifdef __CELLOS_LV2__
- uint64_t mStartTime;
+ uint64_t mStartTime;
#else
- struct timeval mStartTime;
+ struct timeval mStartTime;
#endif
#endif //__CELLOS_LV2__
- };
+};
#endif //USE_BT_CLOCK
-#ifdef USE_QUICKPROF
-
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <map>
+///A node in the Profile Hierarchy Tree
+class CProfileNode {
+public:
+ CProfileNode( const char * name, CProfileNode * parent );
+ ~CProfileNode( void );
+ CProfileNode * Get_Sub_Node( const char * name );
-namespace hidden
-{
- /// A simple data structure representing a single timed block
- /// of code.
- struct ProfileBlock
- {
- ProfileBlock()
- {
- currentBlockStartMicroseconds = 0;
- currentCycleTotalMicroseconds = 0;
- lastCycleTotalMicroseconds = 0;
- totalMicroseconds = 0;
- }
+ CProfileNode * Get_Parent( void ) { return Parent; }
+ CProfileNode * Get_Sibling( void ) { return Sibling; }
+ CProfileNode * Get_Child( void ) { return Child; }
- /// The starting time (in us) of the current block update.
- unsigned long int currentBlockStartMicroseconds;
+ void CleanupMemory();
+ void Reset( void );
+ void Call( void );
+ bool Return( void );
- /// The accumulated time (in us) spent in this block during the
- /// current profiling cycle.
- unsigned long int currentCycleTotalMicroseconds;
+ const char * Get_Name( void ) { return Name; }
+ int Get_Total_Calls( void ) { return TotalCalls; }
+ float Get_Total_Time( void ) { return TotalTime; }
- /// The accumulated time (in us) spent in this block during the
- /// past profiling cycle.
- unsigned long int lastCycleTotalMicroseconds;
+protected:
- /// The total accumulated time (in us) spent in this block.
- unsigned long int totalMicroseconds;
- };
+ const char * Name;
+ int TotalCalls;
+ float TotalTime;
+ unsigned long int StartTime;
+ int RecursionCounter;
+ CProfileNode * Parent;
+ CProfileNode * Child;
+ CProfileNode * Sibling;
};
-/// A static class that manages timing for a set of profiling blocks.
-class btProfiler
+///An iterator to navigate through the tree
+class CProfileIterator
{
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;
+ // Access all the children of the current parent
+ void First(void);
+ void Next(void);
+ bool Is_Done(void);
+ bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
- /// The clock used to time profile blocks.
- static btClock mClock;
+ void Enter_Child( int index ); // Make the given child the new parent
+ void Enter_Largest_Child( void ); // Make the largest child the new parent
+ void Enter_Parent( void ); // Make the current parent's parent the new parent
- /// The starting time (in us) of the current profiling cycle.
- static unsigned long int mCurrentCycleStartMicroseconds;
+ // Access the current child
+ const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); }
+ int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); }
+ float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); }
- /// The duration (in us) of the most recent profiling cycle.
- static unsigned long int mLastCycleDurationMicroseconds;
+ // Access the current parent
+ const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); }
+ int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); }
+ float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); }
- /// Internal map of named profile blocks.
- static std::map<std::string, hidden::ProfileBlock*> mProfileBlocks;
+protected:
- /// The data file used if this feature is enabled in 'init.'
- static std::ofstream mOutputFile;
+ CProfileNode * CurrentParent;
+ CProfileNode * CurrentChild;
- /// 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;
+ CProfileIterator( CProfileNode * start );
+ friend class CProfileManager;
};
-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;
-}
+///The Manager for the Profile system
+class CProfileManager {
+public:
+ static void Start_Profile( const char * name );
+ static void Stop_Profile( void );
-void btProfiler::endProfilingCycle()
-{
- if (!mEnabled)
+ static void CleanupMemory(void)
{
- return;
+ Root.CleanupMemory();
}
- // Store the duration of the cycle that just finished.
- mLastCycleDurationMicroseconds = mClock.getTimeMicroseconds() -
- mCurrentCycleStartMicroseconds;
+ static void Reset( void );
+ static void Increment_Frame_Counter( void );
+ static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; }
+ static float Get_Time_Since_Reset( void );
- // For each block, update data for the cycle that just finished.
- std::map<std::string, hidden::ProfileBlock*>::iterator iter;
- for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter)
- {
- hidden::ProfileBlock* block = (*iter).second;
- block->lastCycleTotalMicroseconds =
- block->currentCycleTotalMicroseconds;
- block->currentCycleTotalMicroseconds = 0;
+ static CProfileIterator * Get_Iterator( void )
+ {
+
+ return new CProfileIterator( &Root );
}
+ static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); }
- 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 "";
- }
+private:
+ static CProfileNode Root;
+ static CProfileNode * CurrentNode;
+ static int FrameCounter;
+ static unsigned long int ResetTime;
+};
- 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;
+///ProfileSampleClass is a simple way to profile a function's scope
+///Use the BT_PROFILE macro at the start of scope to time
+class CProfileSample {
+public:
+ CProfileSample( const char * name )
+ {
+ CProfileManager::Start_Profile( name );
}
- std::map<std::string, hidden::ProfileBlock*>::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;
+ ~CProfileSample( void )
+ {
+ CProfileManager::Stop_Profile();
}
+};
- return s;
-}
-
+#if !defined(BT_NO_PROFILE)
+#define BT_PROFILE( name ) CProfileSample __profile( name )
+#else
+#define BT_PROFILE( name )
+#endif
-#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/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h
index 01ad93e786a..1fee626d0c0 100644
--- a/extern/bullet2/src/LinearMath/btScalar.h
+++ b/extern/bullet2/src/LinearMath/btScalar.h
@@ -18,25 +18,47 @@ subject to the following restrictions:
#define SIMD___SCALAR_H
#include <math.h>
+#include <stdlib.h>//size_t for MSVC 6.0
#include <cstdlib>
#include <cfloat>
#include <float.h>
+#define BT_BULLET_VERSION 271
+
+inline int btGetVersion()
+{
+ return BT_BULLET_VERSION;
+}
+
+#if defined(DEBUG) || defined (_DEBUG)
+#define BT_DEBUG
+#endif
+
+
#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
- #pragma warning(disable:4530)
- #pragma warning(disable:4996)
- #pragma warning(disable:4786)
+ #define BT_HAS_ALIGNED_ALLOCATOR
+ #pragma warning(disable : 4324) // disable padding warning
+// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
+// #pragma warning(disable:4996) //Turn off warnings about deprecated C routines
+// #pragma warning(disable:4786) // Disable the "debug name too long" warning
+
#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 <ppcintrinsics.h>
+ #define BT_HAVE_NATIVE_FSEL
+ #define btFsel(a,b,c) __fsel((a),(b),(c))
#else
#define BT_USE_SSE
#endif
@@ -46,29 +68,63 @@ 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 <assert.h>
#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 <assert.h>
+ #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 <assert.h>
#endif
#define btAssert assert
//btFullAssert is optional, slows down a lot
#define btFullAssert(x)
+ #define btLikely(_c) _c
+ #define btUnlikely(_c) _c
+
+
+#endif // LIBSPE2
+
#endif //__CELLOS_LV2__
#endif
@@ -81,6 +137,7 @@ subject to the following restrictions:
#endif
#endif
+///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
#if defined(BT_USE_DOUBLE_PRECISION)
typedef double btScalar;
#else
@@ -88,6 +145,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 +170,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 +246,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 +256,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 static_cast<int>((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<typename T> 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 static_cast<unsigned short>(((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 = 0;
+ 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 = 0.0f;
+ 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 = 0.0;
+ 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..050d44bdfe9 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
{
@@ -28,7 +29,7 @@ struct btBlock
unsigned char* address;
};
-///StackAlloc provides some fast stack-based memory allocator (LIFO last-in first-out)
+///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
class btStackAlloc
{
public:
@@ -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 static_cast<int>(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..a8cdb428100 100644
--- a/extern/bullet2/src/LinearMath/btTransform.h
+++ b/extern/bullet2/src/LinearMath/btTransform.h
@@ -21,7 +21,8 @@ subject to the following restrictions:
#include "btMatrix3x3.h"
-///btTransform supports rigid transforms (only translation and rotation, no scaling/shear)
+///The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear.
+///It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes.
class btTransform {
@@ -92,13 +93,7 @@ public:
m_basis.getRotation(q);
return q;
}
- template <typename Scalar2>
- void setValue(const Scalar2 *m)
- {
- m_basis.setValue(m);
- m_origin.setValue(&m[12]);
- }
-
+
void setFromOpenGLMatrix(const btScalar *m)
{
@@ -194,8 +189,13 @@ btTransform::operator*(const btTransform& t) const
{
return btTransform(m_basis * t.m_basis,
(*this)(t.m_origin));
-}
+}
+SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2)
+{
+ return ( t1.getBasis() == t2.getBasis() &&
+ t1.getOrigin() == t2.getOrigin() );
+}
#endif
@@ -204,3 +204,4 @@ btTransform::operator*(const btTransform& t) const
+
diff --git a/extern/bullet2/src/LinearMath/btTransformUtil.h b/extern/bullet2/src/LinearMath/btTransformUtil.h
index bc42fd166b6..86ee1da5edf 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
@@ -70,7 +70,9 @@ public:
predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5));
predictedOrn.normalize();
#else
- //exponential map
+ //Exponential map
+ //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
+
btVector3 axis;
btScalar fAngle = angvel.length();
//limit the angular motion
@@ -121,6 +123,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..96548c6ba60 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)
@@ -43,6 +47,7 @@ public:
SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v)
{
+
m_x += v.x(); m_y += v.y(); m_z += v.z();
return *this;
}
@@ -399,4 +404,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/btBulletCollisionCommon.h b/extern/bullet2/src/btBulletCollisionCommon.h
index 8417ccc671f..b21d8b4f66c 100644
--- a/extern/bullet2/src/btBulletCollisionCommon.h
+++ b/extern/bullet2/src/btBulletCollisionCommon.h
@@ -32,23 +32,26 @@ 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"
#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h"
-
+#include "BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
///Math library & Utils
#include "LinearMath/btQuaternion.h"
diff --git a/extern/bullet2/src/btBulletDynamicsCommon.h b/extern/bullet2/src/btBulletDynamicsCommon.h
index 25f016cba8a..ce9bb1d968b 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"
@@ -27,9 +29,13 @@ subject to the following restrictions:
#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
-
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+///Optional ODE quickstep constraint solver, redistributed under ZLib license
+#include "BulletDynamics/ConstraintSolver/btOdeQuickstepConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btOdeTypedJoint.h"
+
///Vehicle simulation, with wheel contact simulated by raycasts
#include "BulletDynamics/Vehicle/btRaycastVehicle.h"